Skip to content

Commit

Permalink
Allow exporting variables of type Variant
Browse files Browse the repository at this point in the history
  • Loading branch information
KoBeWi committed Mar 24, 2024
1 parent 99ff024 commit ca78cdf
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 5 deletions.
96 changes: 92 additions & 4 deletions editor/editor_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
#include "scene/resources/packed_scene.h"
#include "scene/resources/visual_shader_nodes.h"

///////////////////// Nil /////////////////////////
///////////////////// NIL /////////////////////////

void EditorPropertyNil::update_property() {
}
Expand All @@ -69,6 +69,91 @@ EditorPropertyNil::EditorPropertyNil() {
add_child(prop_label);
}

//////////////////// VARIANT ///////////////////////

void EditorPropertyVariant::_change_type(int p_to_type) {
new_type = Variant::Type(p_to_type);

Variant zero;
Callable::CallError ce;
Variant::construct(new_type, zero, nullptr, 0, ce);
emit_changed(get_edited_property(), zero);
}

void EditorPropertyVariant::_set_read_only(bool p_read_only) {
change_type->set_disabled(p_read_only);
if (sub_property) {
sub_property->set_read_only(p_read_only);
}
}

void EditorPropertyVariant::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED) {
change_type->set_icon(get_editor_theme_icon("Edit"));

PopupMenu *popup = change_type->get_popup();
for (int i = 0; i < popup->get_item_count(); i++) {
popup->set_item_icon(i, get_editor_theme_icon(Variant::get_type_name(Variant::Type(popup->get_item_id(i)))));
}
}
}

void EditorPropertyVariant::update_property() {
const Variant &value = get_edited_property_value();
if (new_type == Variant::VARIANT_MAX) {
new_type = value.get_type();
}

if (new_type != current_type) {
current_type = new_type;

if (sub_property) {
memdelete(sub_property);
sub_property = nullptr;
}

if (current_type == Variant::OBJECT) {
sub_property = EditorInspector::instantiate_property_editor(nullptr, current_type, "", PROPERTY_HINT_RESOURCE_TYPE, "Resource", PROPERTY_USAGE_NONE);
} else {
sub_property = EditorInspector::instantiate_property_editor(nullptr, current_type, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE);
}
ERR_FAIL_NULL(sub_property);

sub_property->set_object_and_property(get_edited_object(), get_edited_property());
sub_property->set_name_split_ratio(0);
sub_property->set_selectable(false);
sub_property->set_use_folding(is_using_folding());
sub_property->set_read_only(is_read_only());
sub_property->set_h_size_flags(SIZE_EXPAND_FILL);
sub_property->connect(SNAME("property_changed"), callable_mp((EditorProperty *)this, &EditorProperty::emit_changed));
content->add_child(sub_property);
content->move_child(sub_property, 0);
sub_property->update_property();
} else if (sub_property) {
sub_property->update_property();
}
new_type = Variant::VARIANT_MAX;
}

EditorPropertyVariant::EditorPropertyVariant() {
content = memnew(HBoxContainer);
add_child(content);

change_type = memnew(MenuButton);
change_type->set_flat(false);

PopupMenu *popup = change_type->get_popup();
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
if (i == Variant::CALLABLE || i == Variant::SIGNAL || i == Variant::RID) {
// These types can't be constructed or serialized properly, so skip them.
continue;
}
popup->add_item(Variant::get_type_name(Variant::Type(i)), i);
}
popup->connect("id_pressed", callable_mp(this, &EditorPropertyVariant::_change_type));
content->add_child(change_type);
}

///////////////////// TEXT /////////////////////////

void EditorPropertyText::_set_read_only(bool p_read_only) {
Expand Down Expand Up @@ -3538,8 +3623,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
switch (p_type) {
// atomic types
case Variant::NIL: {
EditorPropertyNil *editor = memnew(EditorPropertyNil);
return editor;
if (p_usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
return memnew(EditorPropertyVariant);
} else {
return memnew(EditorPropertyNil);
}
} break;
case Variant::BOOL: {
EditorPropertyCheck *editor = memnew(EditorPropertyCheck);
Expand Down Expand Up @@ -3921,4 +4009,4 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
}

return nullptr;
}
}
21 changes: 21 additions & 0 deletions editor/editor_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ class EditorPropertyNil : public EditorProperty {
EditorPropertyNil();
};

class EditorPropertyVariant : public EditorProperty {
GDCLASS(EditorPropertyVariant, EditorProperty);

HBoxContainer *content = nullptr;
EditorProperty *sub_property = nullptr;
MenuButton *change_type = nullptr;

Variant::Type current_type = Variant::VARIANT_MAX;
Variant::Type new_type = Variant::VARIANT_MAX;

void _change_type(int p_to_type);

protected:
virtual void _set_read_only(bool p_read_only) override;
void _notification(int p_what);

public:
virtual void update_property() override;
EditorPropertyVariant();
};

class EditorPropertyText : public EditorProperty {
GDCLASS(EditorPropertyText, EditorProperty);
LineEdit *text = nullptr;
Expand Down
8 changes: 7 additions & 1 deletion modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4284,7 +4284,7 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
return false;
}

if (export_type.is_variant() || export_type.has_no_type()) {
if (export_type.has_no_type()) {
push_error(R"(Cannot use simple "@export" annotation because the type of the initialized value can't be inferred.)", p_annotation);
return false;
}
Expand Down Expand Up @@ -4369,6 +4369,12 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
variable->export_info.class_name = String(export_type.native_type).replace("::", ".");
}
} break;
case GDScriptParser::DataType::VARIANT: {
if (export_type.is_variant()) {
variable->export_info.type = Variant::NIL;
variable->export_info.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
}
} break;
default:
push_error(R"(Export type can only be built-in, a resource, a node, or an enum.)", p_annotation);
return false;
Expand Down

0 comments on commit ca78cdf

Please sign in to comment.