Godot Version
4.4
Question
I am trying to make a cabinet door that opens when clicked and when clicked again closes
Below is the code I thought would work but it only stays open as long as I am holding the mouse button
func _on_closed_cabinet_right_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
$"LivingRoomwalls/open cbinet right".visible = true
$LivingRoomwalls/Door.visible = false
func _on_open_cabinet_right_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
$"LivingRoomwalls/open cbinet right".visible = false
$LivingRoomwalls/Door.visible = true
I am not sure what those two func are connected to, but my guess is that since they both play with the same event input that the second is playing the moment you release the first.
I would consolidate those into one func().
In that func just check
if event:
if $LivingRoomWalls/Doors.visible:
#set doors visible = false
#set other visible = true
else:
#set visibility of those above to the opposite value.
Have you used print statements to do any debugging?
Hi! Basic or maybe beginner coder here!
Maybe you should make a variable that counts how many times you pressed that?
When it’s 1 then the cabinet is open,
then when the variable is 2 then the cabinet closes,
then when you tap again it goes back to 1 (it’s back to the open state) So maybe like this?
var Times_Clicked: int = 0
func _on_closed_cabinet_right_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if Times_Clicked == 2:
Times_Clicked = 1
Times_Clicked += 1
func process(delta: float) -> void:
if Times_Clicked == 1:
$"LivingRoomwalls/open cbinet right".visible = true
$LivingRoomwalls/Door.visible = false
elif Times_Clicked == 2:
$"LivingRoomwalls/open cbinet right".visible = false
$LivingRoomwalls/Door.visible = true
Sorry if this doesn’t work! Afterall.. i did say i was a beginner or basic coder! If this did work then wowzie!
(Warning do not be super confident in my code!)
1 Like
One change i’d recommend to your suggestion. Instead of a random int val, use a basic statemachine setup.
enum {CLOSED, OPENED}
var door_state: = CLOSED
Then in your input just check.
if door_state == CLOSED:
door_state = OPENED
else:
door_state = CLOSED
Then in physics just change your two if statements.
if door_state == CLOSED:
#change visibility
else:
#change visibility
Though you could simplify this further if you wanted and optimize more, but this should work.
1 Like
Wow! I didn’t think of that because i usually use enums for enemies or players, not items. Great job:DD
Yep, you could simplify.
enum {IDLE, CHANGED}
var state = IDLE
Then,
if Input:
state = CHANGED
Then in physics,
if state == CHANGED:
#visible of one = !visible of self
#visible of other = !visible of self
state = IDLE
1 Like
@Joee_Yeager Based on your code, I recommend something like this. NOTE: your logic seems to be backwards, but since the variable names weren’t clear, I copied your logic best I could.
@onready var open_cabinet_right = $"LivingRoomwalls/open cbinet right"
@onready var door = $LivingRoomwalls/Door
var is_cabinet_open = false
func _on_cabinet_right_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if is_cabinet_open:
open_cabinet_right.visible = false
door.visible = true
is_cabinet_open = false
else:
open_cabinet_right.visible = true
door.visible = false
is_cabinet_open = true
@isabelle_alejar @regnarok I just used a boolean here. It’s clearer in my opinion, processes faster than an int, and makes the logic a little easier. You can achieve the same clarity that the enum gives in code with the name of the boolean variable.
If you want to get fancy, you could also do something like this with a boolean. I don’t recommend it because the code is confusing to read, but in more complex code something like this will run faster because there’s no if statement at all.
@onready var open_cabinet_right = $"LivingRoomwalls/open cbinet right"
@onready var door = $LivingRoomwalls/Door
var is_cabinet_open = false
func _on_cabinet_right_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
open_cabinet_right.visible = !is_cabinet_open
door.visible = is_cabinet_open
is_cabinet_open = !is_cabinet_open
2 Likes
Yeah @dragonforge-dev , adding the boolean var would give clarity, it is pretty much a refined version of my suggestion keeping to his code logic just adding that extra var for the clarity, and making his node ref var as well. All in all a pretty little piece of code.
Yeah, the enum post was a response to @isabelle_alejar suggestion, I figured it wasn’t a wrong way to handle it, and the logic being used was the same as a enum with state control.
2 Likes
There are definitely multiple ways to handle it that are valid. I just replied because I know @isabelle_alejar is trying to learn and I wanted to give yet another way. 
2 Likes