Skip to content

Commit

Permalink
GH-727 Add constant variable support
Browse files Browse the repository at this point in the history
  • Loading branch information
Naros committed Aug 12, 2024
1 parent c2f475d commit 874135b
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 23 deletions.
9 changes: 9 additions & 0 deletions src/editor/component_panels/variables_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ void OrchestratorScriptVariablesComponentPanel::_create_variable_item(TreeItem*
item->set_button_tooltip_text(0, index, "Variable is exported and visible outside the orchestration.");
item->set_button_disabled(0, index, false);
}
else if (p_variable->is_constant())
{
String tooltip = "Variable is a constant.";

int32_t index = item->get_button_count(0);
item->add_button(0, SceneUtils::get_editor_icon("MemberConstant"), 4);
item->set_button_tooltip_text(0, index, tooltip);
item->set_button_disabled(0, index, false);
}
else
{
String tooltip = "Variable is private and not exported.";
Expand Down
4 changes: 4 additions & 0 deletions src/editor/graph/actions/default_action_registrar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,10 @@ void OrchestratorDefaultGraphActionRegistrar::_register_orchestration_variables(
Ref<OrchestratorGraphActionHandler> getter_handler(memnew(OrchestratorGraphNodeSpawnerVariableGet(variable_name)));
_context->list->push_back(memnew(OrchestratorGraphActionMenuItem(getter_spec, getter_handler)));

// Constants don't allow spawning using setters
if (variable->is_constant())
continue;

OrchestratorGraphActionSpec setter_spec;
setter_spec.category = vformat("Variables/set_%s", variable_name);
setter_spec.tooltip = vformat("Set the value of of variable '%s'", variable_name);
Expand Down
58 changes: 36 additions & 22 deletions src/editor/graph/graph_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,12 @@ bool OrchestratorGraphEdit::_can_drop_data(const Vector2& p_position, const Vari
if (allowed_types.has(type))
{
if (type == "variable")
_show_drag_hint("Use Ctrl to drop a Setter, Shift to drop a Getter");

{
const String variable_name = String(Array(data["variables"])[0]);
const Ref<OScriptVariable> variable = _script_graph->get_orchestration()->get_variable(variable_name);
if (variable.is_valid() && !variable->is_constant())
_show_drag_hint("Use Ctrl to drop a Setter, Shift to drop a Getter");
}
return true;
}

Expand Down Expand Up @@ -737,36 +741,46 @@ void OrchestratorGraphEdit::_drop_data(const Vector2& p_position, const Variant&
_hide_drag_hint();

const String variable_name = String(Array(data["variables"])[0]);
if (Input::get_singleton()->is_key_pressed(Key::KEY_CTRL))

Ref<OScriptVariable> variable = get_orchestration()->get_variable(variable_name);
if (!variable.is_valid())
return;

const bool is_constant = variable->is_constant();
const bool is_validated = variable->get_variable_type() == Variant::OBJECT;

if (Input::get_singleton()->is_key_pressed(KEY_CTRL))
{
OrchestratorGraphNodeSpawnerVariableSet setter(variable_name);
setter.execute(this, _saved_mouse_position);
if (!is_constant)
{
Ref<OrchestratorGraphNodeSpawnerVariableSet> setter(memnew(OrchestratorGraphNodeSpawnerVariableSet(variable_name)));
setter->execute(this, _saved_mouse_position);
}
}
else if (Input::get_singleton()->is_key_pressed(Key::KEY_SHIFT))
else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT))
{
OrchestratorGraphNodeSpawnerVariableGet getter(variable_name);
getter.execute(this, _saved_mouse_position);
Ref<OrchestratorGraphNodeSpawnerVariableGet> getter(memnew(OrchestratorGraphNodeSpawnerVariableGet(variable_name)));
getter->execute(this, _saved_mouse_position);
}
else
{
const bool validated = get_orchestration()->get_variable(variable_name)->get_variable_type() == Variant::OBJECT;

// Create context-menu handlers
Ref<OrchestratorGraphActionHandler> get_handler(memnew(OrchestratorGraphNodeSpawnerVariableGet(variable_name)));
Ref<OrchestratorGraphActionHandler> set_handler(memnew(OrchestratorGraphNodeSpawnerVariableSet(variable_name)));
Ref<OrchestratorGraphActionHandler> get_validated_handler(memnew(OrchestratorGraphNodeSpawnerVariableGet(variable_name, true)));

// Create context-menu to specify variable get or set choice
_context_menu->clear();
_context_menu->add_separator("Variable " + variable_name);
_context_menu->add_item("Get " + variable_name, CM_VARIABLE_GET);
if (validated)
_context_menu->set_item_metadata(_context_menu->get_item_index(CM_VARIABLE_GET), memnew(OrchestratorGraphNodeSpawnerVariableGet(variable_name)));

if (is_validated)
{
_context_menu->add_item("Get " + variable_name + " with validation", CM_VARIABLE_GET_VALIDATED);
_context_menu->add_item("Set " + variable_name, CM_VARIABLE_SET);
_context_menu->set_item_metadata(_context_menu->get_item_index(CM_VARIABLE_GET), get_handler);
if (validated)
_context_menu->set_item_metadata(_context_menu->get_item_index(CM_VARIABLE_GET_VALIDATED), get_validated_handler);
_context_menu->set_item_metadata(_context_menu->get_item_index(CM_VARIABLE_SET), set_handler);
_context_menu->set_item_metadata(_context_menu->get_item_index(CM_VARIABLE_GET_VALIDATED), memnew(OrchestratorGraphNodeSpawnerVariableGet(variable_name, true)));
}

if (!is_constant)
{
_context_menu->add_item("Set " + variable_name, CM_VARIABLE_SET);
_context_menu->set_item_metadata(_context_menu->get_item_index(CM_VARIABLE_SET), memnew(OrchestratorGraphNodeSpawnerVariableSet(variable_name)));
}

_context_menu->reset_size();
_context_menu->set_position(get_screen_position() + p_position);
_context_menu->popup();
Expand Down
16 changes: 16 additions & 0 deletions src/script/nodes/variables/variable_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ class OScriptNodeVariableSetInstance : public OScriptNodeInstance
{
DECLARE_SCRIPT_NODE_INSTANCE(OScriptNodeVariableSet);
StringName _variable_name;
bool _constant{ false };

public:
int step(OScriptExecutionContext& p_context) override
{
if (_constant)
{
p_context.set_error(vformat("Cannot modify a constant variable '%s'", _variable_name));
return -1 | STEP_FLAG_END;
}

Variant value = p_context.get_input(0);

Variant current_value;
Expand Down Expand Up @@ -150,10 +157,19 @@ void OScriptNodeVariableSet::reallocate_pins_during_reconstruction(const Vector<
}
}

void OScriptNodeVariableSet::validate_node_during_build(BuildLog& p_log) const
{
if (_variable.is_valid() && _variable->is_constant())
p_log.error(this, "Cannot modify constant variable value.");

super::validate_node_during_build(p_log);
}

OScriptNodeInstance* OScriptNodeVariableSet::instantiate()
{
OScriptNodeVariableSetInstance *i = memnew(OScriptNodeVariableSetInstance);
i->_node = this;
i->_variable_name = _variable->get_variable_name();
i->_constant = _variable->is_constant();
return i;
}
1 change: 1 addition & 0 deletions src/script/nodes/variables/variable_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class OScriptNodeVariableSet : public OScriptNodeVariable
String get_tooltip_text() const override;
String get_node_title() const override;
void reallocate_pins_during_reconstruction(const Vector<Ref<OScriptNodePin>>& p_old_pins) override;
void validate_node_during_build(BuildLog& p_log) const override;
OScriptNodeInstance* instantiate() override;
//~ End OScriptNode Interface
};
Expand Down
30 changes: 29 additions & 1 deletion src/script/variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ void OScriptVariable::_bind_methods()
ClassDB::bind_method(D_METHOD("get_category"), &OScriptVariable::get_category);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "category"), "set_category", "get_category");

ClassDB::bind_method(D_METHOD("set_constant", "constant"), &OScriptVariable::set_constant);
ClassDB::bind_method(D_METHOD("is_constant"), &OScriptVariable::is_constant);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "constant"), "set_constant", "is_constant");

