extends Node2D var spaceState:World2D var query : PhysicsPointQueryParameters2D var CastResult : Array var hoveredColliders : Array var hoveredCollider:CollisionObject2D var hoveredStickerNode:Sticker var grabbedStickerNode:Sticker var grabbedStickerOffset:Vector2 enum CURSOR_STATE {DEFAULT, CLICK, GRAB, GRABBED} var currentCursorState:CURSOR_STATE = CURSOR_STATE.DEFAULT var oldCursorState:CURSOR_STATE = CURSOR_STATE.DEFAULT var cursorPlaying:bool # Called when the node enters the scene tree for the first time. func _ready(): if not OS.is_debug_build(): Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED_HIDDEN) query = PhysicsPointQueryParameters2D.new() spaceState = get_world_2d() # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta): #region Cursor Position position = get_global_mouse_position() #endregion pointcast() cursor_look() if (grabbedStickerNode != null): grabbedStickerNode.get_parent().position = grabbedStickerOffset+get_global_mouse_position() func pointcast(): resetCast() query.collide_with_areas = true query.collide_with_bodies = false query.position = get_global_mouse_position() CastResult = spaceState.direct_space_state.intersect_point(query) # CastResult is not reliable. Objects are added randomly in the array # so we need to filter/sort the trace result if ( CastResult.size() > 0 and (grabbedStickerNode == null)): #region Fill hoveredColliders for _object in CastResult: if(_object.collider.input_pickable == true): hoveredColliders.append(_object.collider) #endregion if (hoveredColliders.size() > 0): if (hoveredColliders.size() >= 2): hoveredColliders = sortByPosY(hoveredColliders,false) if (hoveredColliders[0] != hoveredCollider): $GrabTimer.stop() if (hoveredCollider and hoveredCollider.has_method("on_unhover")): hoveredCollider.on_unhover() hoveredCollider = hoveredColliders[0] if (hoveredCollider and hoveredCollider.has_method("on_hover")): hoveredCollider.on_hover() print("Current hovered object :", hoveredCollider) if (Global.isSticker(hoveredCollider)): hoveredStickerNode = hoveredCollider print("Current hovered sticker :", hoveredStickerNode) else: hoveredStickerNode = null else: resetCast(true) else: resetCast(true) func resetCast(bFull = false): CastResult.clear() hoveredColliders.clear() if bFull: if (hoveredCollider != null and hoveredCollider.has_method("on_unhover") and (hoveredCollider != grabbedStickerNode)): hoveredCollider.on_unhover() hoveredCollider = null hoveredStickerNode = null ## Sort objects by parent's Y position func sortByPosY(objects: Array, ascending_order: bool = true): var _tempArray :Array var _tempStickerArray :Array _tempArray = objects #filter stickers for _collider in _tempArray: if _collider is Sticker: _tempStickerArray.append(_collider) if _tempStickerArray.size() > 0: _tempStickerArray.sort_custom(compareNodeOrder) _tempArray = _tempStickerArray else: _tempArray.sort_custom(comparePosY) # Reverse if descending order is required if not ascending_order: _tempArray.reverse() return _tempArray func compareNodeOrder(a, b): return a.get_parent().get_index() < b.get_parent().get_index() func comparePosY(a, b): #print("Compare ",a," at ",a.position.y, " and ",b," at ",b.position.y ) return a.get_parent().position.y < b.get_parent().position.y #Sticker are always at 0, so we need parent position func _input(rawInputEvent:InputEvent): if (rawInputEvent.is_action_pressed("select")): cursorClick() $GrabTimer.start() if (rawInputEvent.is_action_released("select")): $GrabTimer.stop() if (grabbedStickerNode != null): grab_end() func grab_start(): if (hoveredStickerNode and grabbedStickerNode == null): grabbedStickerNode = hoveredStickerNode print("Grabbed ", grabbedStickerNode) grabbedStickerOffset = grabbedStickerNode.get_parent().position - get_global_mouse_position() print("offset =", grabbedStickerOffset, " Stickpos:",grabbedStickerNode.get_parent().position,"-",get_global_mouse_position() ) if (grabbedStickerNode.has_method("on_grab")): grabbedStickerNode.on_grab(grabbedStickerOffset) func grab_end(): if (grabbedStickerNode.has_method("on_released")): grabbedStickerNode.on_unhover() grabbedStickerNode.on_released() print("stopg grabbin at ",query.position ) DebugDraw.points.append(query.position) DebugDraw.drawPoints() grabbedStickerNode = null func cursorClick(): if (hoveredCollider and hoveredCollider.has_method("on_click")): hoveredCollider.on_click() func cursor_look(): if (grabbedStickerNode ): currentCursorState = CURSOR_STATE.GRABBED elif (hoveredStickerNode): if ($GrabTimer and !($GrabTimer.is_stopped())): currentCursorState = CURSOR_STATE.GRABBED else: currentCursorState = CURSOR_STATE.GRAB elif ($GrabTimer and !($GrabTimer.is_stopped())): currentCursorState = CURSOR_STATE.CLICK else: currentCursorState = CURSOR_STATE.DEFAULT if (currentCursorState != oldCursorState): oldCursorState = currentCursorState match oldCursorState: CURSOR_STATE.DEFAULT: $AnimatedSprite2D.play("default") CURSOR_STATE.CLICK: $AnimatedSprite2D.play("click") CURSOR_STATE.GRAB: $AnimatedSprite2D.play("grab_intro") CURSOR_STATE.GRABBED: $AnimatedSprite2D.play("grab") func _on_grab_timer_timeout(): grab_start() func _on_animated_sprite_2d_animation_changed(): cursorPlaying = true func _on_animated_sprite_2d_animation_finished(): cursorPlaying = false