extends Node2D var spaceState var query : PhysicsPointQueryParameters2D var CastResult : Array var hoveredObjects : Array var hoveredObject var hoveredSticker var grabbedSticker enum CURSOR_STATE {DEFAULT, CLICK, GRAB, GRABBED} var currentCursorState:CURSOR_STATE = CURSOR_STATE.DEFAULT var oldCursorState:CURSOR_STATE = CURSOR_STATE.DEFAULT # 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() func isSticker(selectedObject:Node): var _isSticker:bool = false var _tags = getTags(selectedObject) if (_tags.size() > 0): if (_tags.find("sticker") != -1): _isSticker = true return _isSticker func getTags(selectedObject:Node): var _tags: Array if (selectedObject.has_meta("tags")): _tags = selectedObject.get_meta("tags") return _tags else: printerr("no tags inside %",selectedObject) return _tags func pointcast(): resetCast() query.collide_with_areas = true 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 (grabbedSticker == null)): #hoveredObjects.clear() #region Fill HoveredObjects for _object in CastResult: if(_object.collider.input_pickable == true): hoveredObjects.append(_object.collider.get_parent()) #endregion if (hoveredObjects.size() > 0): if (hoveredObjects.size() >= 2): sortByPosY(hoveredObjects,false) if (hoveredObjects[0] != hoveredObject): hoveredObject = hoveredObjects[0] print("Current hovered object :", hoveredObject) if (isSticker(hoveredObject)): hoveredSticker = hoveredObject print("Current hovered sticker :", hoveredSticker) else: hoveredSticker = null else: resetCast(true) else: resetCast(true) func resetCast(bFull = false): CastResult.clear() hoveredObjects.clear() if bFull: hoveredObject = null hoveredSticker = null func sortByPosY(objects: Array, ascending_order: bool = true): var _tempArray :Array _tempArray = objects # Inline comparison function _tempArray.sort_custom(comparePosY) # Reverse if descending order is required if not ascending_order: _tempArray.reverse() objects = _tempArray func comparePosY(a, b): #print("Compare ",a," at ",a.position.y, " and ",b," at ",b.position.y ) return a.position.y < b.position.y func cursor_look(): if (Input.is_action_pressed("select")): if (hoveredSticker): currentCursorState = CURSOR_STATE.GRABBED if ($GrabTimer.is_stopped() and not grabbedSticker): $GrabTimer.start() else: currentCursorState = CURSOR_STATE.CLICK if(hoveredObject): hoveredObject.click.emit() else: if (hoveredSticker): currentCursorState = CURSOR_STATE.GRAB else: currentCursorState = CURSOR_STATE.DEFAULT $GrabTimer.stop() 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(): if (hoveredSticker): grabbedSticker = hoveredSticker print("Grabbed ", grabbedSticker)