class_name BaseShape extends Sprite2D
var id:String = GameUtils.generate_uuid()
var is_modulate:bool = true
var color:Color
var scale_factor:float = 1.0
func _ready() -> void:
if is_modulate:
modulate = color
scale *= scale_factor
Child class ‘Triangle’:
class_name Triangle extends BaseShape
func _ready() -> void:
color = Constants.get_color_for_resource(Constants.SHAPE_TRIANGLE)
super._ready()
func _input(event: InputEvent) -> void:
if !event is InputEventScreenTouch:
return
if event.is_pressed() && self is Triangle:
print("triangle test")
elif not event.is_pressed():
pass
Child class ‘Square’
class_name Square extends BaseShape
func _ready() -> void:
color = Constants.get_color_for_resource(Constants.SHAPE_SQUARE)
super._ready()
func _input(event: InputEvent) -> void:
if !event is InputEventScreenTouch:
return
if event.is_pressed() && self is Square:
print("square test")
elif not event.is_pressed():
pass
Problem is when i click or touch square or triangle (vice versa) the other shape’s event is fired too? i even added check for self is <class_name> but it didnt work.
I need just child class input event, not neighbor or parent class!!
Regardless of where i touch or click, input below is written to console
I have not used this event but looking at this thread and the code:
It seems you are going to have to use the event.position to do your own hit testing to see if the touch is valid. (do a bit of math for the square and triangle areas to see if position falls inside)
Judging from your code and the traces, it seems this is a global event that is dispatched when the screen is pressed and controls need to figure out by their own hit test logic if the event is in bounds for their own action.
Yeah it seems like as you said so.
Below code is dirty fix to issue (i will change 100 with get_rect boundaries)
Well at least i can control this (or fire signals) from one class instead copying to child classes which is something?
func _input(event: InputEvent) -> void:
if !event is InputEventScreenTouch:
return
if event.is_pressed():
var distance:Vector2 = abs(event.position - global_position)
if distance.x < 100 && distance.y < 100:
print(self.name)
elif not event.is_pressed():
pass
Yeah you could have a hit manager that holds a list of the shapes and run through them, then check based on shape. Where the manager has the logic for each hit test area type.
I think there’s a simpler solution, actually. The short version, just use a Control node, _gui_input works with touchscreen events.
Now the longer version: the _input function is called on every node in the Viewport that has an _input function (that you have overridden in the script). I think you’re looking for _unhandled_input, which only propagates until something consumes it, which can be done either by the engine itself or by calling get_viewport.set_input_as_handled().
However, you still need to detect whether the input event is inside the shape. Sprites have no way to determine if an input is inside them without you coding the math yourself. But all Control and CollisionObject2D (like Area2D) do. So you can make TextureButton and override the _gui_input function. It automatically marks inputs as handled so you don’t have to worry about other nodes receiving the input, and it only triggers on events that are inside the TextureButton. You can set up a custom click mask for non-rectangular shapes.
I’m pretty sure _gui_input works for InputEventScreenTouch, but since I don’t actually have a touchscreen I’m actually creating the events in code and using get_viewport().push_input() to parse them. If it doesn’t work, you can always turn on emulate_mouse_from_touch in the ProjectSettings and use the normal button signals instead.
Thanks, the problem is, i am doing lots of node2d operations (both code and editor). Control class will not have that. Currently there are only two classes that are listening this so i am fine for now. But if it becomes a bigger problem, i will try to implement your way.