ClassDB::bind_method(D_METHOD("set_exported", "exported"), &OScriptVariable::set_exported);
ClassDB::bind_method(D_METHOD("is_exported"), &OScriptVariable::is_exported);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exported"), "set_exported", "is_exported");
Expand Down Expand Up @@ -97,7 +101,7 @@ void OScriptVariable::_validate_property(PropertyInfo& p_property) const

bool OScriptVariable::_property_can_revert(const StringName& p_name) const
{
static Array properties = Array::make("name", "category", "exported", "classification", "default_value", "description");
static Array properties = Array::make("name", "category", "exported", "classification", "default_value", "description", "constant");
return properties.has(p_name);
}

Expand Down Expand Up @@ -133,11 +137,20 @@ bool OScriptVariable::_property_get_revert(const StringName& p_name, Variant& r_
r_property = "";
return true;
}
else if (p_name.match("constant"))
{
r_property = false;
return true;
}
return false;
}

bool OScriptVariable::_is_exportable_type(const PropertyInfo& p_property) const
{
// Constants cannot be exported
if (_constant)
return false;

switch (p_property.type)
{
// These are all not exportable
Expand Down Expand Up @@ -396,3 +409,18 @@ void OScriptVariable::set_default_value(const Variant& p_default_value)
emit_changed();
}
}

void OScriptVariable::set_constant(bool p_constant)
{
if (_constant != p_constant)
{
_constant = p_constant;

_exportable = _is_exportable_type(_info);
if (!_exportable && _constant)
_exported = false;

notify_property_list_changed();
emit_changed();
}
}
9 changes: 9 additions & 0 deletions src/script/variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class OScriptVariable : public Resource
int _type_category{ 0 }; //! Defaults to basic
Variant _type_subcategory; //! Subcategory type
String _value_list; //! Enum/Bitfield custom value list
bool _constant{ false }; //! Whether variable is a constant

protected:
//~ Begin Wrapped Interface
Expand Down Expand Up @@ -160,6 +161,14 @@ class OScriptVariable : public Resource
/// Set the variable's default value
/// @param p_default_value the default value
void set_default_value(const Variant& p_default_value);

/// Return whether the variable is a constant value
/// @return true if the variable is a constant and cannot be set, false otherwise
bool is_constant() const { return _constant; }

/// Sets whether the variable is a constant
/// @param p_constant whether the variable is constant
void set_constant(bool p_constant);
};

#endif // ORCHESTRATOR_SCRIPT_VARIABLE_H

0 comments on commit 874135b

Please sign in to comment.