I am new to Godot. Trying to make a counter for some values of reactor core. Here is my code:
extends MarginContainer
export var obj=""
export var expr_list={"sig":""}
export(int) var value_from_model setget set_val
onready var panel_frame=get_node("frame")
onready var panel=get_node("frame/Panel")
func set_val(val):
value_from_model=val
if panel_frame != null:
panel_frame.margin_right=value_from_model
check_signal()
func check_signal():
var new_style = StyleBoxFlat.new()
var for_panel = StyleBoxFlat.new()
#var panel_frame=get_node("frame")
new_style.border_width_top=2
new_style.border_width_bottom = 2
new_style.border_width_left=2
new_style.border_width_right=2
new_style.border_color="#1bf408"
new_style.bg_color='#0b0e0e'
panel_frame.set('custom_styles/panel', new_style)
for_panel.bg_color="#1bf408"
panel.set('custom_styles/panel', for_panel)
func _ready():
check_signal()
set_val(value_from_model)
First my onready variables panel_frame and frame were in the funtion check_signal() as local variables. But I was getting an error "get_path: Cannot get path of node as it is not in a scene tree." , "get_node: (Node not found: "frame/Panel" (relative to "").) ". After I made them global and changed to onready var. And now I am getting this error.
When I try to change vavalue_from_model
in the inspector, the error appears again
Here is my progress bar which has to be changing every time when I change the value_from_model
If get_node
is failing, the node isn't there… So it gives you an error. That also explains why set
fails: the variable that should have been initialized with get_node
wasn't initialized.
Usually, that would be a matter of fixing a wrong path. You could even have Godot generate the correct path for you, by dragging the node over the script.
However, since get_path
was also failing, I suspect you are facing a slightly more complex situation.
I believe you or Godot are setting value_from_model
as part of the instantiation process, which triggers set_val
, before the ready mechanism.
You can check with is_inside_tree
. The pattern I often use is as follows:
func set_val(val):
if value_from_model==val:
return
value_from_model=val
if is_inside_tree():
update_val()
func _enter_tree() -> void:
update_val()
func update_val() -> void:
if panel_frame != null:
panel_frame.margin_right=value_from_model
check_signal()
I'm going to suggest to modify it to use _ready
instead of _enter_tree
, since you need children nodes, and _ready
will run after the children are ready. However, remember that _ready
will only run once, unless you call request_ready
, which might be important if you are going to remove and add the node multiple times during runtime.
You could also use yield
to wait until the node is ready or inside the scene tree, however, I have moved away from yield
, that is another tale.
Similarly, you should not need to do set_val(value_from_model)
in _ready
. Furthermore, you might even do panel_frame.margin_right=value_from_model
inside of check_signal
, and then you won't need two different methods (check_signal
and update_val
).
So we land into this:
func set_val(val):
if value_from_model==val:
return
value_from_model=val
if is_node_ready():
check_signal()
func _ready() -> void:
check_signal()
func _exit_tree() -> void:
request_ready()
func check_signal() -> void:
if panel_frame != null:
panel_frame.margin_right=value_from_model
# rest of the code