diff --git a/Editor/AGS.Editor/Resources/agsdefns.sh b/Editor/AGS.Editor/Resources/agsdefns.sh index c72967ce78e..a5120748663 100644 --- a/Editor/AGS.Editor/Resources/agsdefns.sh +++ b/Editor/AGS.Editor/Resources/agsdefns.sh @@ -366,6 +366,13 @@ managed struct Point { }; #endif +#ifdef SCRIPT_API_v400 +managed struct TouchPoint { + int ID, X, Y; + bool IsDown; +}; +#endif + #define CHARID int // $AUTOCOMPLETEIGNORE$ builtin struct ColorType { char r,g,b; @@ -2752,8 +2759,12 @@ builtin managed struct VideoPlayer { /// The volume of this video's sound, from 0 to 100. import attribute int Volume; }; -#endif +builtin struct Touch { + /// Returns array of touch points + import static TouchPoint*[] GetTouchPoints(); // $AUTOCOMPLETESTATICONLY$ +}; +#endif import ColorType palette[PALETTE_SIZE]; import Mouse mouse; diff --git a/Engine/CMakeLists.txt b/Engine/CMakeLists.txt index 3f5d1f1678a..d6a0be4124a 100644 --- a/Engine/CMakeLists.txt +++ b/Engine/CMakeLists.txt @@ -207,6 +207,8 @@ target_sources(engine ac/parser.cpp ac/parser.h ac/path_helper.h + ac/touch.cpp + ac/touch.h ac/properties.cpp ac/properties.h ac/region.cpp diff --git a/Engine/ac/dynobj/scriptuserobject.cpp b/Engine/ac/dynobj/scriptuserobject.cpp index 8ce4e293ea3..24c9a8076f9 100644 --- a/Engine/ac/dynobj/scriptuserobject.cpp +++ b/Engine/ac/dynobj/scriptuserobject.cpp @@ -126,3 +126,15 @@ ScriptUserObject *ScriptStructHelpers::CreatePoint(int x, int y) ref.Mgr->WriteInt32(ref.Obj, sizeof(int32_t), y); return static_cast(ref.Obj); } + +// Allocates managed struct containing four ints: ID, X, Y and Up/Down state +DynObjectRef ScriptStructHelpers::CreateTouchPointRef(int id, int x, int y, int down) +{ + // FIXME: type id! (is it possible to RTTI?) + DynObjectRef ref = ScriptUserObject::Create(RTTI::NoType, sizeof(int32_t) * 4); + ref.Mgr->WriteInt32(ref.Obj, 0, id); + ref.Mgr->WriteInt32(ref.Obj, sizeof(int32_t), x); + ref.Mgr->WriteInt32(ref.Obj, sizeof(int32_t)*2, y); + ref.Mgr->WriteInt32(ref.Obj, sizeof(int32_t)*3, down); + return ref; +} diff --git a/Engine/ac/dynobj/scriptuserobject.h b/Engine/ac/dynobj/scriptuserobject.h index 7243cc13225..324c8b88dd9 100644 --- a/Engine/ac/dynobj/scriptuserobject.h +++ b/Engine/ac/dynobj/scriptuserobject.h @@ -88,6 +88,7 @@ namespace ScriptStructHelpers { // Creates a managed Point object, represented as a pair of X and Y coordinates. ScriptUserObject *CreatePoint(int x, int y); + DynObjectRef CreateTouchPointRef(int id, int x, int y, int down); }; #endif // __AGS_EE_DYNOBJ__SCRIPTUSERSTRUCT_H diff --git a/Engine/ac/sys_events.cpp b/Engine/ac/sys_events.cpp index 70f67a5d8ad..67d4b4fc685 100644 --- a/Engine/ac/sys_events.cpp +++ b/Engine/ac/sys_events.cpp @@ -19,11 +19,13 @@ #include "core/platform.h" #include "ac/common.h" #include "ac/gamesetup.h" +#include "ac/gamestate.h" #include "ac/joystick.h" #include "ac/gamesetupstruct.h" #include "ac/keycode.h" #include "ac/mouse.h" #include "ac/timer.h" +#include "ac/touch.h" #include "device/mousew32.h" #include "gfx/graphicsdriver.h" #include "platform/base/agsplatformdriver.h" @@ -561,7 +563,7 @@ int ags_check_mouse_wheel() struct Fingers { public: - static const int MAX_FINGERS = 2; + static const int MAX_FINGERS = 10; static const int NO_INDEX = -1; // store fingerId, return given finger index @@ -786,6 +788,29 @@ static void sync_sys_mouse_pos() } } +// get finger position for pointer +static Point get_touch_to_pointer_pos(float x, float y) { + const int iw = gfxDriver->GetDisplayMode().Width; + const int ih = gfxDriver->GetDisplayMode().Height; + const float w = static_cast(iw); + const float h = static_cast(ih); + // Save real touch pos + + const int x_real = AGSMath::Clamp(static_cast(std::roundf(x * w)), 0, iw-1); + const int y_real = AGSMath::Clamp(static_cast(std::roundf(y * h)),0, ih-1); + + const Rect bounds = GameScaling.ScaleRange(play.GetMainViewport()); + + const int x_real_bounded = Math::Clamp(x_real, bounds.Left, bounds.Right); + const int y_real_bounded = Math::Clamp(y_real, bounds.Top, bounds.Bottom); + + // duplicating code from Mouse::WindowToGame + const int p_x = GameScaling.X.UnScalePt(x_real_bounded) - play.GetMainViewport().Left; + const int p_y = GameScaling.Y.UnScalePt(y_real_bounded) - play.GetMainViewport().Top; + + return Point(p_x, p_y); +} + static void on_sdl_touch_down(const SDL_TouchFingerEvent &event) { int finger_index = touch.fingers.push(event.fingerId); @@ -794,6 +819,8 @@ static void on_sdl_touch_down(const SDL_TouchFingerEvent &event) touch.fingers_down |= 1 << finger_index; detect_double_tap(event, true); + on_touch_pointer_down(finger_index, get_touch_to_pointer_pos(event.x, event.y)); + switch (t2m.mode) { case kTouchMouse_OneFingerDrag: @@ -858,6 +885,8 @@ static void on_sdl_touch_up(const SDL_TouchFingerEvent &event) touch.fingers_down &= ~(1 << finger_index); detect_double_tap(event, false); + on_touch_pointer_up(finger_index, get_touch_to_pointer_pos(event.x, event.y)); + switch (t2m.mode) { case kTouchMouse_OneFingerDrag: @@ -914,6 +943,8 @@ static void on_sdl_touch_motion(const SDL_TouchFingerEvent &event) int finger_index = touch.fingers.get_index(event.fingerId); if(finger_index == Fingers::NO_INDEX) return; + on_touch_pointer_motion(finger_index, get_touch_to_pointer_pos(event.x, event.y)); + switch (t2m.mode) { case kTouchMouse_OneFingerDrag: diff --git a/Engine/ac/touch.cpp b/Engine/ac/touch.cpp new file mode 100644 index 00000000000..b172de6fab2 --- /dev/null +++ b/Engine/ac/touch.cpp @@ -0,0 +1,106 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-2024 various contributors +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// https://opensource.org/license/artistic-2-0/ +// +//============================================================================= + +#include +#include "ac/dynobj/scriptuserobject.h" +#include "ac/dynobj/cc_dynamicarray.h" +#include "device/mousew32.h" +#include "touch.h" +#include "ac/common.h" + +enum class touch_state { + up, + motion, + down +}; + +struct touch_point { + int x; + int y; + bool down; +}; + +struct tp { + static const int MAX_POINTERS = 10; + int point_count = 0; + std::array touch_points = {}; +} _tp; + +void on_touch_pointer(int pointer_id, Point position, touch_state state) +{ + _tp.point_count = std::max(pointer_id+1, _tp.point_count); + _tp.touch_points[pointer_id].x = position.X; + _tp.touch_points[pointer_id].y = position.Y; + _tp.touch_points[pointer_id].down = state != touch_state::up; +} + +void on_touch_pointer_down(int pointer_id, Point position) +{ + on_touch_pointer(pointer_id, position, touch_state::down); +} + +void on_touch_pointer_motion(int pointer_id, Point position) +{ + on_touch_pointer(pointer_id, position, touch_state::motion); +} + +void on_touch_pointer_up(int pointer_id, Point position) +{ + on_touch_pointer(pointer_id, position, touch_state::up); +} + +DynObjectRef create_touchpoint(int n) +{ + if (n < 0 || n >= tp::MAX_POINTERS) + quit("!Touch: invalid index for touchpoint"); + + touch_point p = _tp.touch_points[n]; + return ScriptStructHelpers::CreateTouchPointRef(n, p.x, p.y, p.down); +} + +void* Touch_GetTouchPoints() +{ + std::vector objs{}; + + for(int i=0; i< _tp.point_count; i++){ + objs.push_back(create_touchpoint(i)); + } + + DynObjectRef arr = DynamicArrayHelpers::CreateScriptArray(std::move(objs)); + return arr.Obj; +} + +//============================================================================= +// +// Script API Functions +// +//============================================================================= + +#include "script/script_api.h" +#include "script/script_runtime.h" + +// Point*[] () +RuntimeScriptValue Sc_Touch_GetTouchPoints(const RuntimeScriptValue *params, int32_t param_count) +{ + API_SCALL_OBJ(ScriptUserObject, globalDynamicArray, Touch_GetTouchPoints); +} + +void RegisterTouchAPI() +{ + ScFnRegister touch_api[] = { + { "Touch::GetTouchPoints^0", API_FN_PAIR(Touch_GetTouchPoints) }, + }; + + ccAddExternalFunctions(touch_api); +} diff --git a/Engine/ac/touch.h b/Engine/ac/touch.h new file mode 100644 index 00000000000..5b0b94e9d03 --- /dev/null +++ b/Engine/ac/touch.h @@ -0,0 +1,24 @@ +//============================================================================= +// +// Adventure Game Studio (AGS) +// +// Copyright (C) 1999-2011 Chris Jones and 2011-2024 various contributors +// The full list of copyright holders can be found in the Copyright.txt +// file, which is part of this source code distribution. +// +// The AGS source code is provided under the Artistic License 2.0. +// A copy of this license can be found in the file License.txt and at +// https://opensource.org/license/artistic-2-0/ +// +//============================================================================= +#ifndef __AGS_EE_AC_TOUCH_H +#define __AGS_EE_AC_TOUCH_H + +#include "util/geometry.h" + +void on_touch_pointer_down(int pointer_id, Point position); +void on_touch_pointer_motion(int pointer_id, Point position); +void on_touch_pointer_up(int pointer_id, Point position); + + +#endif //__AGS_EE_AC_TOUCH_H diff --git a/Engine/script/exports.cpp b/Engine/script/exports.cpp index c5d3c01fb31..1fbad4edc55 100644 --- a/Engine/script/exports.cpp +++ b/Engine/script/exports.cpp @@ -45,6 +45,7 @@ extern void RegisterMouseAPI(); extern void RegisterObjectAPI(); extern void RegisterOverlayAPI(); extern void RegisterParserAPI(); +extern void RegisterTouchAPI(); extern void RegisterRegionAPI(); extern void RegisterRoomAPI(); extern void RegisterScreenAPI(); @@ -90,6 +91,7 @@ void setup_script_exports(ScriptAPIVersion base_api, ScriptAPIVersion compat_api RegisterObjectAPI(); RegisterOverlayAPI(); RegisterParserAPI(); + RegisterTouchAPI(); RegisterRegionAPI(); RegisterRoomAPI(); RegisterScreenAPI(); diff --git a/Solutions/Engine.App/Engine.App.vcxproj b/Solutions/Engine.App/Engine.App.vcxproj index 65980c37fc3..e21d26ca6dc 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj +++ b/Solutions/Engine.App/Engine.App.vcxproj @@ -545,6 +545,7 @@ + @@ -791,6 +792,7 @@ + diff --git a/Solutions/Engine.App/Engine.App.vcxproj.filters b/Solutions/Engine.App/Engine.App.vcxproj.filters index a14db65e30b..8c4858b3a5e 100644 --- a/Solutions/Engine.App/Engine.App.vcxproj.filters +++ b/Solutions/Engine.App/Engine.App.vcxproj.filters @@ -324,6 +324,9 @@ Source Files\ac + + Source Files\ac + Source Files\ac @@ -947,6 +950,9 @@ Header Files\ac + + Header Files\ac + Header Files\ac