summaryrefslogtreecommitdiffstats
path: root/modules/multiplayer/editor/replication_editor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/multiplayer/editor/replication_editor.cpp')
-rw-r--r--modules/multiplayer/editor/replication_editor.cpp141
1 files changed, 77 insertions, 64 deletions
diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp
index 04aa856bf9..eab1f5d51d 100644
--- a/modules/multiplayer/editor/replication_editor.cpp
+++ b/modules/multiplayer/editor/replication_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/scene_tree_editor.h"
#include "editor/inspector_dock.h"
@@ -111,9 +112,9 @@ void ReplicationEditor::_pick_node_filter_input(const Ref<InputEvent> &p_ie) {
void ReplicationEditor::_pick_node_selected(NodePath p_path) {
Node *root = current->get_node(current->get_root_path());
- ERR_FAIL_COND(!root);
+ ERR_FAIL_NULL(root);
Node *node = get_node(p_path);
- ERR_FAIL_COND(!node);
+ ERR_FAIL_NULL(node);
NodePath path_to = root->get_path_to(node);
adding_node_path = path_to;
prop_selector->select_property_from_instance(node);
@@ -176,11 +177,6 @@ ReplicationEditor::ReplicationEditor() {
delete_dialog->connect("confirmed", callable_mp(this, &ReplicationEditor::_dialog_closed).bind(true));
add_child(delete_dialog);
- error_dialog = memnew(AcceptDialog);
- error_dialog->set_ok_button_text(TTR("Close"));
- error_dialog->set_title(TTR("Error!"));
- add_child(error_dialog);
-
VBoxContainer *vb = memnew(VBoxContainer);
vb->set_v_size_flags(SIZE_EXPAND_FILL);
add_child(vb);
@@ -249,42 +245,45 @@ ReplicationEditor::ReplicationEditor() {
add_pick_button->connect("pressed", callable_mp(this, &ReplicationEditor::_pick_new_property));
add_pick_button->set_text(TTR("Add property to sync..."));
hb->add_child(add_pick_button);
+
VSeparator *vs = memnew(VSeparator);
vs->set_custom_minimum_size(Size2(30 * EDSCALE, 0));
hb->add_child(vs);
hb->add_child(memnew(Label(TTR("Path:"))));
+
np_line_edit = memnew(LineEdit);
np_line_edit->set_placeholder(":property");
np_line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ np_line_edit->connect("text_submitted", callable_mp(this, &ReplicationEditor::_np_text_submitted));
hb->add_child(np_line_edit);
+
add_from_path_button = memnew(Button);
add_from_path_button->connect("pressed", callable_mp(this, &ReplicationEditor::_add_pressed));
add_from_path_button->set_text(TTR("Add from path"));
hb->add_child(add_from_path_button);
+
vs = memnew(VSeparator);
vs->set_custom_minimum_size(Size2(30 * EDSCALE, 0));
hb->add_child(vs);
+
pin = memnew(Button);
- pin->set_flat(true);
+ pin->set_theme_type_variation("FlatButton");
pin->set_toggle_mode(true);
hb->add_child(pin);
tree = memnew(Tree);
tree->set_hide_root(true);
- tree->set_columns(5);
+ tree->set_columns(4);
tree->set_column_titles_visible(true);
tree->set_column_title(0, TTR("Properties"));
tree->set_column_expand(0, true);
tree->set_column_title(1, TTR("Spawn"));
tree->set_column_expand(1, false);
tree->set_column_custom_minimum_width(1, 100);
- tree->set_column_title(2, TTR("Sync"));
+ tree->set_column_title(2, TTR("Replicate"));
tree->set_column_custom_minimum_width(2, 100);
- tree->set_column_title(3, TTR("Watch"));
- tree->set_column_custom_minimum_width(3, 100);
tree->set_column_expand(2, false);
tree->set_column_expand(3, false);
- tree->set_column_expand(4, false);
tree->create_item();
tree->connect("button_clicked", callable_mp(this, &ReplicationEditor::_tree_button_pressed));
tree->connect("item_edited", callable_mp(this, &ReplicationEditor::_tree_item_edited));
@@ -292,7 +291,7 @@ ReplicationEditor::ReplicationEditor() {
vb->add_child(tree);
drop_label = memnew(Label);
- drop_label->set_text(TTR("Add properties using the buttons above or\ndrag them them from the inspector and drop them here."));
+ drop_label->set_text(TTR("Add properties using the options above, or\ndrag them them from the inspector and drop them here."));
drop_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
drop_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
tree->add_child(drop_label);
@@ -303,7 +302,7 @@ ReplicationEditor::ReplicationEditor() {
void ReplicationEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_config"), &ReplicationEditor::_update_config);
- ClassDB::bind_method(D_METHOD("_update_checked", "property", "column", "checked"), &ReplicationEditor::_update_checked);
+ ClassDB::bind_method(D_METHOD("_update_value", "property", "column", "value"), &ReplicationEditor::_update_value);
}
bool ReplicationEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
@@ -365,25 +364,29 @@ void ReplicationEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("panel"), SNAME("Panel")));
- add_pick_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- pin->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
+ add_theme_style_override("panel", EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("panel"), SNAME("Panel")));
+ add_pick_button->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
+ pin->set_icon(get_theme_icon(SNAME("Pin"), EditorStringName(EditorIcons)));
} break;
}
}
void ReplicationEditor::_add_pressed() {
if (!current) {
- error_dialog->set_text(TTR("Please select a MultiplayerSynchronizer first."));
- error_dialog->popup_centered();
+ EditorNode::get_singleton()->show_warning(TTR("Please select a MultiplayerSynchronizer first."));
return;
}
if (current->get_root_path().is_empty()) {
- error_dialog->set_text(TTR("The MultiplayerSynchronizer needs a root path."));
- error_dialog->popup_centered();
+ EditorNode::get_singleton()->show_warning(TTR("The MultiplayerSynchronizer needs a root path."));
return;
}
String np_text = np_line_edit->get_text();
+
+ if (np_text.is_empty()) {
+ EditorNode::get_singleton()->show_warning(TTR("Property/path must not be empty."));
+ return;
+ }
+
int idx = np_text.find(":");
if (idx == -1) {
np_text = ".:" + np_text;
@@ -391,46 +394,54 @@ void ReplicationEditor::_add_pressed() {
np_text = "." + np_text;
}
NodePath path = NodePath(np_text);
+ if (path.is_empty()) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid property path: '%s'"), np_text));
+ return;
+ }
_add_sync_property(path);
}
+void ReplicationEditor::_np_text_submitted(const String &p_newtext) {
+ _add_pressed();
+}
+
void ReplicationEditor::_tree_item_edited() {
TreeItem *ti = tree->get_edited();
if (!ti || config.is_null()) {
return;
}
int column = tree->get_edited_column();
- ERR_FAIL_COND(column < 1 || column > 3);
+ ERR_FAIL_COND(column < 1 || column > 2);
const NodePath prop = ti->get_metadata(0);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- bool value = ti->is_checked(column);
- // We have a hard limit of 64 watchable properties per synchronizer.
- if (column == 3 && value && config->get_watch_properties().size() > 64) {
- error_dialog->set_text(TTR("Each MultiplayerSynchronizer can have no more than 64 watched properties."));
- error_dialog->popup_centered();
- ti->set_checked(column, false);
- return;
- }
- String method;
if (column == 1) {
undo_redo->create_action(TTR("Set spawn property"));
- method = "property_set_spawn";
+ bool value = ti->is_checked(column);
+ undo_redo->add_do_method(config.ptr(), "property_set_spawn", prop, value);
+ undo_redo->add_undo_method(config.ptr(), "property_set_spawn", prop, !value);
+ undo_redo->add_do_method(this, "_update_value", prop, column, value ? 1 : 0);
+ undo_redo->add_undo_method(this, "_update_value", prop, column, value ? 1 : 0);
+ undo_redo->commit_action();
} else if (column == 2) {
undo_redo->create_action(TTR("Set sync property"));
- method = "property_set_sync";
- } else if (column == 3) {
- undo_redo->create_action(TTR("Set watch property"));
- method = "property_set_watch";
+ int value = ti->get_range(column);
+ int old_value = config->property_get_replication_mode(prop);
+ // We have a hard limit of 64 watchable properties per synchronizer.
+ if (value == SceneReplicationConfig::REPLICATION_MODE_ON_CHANGE && config->get_watch_properties().size() >= 64) {
+ EditorNode::get_singleton()->show_warning(TTR("Each MultiplayerSynchronizer can have no more than 64 watched properties."));
+ ti->set_range(column, old_value);
+ return;
+ }
+ undo_redo->add_do_method(config.ptr(), "property_set_replication_mode", prop, value);
+ undo_redo->add_undo_method(config.ptr(), "property_set_replication_mode", prop, old_value);
+ undo_redo->add_do_method(this, "_update_value", prop, column, value);
+ undo_redo->add_undo_method(this, "_update_value", prop, column, old_value);
+ undo_redo->commit_action();
} else {
ERR_FAIL();
}
- undo_redo->add_do_method(config.ptr(), method, prop, value);
- undo_redo->add_undo_method(config.ptr(), method, prop, !value);
- undo_redo->add_do_method(this, "_update_checked", prop, column, value);
- undo_redo->add_undo_method(this, "_update_checked", prop, column, !value);
- undo_redo->commit_action();
}
void ReplicationEditor::_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button) {
@@ -455,15 +466,13 @@ void ReplicationEditor::_dialog_closed(bool p_confirmed) {
const NodePath prop = deleting;
int idx = config->property_get_index(prop);
bool spawn = config->property_get_spawn(prop);
- bool sync = config->property_get_sync(prop);
- bool watch = config->property_get_watch(prop);
+ SceneReplicationConfig::ReplicationMode mode = config->property_get_replication_mode(prop);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Remove Property"));
undo_redo->add_do_method(config.ptr(), "remove_property", prop);
undo_redo->add_undo_method(config.ptr(), "add_property", prop, idx);
undo_redo->add_undo_method(config.ptr(), "property_set_spawn", prop, spawn);
- undo_redo->add_undo_method(config.ptr(), "property_set_sync", prop, sync);
- undo_redo->add_undo_method(config.ptr(), "property_set_watch", prop, watch);
+ undo_redo->add_undo_method(config.ptr(), "property_set_replication_mode", prop, mode);
undo_redo->add_do_method(this, "_update_config");
undo_redo->add_undo_method(this, "_update_config");
undo_redo->commit_action();
@@ -471,14 +480,18 @@ void ReplicationEditor::_dialog_closed(bool p_confirmed) {
deleting = NodePath();
}
-void ReplicationEditor::_update_checked(const NodePath &p_prop, int p_column, bool p_checked) {
+void ReplicationEditor::_update_value(const NodePath &p_prop, int p_column, int p_value) {
if (!tree->get_root()) {
return;
}
TreeItem *ti = tree->get_root()->get_first_child();
while (ti) {
if (ti->get_metadata(0).operator NodePath() == p_prop) {
- ti->set_checked(p_column, p_checked);
+ if (p_column == 1) {
+ ti->set_checked(p_column, p_value != 0);
+ } else if (p_column == 2) {
+ ti->set_range(p_column, p_value);
+ }
return;
}
ti = ti->get_next();
@@ -499,7 +512,7 @@ void ReplicationEditor::_update_config() {
}
for (int i = 0; i < props.size(); i++) {
const NodePath path = props[i];
- _add_property(path, config->property_get_spawn(path), config->property_get_sync(path), config->property_get_watch(path));
+ _add_property(path, config->property_get_spawn(path), config->property_get_replication_mode(path));
}
}
@@ -517,10 +530,10 @@ void ReplicationEditor::edit(MultiplayerSynchronizer *p_sync) {
}
Ref<Texture2D> ReplicationEditor::_get_class_icon(const Node *p_node) {
- if (!p_node || !has_theme_icon(p_node->get_class(), "EditorIcons")) {
- return get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"));
+ if (!p_node || !has_theme_icon(p_node->get_class(), EditorStringName(EditorIcons))) {
+ return get_theme_icon(SNAME("ImportFail"), EditorStringName(EditorIcons));
}
- return get_theme_icon(p_node->get_class(), "EditorIcons");
+ return get_theme_icon(p_node->get_class(), EditorStringName(EditorIcons));
}
static bool can_sync(const Variant &p_var) {
@@ -541,14 +554,13 @@ static bool can_sync(const Variant &p_var) {
}
}
-void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, bool p_sync, bool p_watch) {
+void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, SceneReplicationConfig::ReplicationMode p_mode) {
String prop = String(p_property);
TreeItem *item = tree->create_item();
item->set_selectable(0, false);
item->set_selectable(1, false);
item->set_selectable(2, false);
item->set_selectable(3, false);
- item->set_selectable(4, false);
item->set_text(0, prop);
item->set_metadata(0, prop);
Node *root_node = current && !current->get_root_path().is_empty() ? current->get_node(current->get_root_path()) : nullptr;
@@ -565,22 +577,23 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn,
bool valid = false;
Variant value = node->get(subpath, &valid);
if (valid && !can_sync(value)) {
- item->set_icon(3, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
- item->set_tooltip_text(3, TTR("Property of this type not supported."));
+ item->set_icon(0, get_theme_icon(SNAME("StatusWarning"), EditorStringName(EditorIcons)));
+ item->set_tooltip_text(0, TTR("Property of this type not supported."));
+ } else {
+ item->set_icon(0, icon);
}
+ } else {
+ item->set_icon(0, icon);
}
- item->set_icon(0, icon);
- item->add_button(4, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ item->add_button(3, get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
item->set_text_alignment(1, HORIZONTAL_ALIGNMENT_CENTER);
item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK);
item->set_checked(1, p_spawn);
item->set_editable(1, true);
item->set_text_alignment(2, HORIZONTAL_ALIGNMENT_CENTER);
- item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
- item->set_checked(2, p_sync);
+ item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE);
+ item->set_range_config(2, 0, 2, 1);
+ item->set_text(2, "Never,Always,On Change");
+ item->set_range(2, (int)p_mode);
item->set_editable(2, true);
- item->set_text_alignment(3, HORIZONTAL_ALIGNMENT_CENTER);
- item->set_cell_mode(3, TreeItem::CELL_MODE_CHECK);
- item->set_checked(3, p_watch);
- item->set_editable(3, true);
}