Fix update property for dictionnaries so that it updates only what is necessary
This commit is contained in:
parent
ffc41fb76d
commit
0331ecb527
@ -111,6 +111,7 @@ bool EditorPropertyDictionaryObject::_set(const StringName &p_name, const Varian
|
||||
}
|
||||
|
||||
if (name.begins_with("indices")) {
|
||||
dict = dict.duplicate();
|
||||
int index = name.get_slicec('/', 1).to_int();
|
||||
Variant key = dict.get_key_at_index(index);
|
||||
dict[key] = p_value;
|
||||
@ -171,6 +172,31 @@ Variant EditorPropertyDictionaryObject::get_new_item_value() {
|
||||
return new_item_value;
|
||||
}
|
||||
|
||||
String EditorPropertyDictionaryObject::get_property_name_for_index(int p_index) {
|
||||
switch (p_index) {
|
||||
case NEW_KEY_INDEX:
|
||||
return "new_item_key";
|
||||
case NEW_VALUE_INDEX:
|
||||
return "new_item_value";
|
||||
default:
|
||||
return "indices/" + itos(p_index);
|
||||
}
|
||||
}
|
||||
|
||||
String EditorPropertyDictionaryObject::get_label_for_index(int p_index) {
|
||||
switch (p_index) {
|
||||
case NEW_KEY_INDEX:
|
||||
return TTR("New Key:");
|
||||
break;
|
||||
case NEW_VALUE_INDEX:
|
||||
return TTR("New Value:");
|
||||
break;
|
||||
default:
|
||||
return dict.get_key_at_index(p_index).get_construct_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EditorPropertyDictionaryObject::EditorPropertyDictionaryObject() {
|
||||
}
|
||||
|
||||
@ -230,15 +256,14 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
|
||||
Variant array = object->get_array().duplicate();
|
||||
array.set(slots[changing_type_index].index, value);
|
||||
|
||||
emit_changed(get_edited_property(), array, "", true);
|
||||
update_property();
|
||||
emit_changed(get_edited_property(), array);
|
||||
}
|
||||
|
||||
void EditorPropertyArray::_object_id_selected(const StringName &p_property, ObjectID p_id) {
|
||||
emit_signal(SNAME("object_id_selected"), p_property, p_id);
|
||||
}
|
||||
|
||||
void EditorPropertyArray::create_new_property_slot() {
|
||||
void EditorPropertyArray::_create_new_property_slot() {
|
||||
int idx = slots.size();
|
||||
HBoxContainer *hbox = memnew(HBoxContainer);
|
||||
|
||||
@ -365,7 +390,7 @@ void EditorPropertyArray::update_property() {
|
||||
vbox->add_child(paginator);
|
||||
|
||||
for (int i = 0; i < page_length; i++) {
|
||||
create_new_property_slot();
|
||||
_create_new_property_slot();
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,8 +459,7 @@ void EditorPropertyArray::_remove_pressed(int p_slot_index) {
|
||||
Variant array = object->get_array().duplicate();
|
||||
array.call("remove_at", slots[p_slot_index].index);
|
||||
|
||||
emit_changed(get_edited_property(), array, "", false);
|
||||
update_property();
|
||||
emit_changed(get_edited_property(), array);
|
||||
}
|
||||
|
||||
void EditorPropertyArray::_button_draw() {
|
||||
@ -514,8 +538,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d
|
||||
}
|
||||
}
|
||||
|
||||
emit_changed(get_edited_property(), array, "", false);
|
||||
update_property();
|
||||
emit_changed(get_edited_property(), array);
|
||||
}
|
||||
}
|
||||
|
||||
@ -607,8 +630,7 @@ void EditorPropertyArray::_length_changed(double p_page) {
|
||||
Variant array = object->get_array().duplicate();
|
||||
array.call("resize", int(p_page));
|
||||
|
||||
emit_changed(get_edited_property(), array, "", false);
|
||||
update_property();
|
||||
emit_changed(get_edited_property(), array);
|
||||
}
|
||||
|
||||
void EditorPropertyArray::_add_element() {
|
||||
@ -700,8 +722,7 @@ void EditorPropertyArray::_reorder_button_up() {
|
||||
array.call("remove_at", reorder_slot.index);
|
||||
array.call("insert", reorder_to_index, value_to_move);
|
||||
|
||||
reorder_slot.index = reorder_slot.index % page_length + page_index * page_length;
|
||||
emit_changed(get_edited_property(), array, "", false);
|
||||
emit_changed(get_edited_property(), array);
|
||||
}
|
||||
|
||||
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
|
||||
@ -748,31 +769,19 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia
|
||||
p_value = Variant(); // `EditorResourcePicker` resets to `Ref<Resource>()`. See GH-82716.
|
||||
}
|
||||
|
||||
if (p_property == "new_item_key") {
|
||||
object->set_new_item_key(p_value);
|
||||
} else if (p_property == "new_item_value") {
|
||||
object->set_new_item_value(p_value);
|
||||
} else if (p_property.begins_with("indices")) {
|
||||
int index = p_property.get_slice("/", 1).to_int();
|
||||
|
||||
Dictionary dict = object->get_dict().duplicate();
|
||||
Variant key = dict.get_key_at_index(index);
|
||||
dict[key] = p_value;
|
||||
|
||||
object->set_dict(dict);
|
||||
emit_changed(get_edited_property(), dict, "", true);
|
||||
}
|
||||
object->set(p_property, p_value);
|
||||
emit_changed(get_edited_property(), object->get_dict(), p_name, p_changing);
|
||||
}
|
||||
|
||||
void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) {
|
||||
void EditorPropertyDictionary::_change_type(Object *p_button, int p_slot_index) {
|
||||
Button *button = Object::cast_to<Button>(p_button);
|
||||
|
||||
int index = slots[p_slot_index].index;
|
||||
Rect2 rect = button->get_screen_rect();
|
||||
change_type->set_item_disabled(change_type->get_item_index(Variant::VARIANT_MAX), p_index < 0);
|
||||
change_type->set_item_disabled(change_type->get_item_index(Variant::VARIANT_MAX), index < 0);
|
||||
change_type->reset_size();
|
||||
change_type->set_position(rect.get_end() - Vector2(change_type->get_contents_minimum_size().x, 0));
|
||||
change_type->popup();
|
||||
changing_type_index = p_index;
|
||||
changing_type_index = index;
|
||||
}
|
||||
|
||||
void EditorPropertyDictionary::_add_key_value() {
|
||||
@ -796,36 +805,59 @@ void EditorPropertyDictionary::_add_key_value() {
|
||||
VariantInternal::initialize(&new_value, type);
|
||||
object->set_new_item_value(new_value);
|
||||
|
||||
emit_changed(get_edited_property(), dict, "", false);
|
||||
update_property();
|
||||
emit_changed(get_edited_property(), dict);
|
||||
}
|
||||
|
||||
void EditorPropertyDictionary::_create_new_property_slot(int p_idx) {
|
||||
HBoxContainer *hbox = memnew(HBoxContainer);
|
||||
EditorProperty *prop = memnew(EditorPropertyNil);
|
||||
hbox->add_child(prop);
|
||||
|
||||
Button *edit_btn = memnew(Button);
|
||||
edit_btn->set_icon(get_editor_theme_icon(SNAME("Edit")));
|
||||
edit_btn->set_disabled(is_read_only());
|
||||
edit_btn->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type).bind(edit_btn, slots.size()));
|
||||
hbox->add_child(edit_btn);
|
||||
if (add_panel) {
|
||||
add_panel->get_child(0)->add_child(hbox);
|
||||
} else {
|
||||
property_vbox->add_child(hbox);
|
||||
}
|
||||
Slot slot;
|
||||
slot.prop = prop;
|
||||
slot.object = object;
|
||||
slot.container = hbox;
|
||||
int index = p_idx + (p_idx >= 0 ? page_index * page_length : 0);
|
||||
slot.set_index(index);
|
||||
slots.push_back(slot);
|
||||
}
|
||||
|
||||
void EditorPropertyDictionary::_change_type_menu(int p_index) {
|
||||
if (changing_type_index < 0) {
|
||||
Variant value;
|
||||
switch (changing_type_index) {
|
||||
case EditorPropertyDictionaryObject::NEW_KEY_INDEX:
|
||||
case EditorPropertyDictionaryObject::NEW_VALUE_INDEX:
|
||||
VariantInternal::initialize(&value, Variant::Type(p_index));
|
||||
if (changing_type_index == -1) {
|
||||
if (changing_type_index == EditorPropertyDictionaryObject::NEW_KEY_INDEX) {
|
||||
object->set_new_item_key(value);
|
||||
} else {
|
||||
object->set_new_item_value(value);
|
||||
}
|
||||
update_property();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Dictionary dict = object->get_dict().duplicate();
|
||||
if (p_index < Variant::VARIANT_MAX) {
|
||||
Variant value;
|
||||
VariantInternal::initialize(&value, Variant::Type(p_index));
|
||||
Variant key = dict.get_key_at_index(changing_type_index);
|
||||
if (p_index < Variant::VARIANT_MAX) {
|
||||
VariantInternal::initialize(&value, Variant::Type(p_index));
|
||||
dict[key] = value;
|
||||
} else {
|
||||
Variant key = dict.get_key_at_index(changing_type_index);
|
||||
dict.erase(key);
|
||||
}
|
||||
|
||||
emit_changed(get_edited_property(), dict, "", false);
|
||||
update_property();
|
||||
emit_changed(get_edited_property(), dict);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPropertyDictionary::setup(PropertyHint p_hint) {
|
||||
@ -877,331 +909,72 @@ void EditorPropertyDictionary::update_property() {
|
||||
paginator = memnew(EditorPaginator);
|
||||
paginator->connect("page_changed", callable_mp(this, &EditorPropertyDictionary::_page_changed));
|
||||
vbox->add_child(paginator);
|
||||
} else {
|
||||
// Queue children for deletion, deleting immediately might cause errors.
|
||||
for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
|
||||
property_vbox->get_child(i)->queue_free();
|
||||
|
||||
for (int i = 0; i < page_length; i++) {
|
||||
_create_new_property_slot(slots.size());
|
||||
}
|
||||
|
||||
add_panel = memnew(PanelContainer);
|
||||
property_vbox->add_child(add_panel);
|
||||
add_panel->add_theme_style_override(SNAME("panel"), get_theme_stylebox(SNAME("DictionaryAddItem"), EditorStringName(EditorStyles)));
|
||||
VBoxContainer *add_vbox = memnew(VBoxContainer);
|
||||
add_panel->add_child(add_vbox);
|
||||
|
||||
_create_new_property_slot(EditorPropertyDictionaryObject::NEW_KEY_INDEX);
|
||||
_create_new_property_slot(EditorPropertyDictionaryObject::NEW_VALUE_INDEX);
|
||||
|
||||
button_add_item = EditorInspector::create_inspector_action_button(TTR("Add Key/Value Pair"));
|
||||
button_add_item->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
|
||||
button_add_item->set_disabled(is_read_only());
|
||||
button_add_item->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_add_key_value));
|
||||
add_vbox->add_child(button_add_item);
|
||||
}
|
||||
|
||||
int size = dict.size();
|
||||
|
||||
int max_page = MAX(0, size - 1) / page_length;
|
||||
page_index = MIN(page_index, max_page);
|
||||
if (page_index > max_page) {
|
||||
_page_changed(max_page);
|
||||
}
|
||||
|
||||
paginator->update(page_index, max_page);
|
||||
paginator->set_visible(max_page > 0);
|
||||
|
||||
int offset = page_index * page_length;
|
||||
add_panel->set_visible(page_index == max_page);
|
||||
|
||||
int amount = MIN(size - offset, page_length);
|
||||
int total_amount = page_index == max_page ? amount + 2 : amount; // For the "Add Key/Value Pair" box on last page.
|
||||
|
||||
VBoxContainer *add_vbox = nullptr;
|
||||
double default_float_step = EDITOR_GET("interface/inspector/default_float_step");
|
||||
|
||||
for (int i = 0; i < total_amount; i++) {
|
||||
String prop_name;
|
||||
Variant key;
|
||||
Variant value;
|
||||
|
||||
if (i < amount) {
|
||||
prop_name = "indices/" + itos(i + offset);
|
||||
key = dict.get_key_at_index(i + offset);
|
||||
value = dict.get_value_at_index(i + offset);
|
||||
} else if (i == amount) {
|
||||
prop_name = "new_item_key";
|
||||
value = object->get_new_item_key();
|
||||
} else if (i == amount + 1) {
|
||||
prop_name = "new_item_value";
|
||||
value = object->get_new_item_value();
|
||||
for (Slot &slot : slots) {
|
||||
bool slot_visible = slot.index < size;
|
||||
slot.container->set_visible(slot_visible);
|
||||
// If not visible no need to update it.
|
||||
if (!slot_visible) {
|
||||
continue;
|
||||
}
|
||||
Variant value = object->get(slot.prop_name);
|
||||
Variant::Type value_type = value.get_type();
|
||||
|
||||
EditorProperty *prop = nullptr;
|
||||
|
||||
switch (value.get_type()) {
|
||||
case Variant::NIL: {
|
||||
prop = memnew(EditorPropertyNil);
|
||||
|
||||
} break;
|
||||
|
||||
// Atomic types.
|
||||
case Variant::BOOL: {
|
||||
prop = memnew(EditorPropertyCheck);
|
||||
|
||||
} break;
|
||||
case Variant::INT: {
|
||||
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
|
||||
editor->setup(-100000, 100000, 1, false, true, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::FLOAT: {
|
||||
EditorPropertyFloat *editor = memnew(EditorPropertyFloat);
|
||||
editor->setup(-100000, 100000, default_float_step, true, false, true, true);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::STRING: {
|
||||
if (i != amount && property_hint == PROPERTY_HINT_MULTILINE_TEXT) {
|
||||
// If this is NOT the new key field and there's a multiline hint,
|
||||
// show the field as multiline
|
||||
prop = memnew(EditorPropertyMultilineText);
|
||||
} else {
|
||||
prop = memnew(EditorPropertyText);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
// Math types.
|
||||
case Variant::VECTOR2: {
|
||||
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR2I: {
|
||||
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i);
|
||||
editor->setup(-100000, 100000);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::RECT2: {
|
||||
EditorPropertyRect2 *editor = memnew(EditorPropertyRect2);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::RECT2I: {
|
||||
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i);
|
||||
editor->setup(-100000, 100000);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR3: {
|
||||
EditorPropertyVector3 *editor = memnew(EditorPropertyVector3);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR3I: {
|
||||
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i);
|
||||
editor->setup(-100000, 100000);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR4: {
|
||||
EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR4I: {
|
||||
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
|
||||
editor->setup(-100000, 100000);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::TRANSFORM2D: {
|
||||
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::PLANE: {
|
||||
EditorPropertyPlane *editor = memnew(EditorPropertyPlane);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::QUATERNION: {
|
||||
EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::AABB: {
|
||||
EditorPropertyAABB *editor = memnew(EditorPropertyAABB);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::BASIS: {
|
||||
EditorPropertyBasis *editor = memnew(EditorPropertyBasis);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::TRANSFORM3D: {
|
||||
EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
case Variant::PROJECTION: {
|
||||
EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
|
||||
editor->setup(-100000, 100000, default_float_step, true);
|
||||
prop = editor;
|
||||
|
||||
} break;
|
||||
|
||||
// Miscellaneous types.
|
||||
case Variant::COLOR: {
|
||||
prop = memnew(EditorPropertyColor);
|
||||
|
||||
} break;
|
||||
case Variant::STRING_NAME: {
|
||||
EditorPropertyText *ept = memnew(EditorPropertyText);
|
||||
ept->set_string_name(true);
|
||||
prop = ept;
|
||||
|
||||
} break;
|
||||
case Variant::NODE_PATH: {
|
||||
prop = memnew(EditorPropertyNodePath);
|
||||
|
||||
} break;
|
||||
case Variant::RID: {
|
||||
prop = memnew(EditorPropertyRID);
|
||||
|
||||
} break;
|
||||
case Variant::SIGNAL: {
|
||||
prop = memnew(EditorPropertySignal);
|
||||
|
||||
} break;
|
||||
case Variant::CALLABLE: {
|
||||
prop = memnew(EditorPropertyCallable);
|
||||
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
if (Object::cast_to<EncodedObjectAsID>(value)) {
|
||||
// Check if the editor property needs to be updated.
|
||||
bool value_as_id = Object::cast_to<EncodedObjectAsID>(value);
|
||||
if (value_type != slot.type || (value_type == Variant::OBJECT && value_as_id != slot.as_id)) {
|
||||
slot.as_id = value_as_id;
|
||||
slot.type = value_type;
|
||||
EditorProperty *new_prop = nullptr;
|
||||
if (value_type == Variant::OBJECT && value_as_id) {
|
||||
EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID);
|
||||
editor->setup("Object");
|
||||
prop = editor;
|
||||
|
||||
new_prop = editor;
|
||||
} else {
|
||||
EditorPropertyResource *editor = memnew(EditorPropertyResource);
|
||||
editor->setup(object.ptr(), prop_name, "Resource");
|
||||
editor->set_use_folding(is_using_folding());
|
||||
prop = editor;
|
||||
new_prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE);
|
||||
}
|
||||
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
prop = memnew(EditorPropertyDictionary);
|
||||
|
||||
} break;
|
||||
case Variant::ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
|
||||
// Arrays.
|
||||
case Variant::PACKED_BYTE_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_BYTE_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_INT32_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_INT32_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_FLOAT32_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_FLOAT32_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_INT64_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_INT64_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_FLOAT64_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_FLOAT64_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_STRING_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_STRING_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR2_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_VECTOR2_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR3_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_VECTOR3_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
case Variant::PACKED_COLOR_ARRAY: {
|
||||
EditorPropertyArray *editor = memnew(EditorPropertyArray);
|
||||
editor->setup(Variant::PACKED_COLOR_ARRAY);
|
||||
prop = editor;
|
||||
} break;
|
||||
default: {
|
||||
new_prop->set_selectable(false);
|
||||
new_prop->set_use_folding(is_using_folding());
|
||||
new_prop->connect(SNAME("property_changed"), callable_mp(this, &EditorPropertyDictionary::_property_changed));
|
||||
new_prop->connect(SNAME("object_id_selected"), callable_mp(this, &EditorPropertyDictionary::_object_id_selected));
|
||||
new_prop->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
new_prop->set_read_only(is_read_only());
|
||||
slot.set_prop(new_prop);
|
||||
}
|
||||
slot.prop->update_property();
|
||||
}
|
||||
|
||||
ERR_FAIL_NULL(prop);
|
||||
|
||||
prop->set_read_only(is_read_only());
|
||||
|
||||
if (i == amount) {
|
||||
PanelContainer *pc = memnew(PanelContainer);
|
||||
property_vbox->add_child(pc);
|
||||
pc->add_theme_style_override(SNAME("panel"), get_theme_stylebox(SNAME("DictionaryAddItem"), EditorStringName(EditorStyles)));
|
||||
|
||||
add_vbox = memnew(VBoxContainer);
|
||||
pc->add_child(add_vbox);
|
||||
}
|
||||
prop->set_object_and_property(object.ptr(), prop_name);
|
||||
int change_index = 0;
|
||||
|
||||
if (i < amount) {
|
||||
String cs = key.get_construct_string();
|
||||
prop->set_label(key.get_construct_string());
|
||||
prop->set_tooltip_text(cs);
|
||||
change_index = i + offset;
|
||||
} else if (i == amount) {
|
||||
prop->set_label(TTR("New Key:"));
|
||||
change_index = -1;
|
||||
} else if (i == amount + 1) {
|
||||
prop->set_label(TTR("New Value:"));
|
||||
change_index = -2;
|
||||
}
|
||||
|
||||
prop->set_selectable(false);
|
||||
prop->connect("property_changed", callable_mp(this, &EditorPropertyDictionary::_property_changed));
|
||||
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyDictionary::_object_id_selected));
|
||||
|
||||
HBoxContainer *hbox = memnew(HBoxContainer);
|
||||
if (add_vbox) {
|
||||
add_vbox->add_child(hbox);
|
||||
} else {
|
||||
property_vbox->add_child(hbox);
|
||||
}
|
||||
hbox->add_child(prop);
|
||||
prop->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
Button *edit_btn = memnew(Button);
|
||||
edit_btn->set_icon(get_editor_theme_icon(SNAME("Edit")));
|
||||
edit_btn->set_disabled(is_read_only());
|
||||
hbox->add_child(edit_btn);
|
||||
edit_btn->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type).bind(edit_btn, change_index));
|
||||
|
||||
prop->update_property();
|
||||
|
||||
if (i == amount + 1) {
|
||||
button_add_item = EditorInspector::create_inspector_action_button(TTR("Add Key/Value Pair"));
|
||||
button_add_item->set_icon(get_editor_theme_icon(SNAME("Add")));
|
||||
button_add_item->set_disabled(is_read_only());
|
||||
button_add_item->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_add_key_value));
|
||||
add_vbox->add_child(button_add_item);
|
||||
}
|
||||
}
|
||||
|
||||
updating = false;
|
||||
|
||||
} else {
|
||||
@ -1210,6 +983,8 @@ void EditorPropertyDictionary::update_property() {
|
||||
memdelete(container);
|
||||
button_add_item = nullptr;
|
||||
container = nullptr;
|
||||
add_panel = nullptr;
|
||||
slots.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1254,10 +1029,17 @@ void EditorPropertyDictionary::_edit_pressed() {
|
||||
}
|
||||
|
||||
void EditorPropertyDictionary::_page_changed(int p_page) {
|
||||
page_index = p_page;
|
||||
int i = p_page * page_length;
|
||||
for (Slot &slot : slots) {
|
||||
if (slot.index > -1) {
|
||||
slot.set_index(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (updating) {
|
||||
return;
|
||||
}
|
||||
page_index = p_page;
|
||||
update_property();
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,11 @@ protected:
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
|
||||
public:
|
||||
enum {
|
||||
NEW_KEY_INDEX = -2,
|
||||
NEW_VALUE_INDEX,
|
||||
};
|
||||
|
||||
void set_dict(const Dictionary &p_dict);
|
||||
Dictionary get_dict();
|
||||
|
||||
@ -75,6 +80,9 @@ public:
|
||||
void set_new_item_value(const Variant &p_new_item);
|
||||
Variant get_new_item_value();
|
||||
|
||||
String get_label_for_index(int p_index);
|
||||
String get_property_name_for_index(int p_index);
|
||||
|
||||
EditorPropertyDictionaryObject();
|
||||
};
|
||||
|
||||
@ -125,7 +133,7 @@ class EditorPropertyArray : public EditorProperty {
|
||||
void _reorder_button_gui_input(const Ref<InputEvent> &p_event);
|
||||
void _reorder_button_down(int p_index);
|
||||
void _reorder_button_up();
|
||||
void create_new_property_slot();
|
||||
void _create_new_property_slot();
|
||||
|
||||
protected:
|
||||
Ref<EditorPropertyArrayObject> object;
|
||||
@ -160,6 +168,34 @@ public:
|
||||
class EditorPropertyDictionary : public EditorProperty {
|
||||
GDCLASS(EditorPropertyDictionary, EditorProperty);
|
||||
|
||||
struct Slot {
|
||||
Ref<EditorPropertyDictionaryObject> object;
|
||||
HBoxContainer *container = nullptr;
|
||||
int index = -1;
|
||||
Variant::Type type = Variant::VARIANT_MAX;
|
||||
bool as_id = false;
|
||||
EditorProperty *prop = nullptr;
|
||||
String prop_name;
|
||||
|
||||
void set_index(int p_idx) {
|
||||
index = p_idx;
|
||||
prop_name = object->get_property_name_for_index(p_idx);
|
||||
update_prop_or_index();
|
||||
}
|
||||
|
||||
void set_prop(EditorProperty *p_prop) {
|
||||
prop->add_sibling(p_prop);
|
||||
prop->queue_free();
|
||||
prop = p_prop;
|
||||
update_prop_or_index();
|
||||
}
|
||||
|
||||
void update_prop_or_index() {
|
||||
prop->set_object_and_property(object.ptr(), prop_name);
|
||||
prop->set_label(object->get_label_for_index(index));
|
||||
}
|
||||
};
|
||||
|
||||
PopupMenu *change_type = nullptr;
|
||||
bool updating = false;
|
||||
|
||||
@ -170,15 +206,18 @@ class EditorPropertyDictionary : public EditorProperty {
|
||||
Button *edit = nullptr;
|
||||
MarginContainer *container = nullptr;
|
||||
VBoxContainer *property_vbox = nullptr;
|
||||
PanelContainer *add_panel = nullptr;
|
||||
EditorSpinSlider *size_sliderv = nullptr;
|
||||
Button *button_add_item = nullptr;
|
||||
EditorPaginator *paginator = nullptr;
|
||||
PropertyHint property_hint;
|
||||
LocalVector<Slot> slots;
|
||||
void _create_new_property_slot(int p_idx);
|
||||
|
||||
void _page_changed(int p_page);
|
||||
void _edit_pressed();
|
||||
void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
|
||||
void _change_type(Object *p_button, int p_index);
|
||||
void _change_type(Object *p_button, int p_slot_index);
|
||||
void _change_type_menu(int p_index);
|
||||
|
||||
void _add_key_value();
|
||||
|
Loading…
Reference in New Issue
Block a user