Skip to content

Commit

Permalink
Pointer (#3210)
Browse files Browse the repository at this point in the history
* overhaul pointer

* fix debug selection on native fullscreen

* fix backwards compat

* fix CI on github actions

* more CI fixes

* D'oh

* doc

* more doc

* more docs
  • Loading branch information
Geokureli authored Jul 10, 2024
1 parent c839af2 commit ad012fa
Show file tree
Hide file tree
Showing 15 changed files with 371 additions and 156 deletions.
317 changes: 214 additions & 103 deletions flixel/input/FlxPointer.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,165 +7,276 @@ import flixel.util.FlxStringUtil;

class FlxPointer
{
/** The position in the world */
public var x(default, null):Int = 0;
/** The position in the world */
public var y(default, null):Int = 0;

/** The world position relative to the main camera's scroll position */
@:deprecated("screenX is deprecated, use viewX, instead")
public var screenX(default, never):Int = 0;
/** The world position relative to the main camera's scroll position */
@:deprecated("screenY is deprecated, use viewY, instead")
public var screenY(default, never):Int = 0;

/**
* The world position relative to the main camera's scroll position, `cam.viewMarginX` or
* `cam.viewMarginLeft` is the left edge of the camera and `cam.viewMarginRight` is the right
*
* @since 5.9.0
*/
public var viewX(default, null):Int = 0;
/**
* The world position relative to the main camera's scroll position, `cam.viewMarginY` or
* `cam.viewMarginTop` is the top edge of the camera and `cam.viewMarginBottom` is the bottom
*
* @since 5.9.0
*/
public var viewY(default, null):Int = 0;

/**
* The position relative to the `FlxGame`'s position in the window,
* where `0` is the left edge of the game and `FlxG.width` is the right
*
* @since 5.9.0
*/
public var gameX(default, null):Int = 0;
/**
* The position relative to the `FlxGame`'s position in the window,
* where `0` is the top edge of the game and `FlxG.height` is the bottom
*
* @since 5.9.0
*/
public var gameY(default, null):Int = 0;

public var screenX(default, null):Int = 0;
public var screenY(default, null):Int = 0;

var _globalScreenX:Int = 0;
var _globalScreenY:Int = 0;
@:deprecated("_globalScreenX is deprecated, use gameX, instead") // 5.9.0
var _globalScreenX(get, set):Int;
@:deprecated("_globalScreenY is deprecated, use gameY, instead") // 5.9.0
var _globalScreenY(get, set):Int;

var _rawX(default, null):Float = 0;
var _rawY(default, null):Float = 0;

static var _cachedPoint:FlxPoint = new FlxPoint();

public function new() {}

/**
* Fetch the world position of the pointer on any given camera.
* NOTE: x and y also store the world position of the pointer on the main camera.
* Fetch the world position of the pointer on any given camera
*
* **Note:** Fields `x` and `y` also store this result
*
* @param Camera If unspecified, first/main global camera is used instead.
* @param point An existing point object to store the results (if you don't want a new one created).
* @return The touch point's location in world space.
* @param camera If unspecified, `FlxG.camera` is used, instead
* @param result An existing point to store the results, if unspecified, one is created
*/
public function getWorldPosition(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint
public function getWorldPosition(?camera:FlxCamera, ?result:FlxPoint):FlxPoint
{
if (Camera == null)
{
Camera = FlxG.camera;
}
if (point == null)
{
point = FlxPoint.get();
}
getScreenPosition(Camera, _cachedPoint);
point.x = _cachedPoint.x + Camera.scroll.x;
point.y = _cachedPoint.y + Camera.scroll.y;
return point;
if (camera == null)
camera = FlxG.camera;

getViewPosition(camera, result);
result.addPoint(camera.scroll);
return result;
}

/**
* Fetch the screen position of the pointer on any given camera.
* NOTE: screenX and screenY also store the screen position of the pointer on the main camera.
*
* @param Camera If unspecified, first/main global camera is used instead.
* @param point An existing point object to store the results (if you don't want a new one created).
* @return The touch point's location in screen space.
* The position relative to the game's position in the window, where `(0, 0)` is the
* top-left edge of the game and `(FlxG.width, FlxG.height)` is the bottom-right
*
* **Note:** Fields `gameX` and `gameY` also store this result
*
* @param result An existing point to store the results, if unspecified, one is created
* @since 5.9.0
*/
public function getScreenPosition(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint
public function getGamePosition(?result:FlxPoint):FlxPoint
{
if (Camera == null)
{
Camera = FlxG.camera;
}
if (point == null)
{
point = FlxPoint.get();
}

point.x = (_globalScreenX - Camera.x + 0.5 * Camera.width * (Camera.zoom - Camera.initialZoom)) / Camera.zoom;
point.y = (_globalScreenY - Camera.y + 0.5 * Camera.height * (Camera.zoom - Camera.initialZoom)) / Camera.zoom;

return point;
if (result == null)
return FlxPoint.get();

return result.set(Std.int(_rawX), Std.int(_rawY));
}

/**
* Fetch the screen position of the pointer relative to given camera's viewport.
* Fetch the world position relative to the main camera's `scroll` position, where
* `(cam.viewMarginLeft, cam.viewMarginTop)` is the top-left of the camera and
* `(cam.viewMarginRight, cam.viewMarginBottom)` is the bottom right
*
* **Note:** Fields `viewX` and `viewY` also store this result
*
* @param Camera If unspecified, first/main global camera is used instead.
* @param point An existing point object to store the results (if you don't want a new one created).
* @return The touch point's location relative to camera's viewport.
* @param camera If unspecified, `FlxG.camera` is used, instead
* @param result An existing point to store the results, if unspecified, one is created
*/
@:access(flixel.FlxCamera)
public function getPositionInCameraView(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint
public function getViewPosition(?camera:FlxCamera, ?result:FlxPoint):FlxPoint
{
if (Camera == null)
Camera = FlxG.camera;

if (point == null)
point = FlxPoint.get();

point.x = (_globalScreenX - Camera.x) / Camera.zoom + Camera.viewMarginX;
point.y = (_globalScreenY - Camera.y) / Camera.zoom + Camera.viewMarginY;

return point;
if (camera == null)
camera = FlxG.camera;
if (result == null)
result = FlxPoint.get();
result.x = Std.int((gameX - camera.x) / camera.zoom + camera.viewMarginX);
result.y = Std.int((gameY - camera.y) / camera.zoom + camera.viewMarginY);
return result;
}


/**
* Fetch the position of the pointer relative to given camera's `scroll` position, where
* `(cam.viewMarginLeft, cam.viewMarginTop)` is the top-left of the camera and
* `(cam.viewMarginRight, cam.viewMarginBottom)` is the bottom right of the camera
*
* **Note:** Fields `viewX` and `viewY` also store this result for `FlxG.camera`
*
* @param camera If unspecified, `FlxG.camera` is used, instead
* @param result An existing point to store the results, if unspecified, one is created
*/
@:deprecated("getScreenPosition is deprecated, use getViewPosition, instead") // 5.9.0
public function getScreenPosition(?camera:FlxCamera, ?result:FlxPoint):FlxPoint
{
if (camera == null)
camera = FlxG.camera;

if (result == null)
result = FlxPoint.get();

result.x = (gameX - camera.x + 0.5 * camera.width * (camera.zoom - camera.initialZoom)) / camera.zoom;
result.y = (gameY - camera.y + 0.5 * camera.height * (camera.zoom - camera.initialZoom)) / camera.zoom;

return result;
}

/**
* Fetch the position of the pointer relative to given camera's `scroll` position, where
* `(cam.viewMarginLeft, cam.viewMarginTop)` is the top-left of the camera and
* `(cam.viewMarginRight, cam.viewMarginBottom)` is the bottom right of the camera
*
* **Note:** Fields `viewX` and `viewY` also store this result for `FlxG.camera`
*
* @param camera If unspecified, `FlxG.camera` is used, instead.
* @param result An existing point to store the results, if unspecified, one is created
* @return The pointer's location relative to camera's viewport.
*/
@:deprecated("getPositionInCameraView is deprecated, use getViewPosition, instead") // 5.9.0
public function getPositionInCameraView(?camera:FlxCamera, ?result:FlxPoint):FlxPoint
{
if (camera == null)
camera = FlxG.camera;

if (result == null)
result = FlxPoint.get();

result.x = (gameX - camera.x) / camera.zoom + camera.viewMarginX;
result.y = (gameY - camera.y) / camera.zoom + camera.viewMarginY;

return result;
}

/**
* Returns a FlxPoint with this input's x and y.
*/
public function getPosition(?point:FlxPoint):FlxPoint
public function getPosition(?result:FlxPoint):FlxPoint
{
if (point == null)
point = FlxPoint.get();
return point.set(x, y);
if (result == null)
return FlxPoint.get(x, y);

return result.set(x, y);
}

/**
* Checks to see if some FlxObject overlaps this FlxObject or FlxGroup.
* If the group has a LOT of things in it, it might be faster to use FlxG.overlaps().
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
* Checks to see if this pointer overlaps some `FlxObject` or `FlxGroup`.
*
* @param ObjectOrGroup The object or group being tested.
* @param Camera Specify which game camera you want. If null getScreenPosition() will just grab the first global camera.
* @return Whether or not the two objects overlap.
* @param objectOrGroup The object or group being tested
* @param camera Helps determine the world position. If unspecified, `FlxG.camera` is used
*/
@:access(flixel.group.FlxTypedGroup.resolveGroup)
public function overlaps(ObjectOrGroup:FlxBasic, ?Camera:FlxCamera):Bool
public function overlaps(objectOrGroup:FlxBasic, ?camera:FlxCamera):Bool
{
var result:Bool = false;

var group = FlxTypedGroup.resolveGroup(ObjectOrGroup);
// check group
final group = FlxTypedGroup.resolveGroup(objectOrGroup);
if (group != null)
{
group.forEachExists(function(basic:FlxBasic)
for (basic in group.members)
{
if (overlaps(basic, Camera))
if (basic != null && overlaps(basic, camera))
{
result = true;
return;
return true;
}
});
}
else
{
getWorldPosition(Camera, _cachedPoint);
var object:FlxObject = cast ObjectOrGroup;
result = object.overlapsPoint(_cachedPoint, true, Camera);
}
return false;
}

return result;
// check object
getWorldPosition(camera, _cachedPoint);
final object = cast (objectOrGroup, FlxObject);
return object.overlapsPoint(_cachedPoint, true, camera);
}

/**
* Directly set the underyling screen position variable. WARNING! You should never use
* this unless you are trying to manually dispatch low-level mouse / touch events to the stage.
*/
@:deprecated("setGlobalScreenPositionUnsafe is deprecated, use setRawPositionUnsafe, instead")
public inline function setGlobalScreenPositionUnsafe(newX:Float, newY:Float):Void
{
_globalScreenX = Std.int(newX / FlxG.scaleMode.scale.x);
_globalScreenY = Std.int(newY / FlxG.scaleMode.scale.y);

updatePositions();
setRawPositionUnsafe(newX, newY);
}

public function toString():String

/**
* Directly set the underyling position variable. WARNING! You should never use
* this unless you are trying to manually dispatch low-level mouse / touch events to the stage.
* @since 5.9.0
*/
@:haxe.warning("-WDeprecated")
public function setRawPositionUnsafe(x:Float, y:Float)
{
return FlxStringUtil.getDebugString([LabelValuePair.weak("x", x), LabelValuePair.weak("y", y)]);
_rawX = x / FlxG.scaleMode.scale.x;
_rawY = y / FlxG.scaleMode.scale.y;

updatePositions();
}

/**
* Helper function to update the cursor used by update() and playback().
* Updates the x, y, screenX, and screenY variables based on the default camera.
*/
function updatePositions():Void
{
getScreenPosition(FlxG.camera, _cachedPoint);
screenX = Std.int(_cachedPoint.x);
screenY = Std.int(_cachedPoint.y);

getGamePosition(_cachedPoint);
gameX = Std.int(_cachedPoint.x);
gameY = Std.int(_cachedPoint.y);

getViewPosition(FlxG.camera, _cachedPoint);
viewX = Std.int(_cachedPoint.x);
viewY = Std.int(_cachedPoint.y);

getWorldPosition(FlxG.camera, _cachedPoint);
x = Std.int(_cachedPoint.x);
y = Std.int(_cachedPoint.y);
}

public function toString():String
{
return FlxStringUtil.getDebugString([LabelValuePair.weak("x", x), LabelValuePair.weak("y", y)]);
}

inline function get__globalScreenX():Int
{
return gameX;
}

inline function get__globalScreenY():Int
{
return gameY;
}

inline function set__globalScreenX(value:Int):Int
{
_rawX = value * FlxG.scaleMode.scale.x;
return value;
}

inline function set__globalScreenY(value:Int):Int
{
_rawY = value * FlxG.scaleMode.scale.y;
return value;
}
}
Loading

0 comments on commit ad012fa

Please sign in to comment.