summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/connections_dialog.cpp284
-rw-r--r--editor/connections_dialog.h73
-rw-r--r--editor/editor_asset_installer.cpp4
-rw-r--r--editor/editor_export.cpp9
-rw-r--r--editor/editor_export.h5
-rw-r--r--editor/editor_node.cpp7
-rw-r--r--editor/editor_resource_picker.cpp38
-rw-r--r--editor/export_template_manager.cpp6
-rw-r--r--editor/import_dock.cpp30
-rw-r--r--editor/import_dock.h3
-rw-r--r--editor/inspector_dock.h1
-rw-r--r--editor/node_dock.cpp1
-rw-r--r--editor/node_dock.h3
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp14
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp193
-rw-r--r--editor/plugins/node_3d_editor_plugin.h5
-rw-r--r--editor/plugins/script_text_editor.cpp18
-rw-r--r--editor/project_manager.cpp6
-rw-r--r--editor/scene_tree_dock.h1
19 files changed, 433 insertions, 268 deletions
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 606be7e154..0edbb182e1 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -38,6 +38,7 @@
#include "plugins/script_editor_plugin.h"
#include "scene/gui/label.h"
#include "scene/gui/popup_menu.h"
+#include "scene/gui/spin_box.h"
static Node *_find_first_script(Node *p_root, Node *p_node) {
if (p_node != p_root && p_node->get_owner() != p_root) {
@@ -164,6 +165,20 @@ void ConnectDialog::_tree_node_selected() {
_update_ok_enabled();
}
+void ConnectDialog::_unbind_count_changed(double p_count) {
+ for (Control *control : bind_controls) {
+ BaseButton *b = Object::cast_to<BaseButton>(control);
+ if (b) {
+ b->set_disabled(p_count > 0);
+ }
+
+ EditorInspector *e = Object::cast_to<EditorInspector>(control);
+ if (e) {
+ e->set_read_only(p_count > 0);
+ }
+ }
+}
+
/*
* Adds a new parameter bind to connection.
*/
@@ -305,6 +320,10 @@ void ConnectDialog::set_dst_method(const StringName &p_method) {
dst_method->set_text(p_method);
}
+int ConnectDialog::get_unbinds() const {
+ return int(unbind_count->get_value());
+}
+
Vector<Variant> ConnectDialog::get_binds() const {
return cdbinds->params;
}
@@ -321,7 +340,7 @@ bool ConnectDialog::get_oneshot() const {
* Returns true if ConnectDialog is being used to edit an existing connection.
*/
bool ConnectDialog::is_editing() const {
- return bEditMode;
+ return edit_mode;
}
/*
@@ -329,33 +348,35 @@ bool ConnectDialog::is_editing() const {
* If creating a connection from scratch, sensible defaults are used.
* If editing an existing connection, previous data is retained.
*/
-void ConnectDialog::init(ConnectionData c, bool bEdit) {
+void ConnectDialog::init(ConnectionData p_cd, bool p_edit) {
set_hide_on_ok(false);
- source = static_cast<Node *>(c.source);
- signal = c.signal;
+ source = static_cast<Node *>(p_cd.source);
+ signal = p_cd.signal;
tree->set_selected(nullptr);
tree->set_marked(source, true);
- if (c.target) {
- set_dst_node(static_cast<Node *>(c.target));
- set_dst_method(c.method);
+ if (p_cd.target) {
+ set_dst_node(static_cast<Node *>(p_cd.target));
+ set_dst_method(p_cd.method);
}
_update_ok_enabled();
- bool bDeferred = (c.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED;
- bool bOneshot = (c.flags & CONNECT_ONESHOT) == CONNECT_ONESHOT;
+ bool b_deferred = (p_cd.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED;
+ bool b_oneshot = (p_cd.flags & CONNECT_ONESHOT) == CONNECT_ONESHOT;
- deferred->set_pressed(bDeferred);
- oneshot->set_pressed(bOneshot);
+ deferred->set_pressed(b_deferred);
+ oneshot->set_pressed(b_oneshot);
+ unbind_count->set_value(p_cd.unbinds);
+ _unbind_count_changed(p_cd.unbinds);
cdbinds->params.clear();
- cdbinds->params = c.binds;
+ cdbinds->params = p_cd.binds;
cdbinds->notify_changed();
- bEditMode = bEdit;
+ edit_mode = p_edit;
}
void ConnectDialog::popup_dialog(const String &p_for_signal) {
@@ -449,23 +470,33 @@ ConnectDialog::ConnectDialog() {
type_list->add_item("Transform3D", Variant::TRANSFORM3D);
type_list->add_item("Color", Variant::COLOR);
type_list->select(0);
+ bind_controls.push_back(type_list);
Button *add_bind = memnew(Button);
add_bind->set_text(TTR("Add"));
add_bind_hb->add_child(add_bind);
add_bind->connect("pressed", callable_mp(this, &ConnectDialog::_add_bind));
+ bind_controls.push_back(add_bind);
Button *del_bind = memnew(Button);
del_bind->set_text(TTR("Remove"));
add_bind_hb->add_child(del_bind);
del_bind->connect("pressed", callable_mp(this, &ConnectDialog::_remove_bind));
+ bind_controls.push_back(del_bind);
vbc_right->add_margin_child(TTR("Add Extra Call Argument:"), add_bind_hb);
bind_editor = memnew(EditorInspector);
+ bind_controls.push_back(bind_editor);
vbc_right->add_margin_child(TTR("Extra Call Arguments:"), bind_editor, true);
+ unbind_count = memnew(SpinBox);
+ unbind_count->set_tooltip(TTR("Allows to drop arguments sent by signal emitter."));
+ unbind_count->connect("value_changed", callable_mp(this, &ConnectDialog::_unbind_count_changed));
+
+ vbc_right->add_margin_child(TTR("Unbind Signal Arguments:"), unbind_count);
+
HBoxContainer *dstm_hb = memnew(HBoxContainer);
vbc_left->add_margin_child(TTR("Receiver Method:"), dstm_hb);
@@ -515,7 +546,7 @@ Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const {
String text = TTR("Signal:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]";
text += p_text.get_slice("::", 1).strip_edges() + "\n";
text += p_text.get_slice("::", 2).strip_edges();
- help_bit->call_deferred(SNAME("set_text"), text); //hack so it uses proper theme once inside scene
+ help_bit->call_deferred(SNAME("set_text"), text); // Hack so it uses proper theme once inside scene.
return help_bit;
}
@@ -538,29 +569,32 @@ void ConnectionsDock::_make_or_edit_connection() {
ERR_FAIL_COND(!it);
NodePath dst_path = connect_dialog->get_dst_path();
- Node *target = selectedNode->get_node(dst_path);
+ Node *target = selected_node->get_node(dst_path);
ERR_FAIL_COND(!target);
- ConnectDialog::ConnectionData cToMake;
- cToMake.source = connect_dialog->get_source();
- cToMake.target = target;
- cToMake.signal = connect_dialog->get_signal_name();
- cToMake.method = connect_dialog->get_dst_method_name();
- cToMake.binds = connect_dialog->get_binds();
- bool defer = connect_dialog->get_deferred();
- bool oshot = connect_dialog->get_oneshot();
- cToMake.flags = CONNECT_PERSIST | (defer ? CONNECT_DEFERRED : 0) | (oshot ? CONNECT_ONESHOT : 0);
+ ConnectDialog::ConnectionData cd;
+ cd.source = connect_dialog->get_source();
+ cd.target = target;
+ cd.signal = connect_dialog->get_signal_name();
+ cd.method = connect_dialog->get_dst_method_name();
+ cd.unbinds = connect_dialog->get_unbinds();
+ if (cd.unbinds == 0) {
+ cd.binds = connect_dialog->get_binds();
+ }
+ bool b_deferred = connect_dialog->get_deferred();
+ bool b_oneshot = connect_dialog->get_oneshot();
+ cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONESHOT : 0);
// Conditions to add function: must have a script and must not have the method already
// (in the class, the script itself, or inherited).
bool add_script_function = false;
Ref<Script> script = target->get_script();
- if (!target->get_script().is_null() && !ClassDB::has_method(target->get_class(), cToMake.method)) {
+ if (!target->get_script().is_null() && !ClassDB::has_method(target->get_class(), cd.method)) {
// There is a chance that the method is inherited from another script.
bool found_inherited_function = false;
Ref<Script> inherited_script = script->get_base_script();
while (!inherited_script.is_null()) {
- int line = inherited_script->get_language()->find_function(cToMake.method, inherited_script->get_source_code());
+ int line = inherited_script->get_language()->find_function(cd.method, inherited_script->get_source_code());
if (line != -1) {
found_inherited_function = true;
break;
@@ -575,23 +609,23 @@ void ConnectionsDock::_make_or_edit_connection() {
if (add_script_function) {
// Pick up args here before "it" is deleted by update_tree.
script_function_args = it->get_metadata(0).operator Dictionary()["args"];
- for (int i = 0; i < cToMake.binds.size(); i++) {
- script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cToMake.binds[i].get_type()));
+ for (int i = 0; i < cd.binds.size(); i++) {
+ script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type()));
}
}
if (connect_dialog->is_editing()) {
_disconnect(*it);
- _connect(cToMake);
+ _connect(cd);
} else {
- _connect(cToMake);
+ _connect(cd);
}
// IMPORTANT NOTE: _disconnect and _connect cause an update_tree, which will delete the object "it" is pointing to.
it = nullptr;
if (add_script_function) {
- editor->emit_signal(SNAME("script_add_function_request"), target, cToMake.method, script_function_args);
+ editor->emit_signal(SNAME("script_add_function_request"), target, cd.method, script_function_args);
hide();
}
@@ -601,23 +635,21 @@ void ConnectionsDock::_make_or_edit_connection() {
/*
* Creates single connection w/ undo-redo functionality.
*/
-void ConnectionsDock::_connect(ConnectDialog::ConnectionData cToMake) {
- Node *source = static_cast<Node *>(cToMake.source);
- Node *target = static_cast<Node *>(cToMake.target);
+void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) {
+ Node *source = Object::cast_to<Node>(p_cd.source);
+ Node *target = Object::cast_to<Node>(p_cd.target);
if (!source || !target) {
return;
}
- undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(cToMake.signal), String(cToMake.method)));
-
- Callable c(target, cToMake.method);
-
- undo_redo->add_do_method(source, "connect", cToMake.signal, c, cToMake.binds, cToMake.flags);
- undo_redo->add_undo_method(source, "disconnect", cToMake.signal, c);
+ Callable callable = p_cd.get_callable();
+ undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(p_cd.signal), String(p_cd.method)));
+ undo_redo->add_do_method(source, "connect", p_cd.signal, callable, varray(), p_cd.flags);
+ undo_redo->add_undo_method(source, "disconnect", p_cd.signal, callable);
undo_redo->add_do_method(this, "update_tree");
undo_redo->add_undo_method(this, "update_tree");
- undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); //to force redraw of scene tree
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); // To force redraw of scene tree.
undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
undo_redo->commit_action();
@@ -626,16 +658,17 @@ void ConnectionsDock::_connect(ConnectDialog::ConnectionData cToMake) {
/*
* Break single connection w/ undo-redo functionality.
*/
-void ConnectionsDock::_disconnect(TreeItem &item) {
- Connection cd = item.get_metadata(0);
- ConnectDialog::ConnectionData c = cd;
+void ConnectionsDock::_disconnect(TreeItem &p_item) {
+ Connection connection = p_item.get_metadata(0);
+ ConnectDialog::ConnectionData cd = connection;
- ERR_FAIL_COND(c.source != selectedNode); // Shouldn't happen but... Bugcheck.
+ ERR_FAIL_COND(cd.source != selected_node); // Shouldn't happen but... Bugcheck.
- undo_redo->create_action(vformat(TTR("Disconnect '%s' from '%s'"), c.signal, c.method));
+ undo_redo->create_action(vformat(TTR("Disconnect '%s' from '%s'"), cd.signal, cd.method));
- undo_redo->add_do_method(selectedNode, "disconnect", c.signal, Callable(c.target, c.method));
- undo_redo->add_undo_method(selectedNode, "connect", c.signal, Callable(c.target, c.method), c.binds, c.flags);
+ Callable callable = cd.get_callable();
+ undo_redo->add_do_method(selected_node, "disconnect", cd.signal, callable);
+ undo_redo->add_undo_method(selected_node, "connect", cd.signal, callable, cd.binds, cd.flags);
undo_redo->add_do_method(this, "update_tree");
undo_redo->add_undo_method(this, "update_tree");
undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); // To force redraw of scene tree.
@@ -656,14 +689,14 @@ void ConnectionsDock::_disconnect_all() {
}
TreeItem *child = item->get_first_child();
- String signalName = item->get_metadata(0).operator Dictionary()["name"];
- undo_redo->create_action(vformat(TTR("Disconnect all from signal: '%s'"), signalName));
+ String signal_name = item->get_metadata(0).operator Dictionary()["name"];
+ undo_redo->create_action(vformat(TTR("Disconnect all from signal: '%s'"), signal_name));
while (child) {
- Connection cd = child->get_metadata(0);
- ConnectDialog::ConnectionData c = cd;
- undo_redo->add_do_method(selectedNode, "disconnect", c.signal, Callable(c.target, c.method));
- undo_redo->add_undo_method(selectedNode, "connect", c.signal, Callable(c.target, c.method), c.binds, c.flags);
+ Connection connection = child->get_metadata(0);
+ ConnectDialog::ConnectionData cd = connection;
+ undo_redo->add_do_method(selected_node, "disconnect", cd.signal, cd.get_callable());
+ undo_redo->add_undo_method(selected_node, "connect", cd.signal, cd.get_callable(), cd.binds, cd.flags);
child = child->get_next();
}
@@ -704,100 +737,118 @@ void ConnectionsDock::_tree_item_activated() { // "Activation" on double-click.
}
}
-bool ConnectionsDock::_is_item_signal(TreeItem &item) {
- return (item.get_parent() == tree->get_root() || item.get_parent()->get_parent() == tree->get_root());
+bool ConnectionsDock::_is_item_signal(TreeItem &p_item) {
+ return (p_item.get_parent() == tree->get_root() || p_item.get_parent()->get_parent() == tree->get_root());
}
/*
* Open connection dialog with TreeItem data to CREATE a brand-new connection.
*/
-void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
- String signal = item.get_metadata(0).operator Dictionary()["name"];
- const String &signalname = signal;
- String midname = selectedNode->get_name();
- for (int i = 0; i < midname.length(); i++) { //TODO: Regex filter may be cleaner.
- char32_t c = midname[i];
+void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
+ String signal_name = p_item.get_metadata(0).operator Dictionary()["name"];
+ const String &signal_name_ref = signal_name;
+ String node_name = selected_node->get_name();
+ for (int i = 0; i < node_name.length(); i++) { // TODO: Regex filter may be cleaner.
+ char32_t c = node_name[i];
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) {
if (c == ' ') {
// Replace spaces with underlines.
c = '_';
} else {
// Remove any other characters.
- midname.remove_at(i);
+ node_name.remove_at(i);
i--;
continue;
}
}
- midname[i] = c;
+ node_name[i] = c;
}
- Node *dst_node = selectedNode->get_owner() ? selectedNode->get_owner() : selectedNode;
+ Node *dst_node = selected_node->get_owner() ? selected_node->get_owner() : selected_node;
if (!dst_node || dst_node->get_script().is_null()) {
dst_node = _find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root());
}
- StringName dst_method = "_on_" + midname + "_" + signal;
+ Dictionary subst;
- ConnectDialog::ConnectionData c;
- c.source = selectedNode;
- c.signal = StringName(signalname);
- c.target = dst_node;
- c.method = dst_method;
- connect_dialog->popup_dialog(signalname);
- connect_dialog->init(c);
+ String s = node_name.capitalize().replace(" ", "");
+ subst["NodeName"] = s;
+ if (!s.is_empty()) {
+ s[0] = s.to_lower()[0];
+ }
+ subst["nodeName"] = s;
+ subst["node_name"] = node_name.capitalize().replace(" ", "_").to_lower();
+
+ s = signal_name.capitalize().replace(" ", "");
+ subst["SignalName"] = s;
+ if (!s.is_empty()) {
+ s[0] = s.to_lower()[0];
+ }
+ subst["signalName"] = s;
+ subst["signal_name"] = signal_name.capitalize().replace(" ", "_").to_lower();
+
+ String dst_method = String(EDITOR_GET("interface/editors/default_signal_callback_name")).format(subst);
+
+ ConnectDialog::ConnectionData cd;
+ cd.source = selected_node;
+ cd.signal = StringName(signal_name_ref);
+ cd.target = dst_node;
+ cd.method = StringName(dst_method);
+ connect_dialog->popup_dialog(signal_name_ref);
+ connect_dialog->init(cd);
connect_dialog->set_title(TTR("Connect a Signal to a Method"));
}
/*
* Open connection dialog with Connection data to EDIT an existing connection.
*/
-void ConnectionsDock::_open_connection_dialog(ConnectDialog::ConnectionData cToEdit) {
- Node *src = static_cast<Node *>(cToEdit.source);
- Node *dst = static_cast<Node *>(cToEdit.target);
+void ConnectionsDock::_open_connection_dialog(ConnectDialog::ConnectionData p_cd) {
+ Node *src = Object::cast_to<Node>(p_cd.source);
+ Node *dst = Object::cast_to<Node>(p_cd.target);
if (src && dst) {
- const String &signalname = cToEdit.signal;
- connect_dialog->set_title(TTR("Edit Connection:") + cToEdit.signal);
- connect_dialog->popup_dialog(signalname);
- connect_dialog->init(cToEdit, true);
+ const String &signal_name_ref = p_cd.signal;
+ connect_dialog->set_title(TTR("Edit Connection:") + p_cd.signal);
+ connect_dialog->popup_dialog(signal_name_ref);
+ connect_dialog->init(p_cd, true);
}
}
/*
* Open slot method location in script editor.
*/
-void ConnectionsDock::_go_to_script(TreeItem &item) {
- if (_is_item_signal(item)) {
+void ConnectionsDock::_go_to_script(TreeItem &p_item) {
+ if (_is_item_signal(p_item)) {
return;
}
- Connection cd = item.get_metadata(0);
- ConnectDialog::ConnectionData c = cd;
- ERR_FAIL_COND(c.source != selectedNode); //shouldn't happen but...bugcheck
+ Connection connection = p_item.get_metadata(0);
+ ConnectDialog::ConnectionData cd = connection;
+ ERR_FAIL_COND(cd.source != selected_node); // Shouldn't happen but... bugcheck.
- if (!c.target) {
+ if (!cd.target) {
return;
}
- Ref<Script> script = c.target->get_script();
+ Ref<Script> script = cd.target->get_script();
if (script.is_null()) {
return;
}
- if (script.is_valid() && ScriptEditor::get_singleton()->script_goto_method(script, c.method)) {
+ if (script.is_valid() && ScriptEditor::get_singleton()->script_goto_method(script, cd.method)) {
editor->call("_editor_select", EditorNode::EDITOR_SCRIPT);
}
}
-void ConnectionsDock::_handle_signal_menu_option(int option) {
+void ConnectionsDock::_handle_signal_menu_option(int p_option) {
TreeItem *item = tree->get_selected();
if (!item) {
return;
}
- switch (option) {
+ switch (p_option) {
case CONNECT: {
_open_connection_dialog(*item);
} break;
@@ -809,17 +860,17 @@ void ConnectionsDock::_handle_signal_menu_option(int option) {
}
}
-void ConnectionsDock::_handle_slot_menu_option(int option) {
+void ConnectionsDock::_handle_slot_menu_option(int p_option) {
TreeItem *item = tree->get_selected();
if (!item) {
return;
}
- switch (option) {
+ switch (p_option) {
case EDIT: {
- Connection c = item->get_metadata(0);
- _open_connection_dialog(c);
+ Connection connection = item->get_metadata(0);
+ _open_connection_dialog(connection);
} break;
case GO_TO_SCRIPT: {
_go_to_script(*item);
@@ -831,14 +882,14 @@ void ConnectionsDock::_handle_slot_menu_option(int option) {
}
}
-void ConnectionsDock::_rmb_pressed(Vector2 position) {
+void ConnectionsDock::_rmb_pressed(Vector2 p_position) {
TreeItem *item = tree->get_selected();
if (!item) {
return;
}
- Vector2 screen_position = tree->get_screen_position() + position;
+ Vector2 screen_position = tree->get_screen_position() + p_position;
if (_is_item_signal(*item)) {
signal_menu->set_position(screen_position);
@@ -881,14 +932,14 @@ void ConnectionsDock::_bind_methods() {
}
void ConnectionsDock::set_node(Node *p_node) {
- selectedNode = p_node;
+ selected_node = p_node;
update_tree();
}
void ConnectionsDock::update_tree() {
tree->clear();
- if (!selectedNode) {
+ if (!selected_node) {
return;
}
@@ -896,10 +947,10 @@ void ConnectionsDock::update_tree() {
List<MethodInfo> node_signals;
- selectedNode->get_signal_list(&node_signals);
+ selected_node->get_signal_list(&node_signals);
bool did_script = false;
- StringName base = selectedNode->get_class();
+ StringName base = selected_node->get_class();
while (base) {
List<MethodInfo> node_signals2;
@@ -908,7 +959,7 @@ void ConnectionsDock::update_tree() {
if (!did_script) {
// Get script signals (including signals from any base scripts).
- Ref<Script> scr = selectedNode->get_script();
+ Ref<Script> scr = selected_node->get_script();
if (scr.is_valid()) {
scr->get_script_signal_list(&node_signals2);
if (scr->get_path().is_resource_file()) {
@@ -1021,44 +1072,45 @@ void ConnectionsDock::update_tree() {
signal_item->set_tooltip(0, String(signal_name) + "::" + signaldesc + "::" + descr);
}
- // List existing connections
+ // List existing connections.
List<Object::Connection> connections;
- selectedNode->get_signal_connection_list(signal_name, &connections);
+ selected_node->get_signal_connection_list(signal_name, &connections);
for (const Object::Connection &F : connections) {
- Connection cn = F;
- if (!(cn.flags & CONNECT_PERSIST)) {
+ Connection connection = F;
+ if (!(connection.flags & CONNECT_PERSIST)) {
continue;
}
- ConnectDialog::ConnectionData c = cn;
+ ConnectDialog::ConnectionData cd = connection;
- Node *target = Object::cast_to<Node>(c.target);
+ Node *target = Object::cast_to<Node>(cd.target);
if (!target) {
continue;
}
- String path = String(selectedNode->get_path_to(target)) + " :: " + c.method + "()";
- if (c.flags & CONNECT_DEFERRED) {
+ String path = String(selected_node->get_path_to(target)) + " :: " + cd.method + "()";
+ if (cd.flags & CONNECT_DEFERRED) {
path += " (deferred)";
}
- if (c.flags & CONNECT_ONESHOT) {
+ if (cd.flags & CONNECT_ONESHOT) {
path += " (oneshot)";
}
- if (c.binds.size()) {
+ if (cd.unbinds > 0) {
+ path += " unbinds(" + itos(cd.unbinds) + ")";
+ } else if (!cd.binds.is_empty()) {
path += " binds(";
- for (int i = 0; i < c.binds.size(); i++) {
+ for (int i = 0; i < cd.binds.size(); i++) {
if (i > 0) {
path += ", ";
}
- path += c.binds[i].operator String();
+ path += cd.binds[i].operator String();
}
path += ")";
}
TreeItem *connection_item = tree->create_item(signal_item);
connection_item->set_text(0, path);
- Connection cd = c;
- connection_item->set_metadata(0, cd);
+ connection_item->set_metadata(0, connection);
connection_item->set_icon(0, get_theme_icon(SNAME("Slot"), SNAME("EditorIcons")));
}
}
@@ -1130,6 +1182,8 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) {
tree->connect("item_rmb_selected", callable_mp(this, &ConnectionsDock::_rmb_pressed));
add_theme_constant_override("separation", 3 * EDSCALE);
+
+ EDITOR_DEF("interface/editors/default_signal_callback_name", "_on_{node_name}_{signal_name}");
}
ConnectionsDock::~ConnectionsDock() {
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 5154cc90f1..2759c6cfde 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -48,6 +48,7 @@
class PopupMenu;
class ConnectDialogBinds;
+class SpinBox;
class ConnectDialog : public ConfirmationDialog {
GDCLASS(ConnectDialog, ConfirmationDialog);
@@ -59,25 +60,45 @@ public:
StringName signal;
StringName method;
uint32_t flags = 0;
+ int unbinds = 0;
Vector<Variant> binds;
- ConnectionData() {
- }
+ ConnectionData() {}
+
ConnectionData(const Connection &p_connection) {
source = Object::cast_to<Node>(p_connection.signal.get_object());
signal = p_connection.signal.get_name();
target = Object::cast_to<Node>(p_connection.callable.get_object());
- method = p_connection.callable.get_method();
flags = p_connection.flags;
- binds = p_connection.binds;
+
+ Callable base_callable;
+ if (p_connection.callable.is_custom()) {
+ CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(p_connection.callable.get_custom());
+ if (ccb) {
+ binds = ccb->get_binds();
+ base_callable = ccb->get_callable();
+ }
+
+ CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(p_connection.callable.get_custom());
+ if (ccu) {
+ unbinds = ccu->get_unbinds();
+ base_callable = ccu->get_callable();
+ }
+ } else {
+ base_callable = p_connection.callable;
+ }
+ method = base_callable.get_method();
}
- operator Connection() {
- Connection c;
- c.signal = ::Signal(source, signal);
- c.callable = Callable(target, method);
- c.flags = flags;
- c.binds = binds;
- return c;
+
+ Callable get_callable() {
+ if (unbinds > 0) {
+ return Callable(target, method).unbind(unbinds);
+ } else if (!binds.is_empty()) {
+ const Variant *args = binds.ptr();
+ return Callable(target, method).bind(&args, binds.size());
+ } else {
+ return Callable(target, method);
+ }
}
};
@@ -88,25 +109,28 @@ private:
StringName signal;
LineEdit *dst_method;
ConnectDialogBinds *cdbinds;
- bool bEditMode;
+ bool edit_mode;
NodePath dst_path;
VBoxContainer *vbc_right;
SceneTreeEditor *tree;
AcceptDialog *error;
+ SpinBox *unbind_count;
EditorInspector *bind_editor;
OptionButton *type_list;
CheckBox *deferred;
CheckBox *oneshot;
CheckButton *advanced;
+ Vector<Control *> bind_controls;
Label *error_label;
void ok_pressed() override;
void _cancel_pressed();
void _item_activated();
- void _text_submitted(const String &_text);
+ void _text_submitted(const String &p_text);
void _tree_node_selected();
+ void _unbind_count_changed(double p_count);
void _add_bind();
void _remove_bind();
void _advanced_pressed();
@@ -123,13 +147,14 @@ public:
void set_dst_node(Node *p_node);
StringName get_dst_method_name() const;
void set_dst_method(const StringName &p_method);
+ int get_unbinds() const;
Vector<Variant> get_binds() const;
bool get_deferred() const;
bool get_oneshot() const;
bool is_editing() const;
- void init(ConnectionData c, bool bEdit = false);
+ void init(ConnectionData p_cd, bool p_edit = false);
void popup_dialog(const String &p_for_signal);
ConnectDialog();
@@ -159,7 +184,7 @@ class ConnectionsDock : public VBoxContainer {
DISCONNECT
};
- Node *selectedNode;
+ Node *selected_node;
ConnectionsDockTree *tree;
EditorNode *editor;
@@ -176,21 +201,21 @@ class ConnectionsDock : public VBoxContainer {
void _filter_changed(const String &p_text);
void _make_or_edit_connection();
- void _connect(ConnectDialog::ConnectionData cToMake);
- void _disconnect(TreeItem &item);
+ void _connect(ConnectDialog::ConnectionData p_cd);
+ void _disconnect(TreeItem &p_item);
void _disconnect_all();
void _tree_item_selected();
void _tree_item_activated();
- bool _is_item_signal(TreeItem &item);
+ bool _is_item_signal(TreeItem &p_item);
- void _open_connection_dialog(TreeItem &item);
- void _open_connection_dialog(ConnectDialog::ConnectionData cToEdit);
- void _go_to_script(TreeItem &item);
+ void _open_connection_dialog(TreeItem &p_item);
+ void _open_connection_dialog(ConnectDialog::ConnectionData p_cd);
+ void _go_to_script(TreeItem &p_item);
- void _handle_signal_menu_option(int option);
- void _handle_slot_menu_option(int option);
- void _rmb_pressed(Vector2 position);
+ void _handle_signal_menu_option(int p_option);
+ void _handle_slot_menu_option(int p_option);
+ void _rmb_pressed(Vector2 p_position);
void _close();
protected:
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 4d6b2e2750..1de67149c6 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -124,7 +124,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
char fname[16384];
unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String name = fname;
+ String name = String::utf8(fname);
files_sorted.insert(name);
ret = unzGoToNextFile(pkg);
@@ -303,7 +303,7 @@ void EditorAssetInstaller::ok_pressed() {
char fname[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String name = fname;
+ String name = String::utf8(fname);
if (status_map.has(name) && status_map[name]->is_checked(0)) {
String path = status_map[name]->get_metadata(0);
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index d681074bf5..014e27ae15 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -620,6 +620,14 @@ String EditorExportPlugin::get_ios_cpp_code() const {
return ios_cpp_code;
}
+void EditorExportPlugin::add_osx_plugin_file(const String &p_path) {
+ osx_plugin_files.push_back(p_path);
+}
+
+const Vector<String> &EditorExportPlugin::get_osx_plugin_files() const {
+ return osx_plugin_files;
+}
+
void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) {
ios_project_static_libs.push_back(p_path);
}
@@ -660,6 +668,7 @@ void EditorExportPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
+ ClassDB::bind_method(D_METHOD("add_osx_plugin_file", "path"), &EditorExportPlugin::add_osx_plugin_file);
ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
GDVIRTUAL_BIND(_export_file, "path", "type", "features");
diff --git a/editor/editor_export.h b/editor/editor_export.h
index fd885ad313..3d46ae1996 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -308,6 +308,8 @@ class EditorExportPlugin : public RefCounted {
Vector<String> ios_bundle_files;
String ios_cpp_code;
+ Vector<String> osx_plugin_files;
+
_FORCE_INLINE_ void _clear() {
shared_objects.clear();
extra_files.clear();
@@ -321,6 +323,7 @@ class EditorExportPlugin : public RefCounted {
ios_plist_content = "";
ios_linker_flags = "";
ios_cpp_code = "";
+ osx_plugin_files.clear();
}
void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features);
@@ -341,6 +344,7 @@ protected:
void add_ios_linker_flags(const String &p_flags);
void add_ios_bundle_file(const String &p_path);
void add_ios_cpp_code(const String &p_code);
+ void add_osx_plugin_file(const String &p_path);
void skip();
@@ -361,6 +365,7 @@ public:
String get_ios_linker_flags() const;
Vector<String> get_ios_bundle_files() const;
String get_ios_cpp_code() const;
+ const Vector<String> &get_osx_plugin_files() const;
EditorExportPlugin();
};
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index ed7779bf7d..cca8bc1b29 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -522,8 +522,8 @@ void EditorNode::_update_from_settings() {
Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/2d/sdf/scale")));
scene_root->set_sdf_scale(sdf_scale);
- float lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
- scene_root->set_lod_threshold(lod_threshold);
+ float mesh_lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
+ scene_root->set_mesh_lod_threshold(mesh_lod_threshold);
RS::get_singleton()->decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
RS::get_singleton()->light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
@@ -2272,7 +2272,8 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
if (main_plugin) {
// special case if use of external editor is true
- if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && res && !res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) {
+ Resource *current_res = Object::cast_to<Resource>(current_obj);
+ if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && current_res && !current_res->is_built_in() && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) {
if (!changing_scene) {
main_plugin->edit(current_obj);
}
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index b20aee82e6..421d16313a 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -49,6 +49,7 @@ void EditorResourcePicker::_update_resource() {
if (edited_resource == RES()) {
assign_button->set_icon(Ref<Texture2D>());
assign_button->set_text(TTR("[empty]"));
+ assign_button->set_tooltip("");
} else {
assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object"));
@@ -56,14 +57,15 @@ void EditorResourcePicker::_update_resource() {
assign_button->set_text(edited_resource->get_name());
} else if (edited_resource->get_path().is_resource_file()) {
assign_button->set_text(edited_resource->get_path().get_file());
- assign_button->set_tooltip(edited_resource->get_path());
} else {
assign_button->set_text(edited_resource->get_class());
}
+ String resource_path;
if (edited_resource->get_path().is_resource_file()) {
- assign_button->set_tooltip(edited_resource->get_path());
+ resource_path = edited_resource->get_path() + "\n";
}
+ assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class());
// Preview will override the above, so called at the end.
EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id());
@@ -514,12 +516,14 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, Set<String> *
}
if (p_with_convert) {
- if (base == "StandardMaterial3D") {
+ if (base == "BaseMaterial3D") {
p_vector->insert("Texture2D");
} else if (base == "ShaderMaterial") {
p_vector->insert("Shader");
} else if (base == "Font") {
p_vector->insert("FontData");
+ } else if (base == "Texture2D") {
+ p_vector->insert("Image");
}
}
}
@@ -636,26 +640,46 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_
for (Set<String>::Element *E = allowed_types.front(); E; E = E->next()) {
String at = E->get().strip_edges();
- if (at == "StandardMaterial3D" && ClassDB::is_parent_class(dropped_resource->get_class(), "Texture2D")) {
- Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
+ if (at == "BaseMaterial3D" && ClassDB::is_parent_class(dropped_resource->get_class(), "Texture2D")) {
+ // Use existing resource if possible and only replace its data.
+ Ref<StandardMaterial3D> mat = edited_resource;
+ if (!mat.is_valid()) {
+ mat.instantiate();
+ }
mat->set_texture(StandardMaterial3D::TextureParam::TEXTURE_ALBEDO, dropped_resource);
dropped_resource = mat;
break;
}
if (at == "ShaderMaterial" && ClassDB::is_parent_class(dropped_resource->get_class(), "Shader")) {
- Ref<ShaderMaterial> mat = memnew(ShaderMaterial);
+ Ref<ShaderMaterial> mat = edited_resource;
+ if (!mat.is_valid()) {
+ mat.instantiate();
+ }
mat->set_shader(dropped_resource);
dropped_resource = mat;
break;
}
if (at == "Font" && ClassDB::is_parent_class(dropped_resource->get_class(), "FontData")) {
- Ref<Font> font = memnew(Font);
+ Ref<Font> font = edited_resource;
+ if (!font.is_valid()) {
+ font.instantiate();
+ }
font->add_data(dropped_resource);
dropped_resource = font;
break;
}
+
+ if (at == "Texture2D" && ClassDB::is_parent_class(dropped_resource->get_class(), "Image")) {
+ Ref<ImageTexture> texture = edited_resource;
+ if (!texture.is_valid()) {
+ texture.instantiate();
+ }
+ texture->create_from_image(dropped_resource);
+ dropped_resource = texture;
+ break;
+ }
}
}
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index f12a851388..8c34609e9c 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -396,7 +396,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
char fname[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String file = fname;
+ String file = String::utf8(fname);
if (file.ends_with("version.txt")) {
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
@@ -457,7 +457,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
char fname[16384];
unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String file_path(String(fname).simplify_path());
+ String file_path(String::utf8(fname).simplify_path());
String file = file_path.get_file();
@@ -698,7 +698,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
char fpath[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fpath, 16384, nullptr, 0, nullptr, 0);
- String path = fpath;
+ String path = String::utf8(fpath);
String base_dir = path.get_base_dir();
if (!path.ends_with("/")) {
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 09c02465a7..ab1be7f41b 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -31,6 +31,7 @@
#include "import_dock.h"
#include "editor_node.h"
#include "editor_resource_preview.h"
+#include "editor_scale.h"
class ImportDockParameters : public Object {
GDCLASS(ImportDockParameters, Object);
@@ -135,6 +136,8 @@ void ImportDock::set_edit_path(const String &p_path) {
_set_dirty(false);
import_as->set_disabled(false);
preset->set_disabled(false);
+ content->show();
+ select_a_resource->hide();
imported->set_text(p_path.get_file());
}
@@ -423,6 +426,8 @@ void ImportDock::clear() {
params->properties.clear();
params->update();
preset->get_popup()->clear();
+ content->hide();
+ select_a_resource->show();
}
static bool _find_owners(EditorFileSystemDirectory *efsd, const String &p_path) {
@@ -600,12 +605,18 @@ void ImportDock::initialize_import_options() const {
ImportDock::ImportDock() {
set_name("Import");
+
+ content = memnew(VBoxContainer);
+ content->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(content);
+ content->hide();
+
imported = memnew(Label);
imported->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")));
imported->set_clip_text(true);
- add_child(imported);
+ content->add_child(imported);
HBoxContainer *hb = memnew(HBoxContainer);
- add_margin_child(TTR("Import As:"), hb);
+ content->add_margin_child(TTR("Import As:"), hb);
import_as = memnew(OptionButton);
import_as->set_disabled(true);
import_as->connect("item_selected", callable_mp(this, &ImportDock::_importer_selected));
@@ -618,13 +629,13 @@ ImportDock::ImportDock() {
hb->add_child(preset);
import_opts = memnew(EditorInspector);
- add_child(import_opts);
+ content->add_child(import_opts);
import_opts->set_v_size_flags(SIZE_EXPAND_FILL);
import_opts->connect("property_edited", callable_mp(this, &ImportDock::_property_edited));
import_opts->connect("property_toggled", callable_mp(this, &ImportDock::_property_toggled));
hb = memnew(HBoxContainer);
- add_child(hb);
+ content->add_child(hb);
import = memnew(Button);
import->set_text(TTR("Reimport"));
import->set_disabled(true);
@@ -652,7 +663,7 @@ ImportDock::ImportDock() {
reimport_confirm = memnew(ConfirmationDialog);
reimport_confirm->get_ok_button()->set_text(TTR("Save Scenes, Re-Import, and Restart"));
- add_child(reimport_confirm);
+ content->add_child(reimport_confirm);
reimport_confirm->connect("confirmed", callable_mp(this, &ImportDock::_reimport_and_restart));
VBoxContainer *vbc_confirm = memnew(VBoxContainer());
@@ -662,6 +673,15 @@ ImportDock::ImportDock() {
reimport_confirm->add_child(vbc_confirm);
params = memnew(ImportDockParameters);
+
+ select_a_resource = memnew(Label);
+ select_a_resource->set_text(TTR("Select a resource file in the filesystem or in the inspector to adjust import settings."));
+ select_a_resource->set_autowrap_mode(Label::AUTOWRAP_WORD);
+ select_a_resource->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
+ select_a_resource->set_v_size_flags(SIZE_EXPAND_FILL);
+ select_a_resource->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ select_a_resource->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
+ add_child(select_a_resource);
}
ImportDock::~ImportDock() {
diff --git a/editor/import_dock.h b/editor/import_dock.h
index d21f0d507d..33fc23f1b4 100644
--- a/editor/import_dock.h
+++ b/editor/import_dock.h
@@ -62,6 +62,9 @@ class ImportDock : public VBoxContainer {
ImportDockParameters *params;
+ VBoxContainer *content;
+ Label *select_a_resource;
+
void _preset_selected(int p_idx);
void _importer_selected(int i_idx);
void _update_options(const String &p_path, const Ref<ConfigFile> &p_config = Ref<ConfigFile>());
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index a20e10005d..94e4f67348 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -32,7 +32,6 @@
#define INSPECTOR_DOCK_H
#include "editor/animation_track_editor.h"
-#include "editor/connections_dialog.h"
#include "editor/create_dialog.h"
#include "editor/editor_data.h"
#include "editor/editor_inspector.h"
diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp
index 215138a4df..d8f16b367a 100644
--- a/editor/node_dock.cpp
+++ b/editor/node_dock.cpp
@@ -30,6 +30,7 @@
#include "node_dock.h"
+#include "connections_dialog.h"
#include "editor_node.h"
#include "editor_scale.h"
diff --git a/editor/node_dock.h b/editor/node_dock.h
index cef1561e8e..b35be8de8a 100644
--- a/editor/node_dock.h
+++ b/editor/node_dock.h
@@ -31,9 +31,10 @@
#ifndef NODE_DOCK_H
#define NODE_DOCK_H
-#include "connections_dialog.h"
#include "groups_editor.h"
+class ConnectionsDock;
+
class NodeDock : public VBoxContainer {
GDCLASS(NodeDock, VBoxContainer);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index d6fd153665..089c37d7a6 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2097,8 +2097,16 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
(k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::LEFT || k->get_keycode() == Key::RIGHT)) {
if (!k->is_echo()) {
- // Start moving the canvas items with the keyboard
- drag_selection = _get_edited_canvas_items();
+ // Start moving the canvas items with the keyboard, if they are movable
+ List<CanvasItem *> selection = _get_edited_canvas_items();
+
+ drag_selection.clear();
+ for (CanvasItem *item : selection) {
+ if (_is_node_movable(item, true)) {
+ drag_selection.push_back(item);
+ }
+ }
+
drag_type = DRAG_KEY_MOVE;
drag_from = Vector2();
drag_to = Vector2();
@@ -5852,7 +5860,7 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path));
- editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene);
+ editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true);
editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_owner", editor->get_edited_scene());
editor_data->get_undo_redo().add_do_reference(instantiated_scene);
editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instantiated_scene);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 1a466d4046..957d1483bc 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -954,7 +954,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
real_t col_d = 1e20;
for (int i = 0; i < 3; i++) {
- const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gizmo_scale * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5));
+ const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i).normalized() * gizmo_scale * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5));
const real_t grabber_radius = gizmo_scale * GIZMO_ARROW_SIZE;
Vector3 r;
@@ -1058,7 +1058,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
float col_d = 1e20;
for (int i = 0; i < 3; i++) {
- const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gizmo_scale * GIZMO_SCALE_OFFSET;
+ const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i).normalized() * gizmo_scale * GIZMO_SCALE_OFFSET;
const real_t grabber_radius = gizmo_scale * GIZMO_ARROW_SIZE;
Vector3 r;
@@ -1138,68 +1138,62 @@ void Node3DEditorViewport::_transform_gizmo_apply(Node3D *p_node, const Transfor
}
}
-Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local) {
+Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local, bool p_orthogonal) {
switch (p_mode) {
case TRANSFORM_SCALE: {
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ p_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ }
+ Transform3D s;
if (p_local) {
- Basis g = p_original.basis.orthonormalized();
- Vector3 local_motion = g.inverse().xform(p_motion);
-
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- local_motion.snap(Vector3(p_extra, p_extra, p_extra));
- }
-
- Transform3D local_t;
- local_t.basis = p_original_local.basis.scaled_local(local_motion + Vector3(1, 1, 1));
- local_t.origin = p_original_local.origin;
- return local_t;
+ s.basis = p_original_local.basis.scaled_local(p_motion + Vector3(1, 1, 1));
+ s.origin = p_original_local.origin;
} else {
+ s.basis.scale(p_motion + Vector3(1, 1, 1));
Transform3D base = Transform3D(Basis(), _edit.center);
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- p_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ s = base * (s * (base.inverse() * p_original));
+
+ // Recalculate orthogonalized scale without moving origin.
+ if (p_orthogonal) {
+ s.basis = p_original_local.basis.scaled_orthogonal(p_motion + Vector3(1, 1, 1));
+ // The scaled_orthogonal() does not require orthogonal Basis,
+ // but it may make a bit skew by precision problems.
+ s.basis.orthogonalize();
}
-
- Transform3D global_t;
- global_t.basis.scale(p_motion + Vector3(1, 1, 1));
- return base * (global_t * (base.inverse() * p_original));
}
+
+ return s;
}
case TRANSFORM_TRANSLATE: {
- if (p_local) {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- Basis g = p_original.basis.orthonormalized();
- Vector3 local_motion = g.inverse().xform(p_motion);
- local_motion.snap(Vector3(p_extra, p_extra, p_extra));
-
- p_motion = g.xform(local_motion);
- }
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ p_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ }
- } else {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- p_motion.snap(Vector3(p_extra, p_extra, p_extra));
- }
+ if (p_local) {
+ p_motion = p_original.basis.xform(p_motion);
}
// Apply translation
Transform3D t = p_original;
t.origin += p_motion;
+
return t;
}
case TRANSFORM_ROTATE: {
+ Transform3D r;
+
if (p_local) {
- Transform3D r;
Vector3 axis = p_original_local.basis.xform(p_motion);
r.basis = Basis(axis.normalized(), p_extra) * p_original_local.basis;
r.origin = p_original_local.origin;
- return r;
} else {
- Transform3D r;
Basis local = p_original.basis * p_original_local.basis.inverse();
Vector3 axis = local.xform_inv(p_motion);
r.basis = local * Basis(axis.normalized(), p_extra) * p_original_local.basis;
r.origin = Basis(p_motion, p_extra).xform(p_original.origin - _edit.center) + _edit.center;
- return r;
}
+
+ return r;
}
default: {
ERR_FAIL_V_MSG(Transform3D(), "Invalid mode in '_compute_transform'");
@@ -1480,6 +1474,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_edit.original_mouse_pos = b->get_position();
_edit.snap = spatial_editor->is_snap_enabled();
_edit.mode = TRANSFORM_NONE;
+ _edit.original = spatial_editor->get_gizmo_transform(); // To prevent to break when flipping with scale.
bool can_select_gizmos = spatial_editor->get_single_selected_node();
@@ -1783,30 +1778,30 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
plane = Plane(_get_camera_normal(), _edit.center);
break;
case TRANSFORM_X_AXIS:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized();
plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center);
break;
case TRANSFORM_Y_AXIS:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized();
plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center);
break;
case TRANSFORM_Z_AXIS:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized();
plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center);
break;
case TRANSFORM_YZ:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0), _edit.center);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized() + spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized();
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(), _edit.center);
plane_mv = true;
break;
case TRANSFORM_XZ:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(0);
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1), _edit.center);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized() + spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized();
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(), _edit.center);
plane_mv = true;
break;
case TRANSFORM_XY:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0) + spatial_editor->get_gizmo_transform().basis.get_axis(1);
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2), _edit.center);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized() + spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized();
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(), _edit.center);
plane_mv = true;
break;
}
@@ -1857,6 +1852,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
// This might not be necessary anymore after issue #288 is solved (in 4.0?).
set_message(TTR("Scaling: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " +
String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")");
+ motion = _edit.original.basis.inverse().xform(motion);
List<Node *> &selection = editor_selection->get_selected_node_list();
for (Node *E : selection) {
@@ -1877,14 +1873,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (se->gizmo.is_valid()) {
for (KeyValue<int, Transform3D> &GE : se->subgizmos) {
Transform3D xform = GE.value;
- Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords);
+ Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords, true); // Force orthogonal with subgizmo.
if (!local_coords) {
new_xform = se->original.affine_inverse() * new_xform;
}
se->gizmo->set_subgizmo_transform(GE.key, new_xform);
}
} else {
- Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords);
+ Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS);
_transform_gizmo_apply(se->sp, new_xform, local_coords);
}
}
@@ -1904,27 +1900,27 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
plane = Plane(_get_camera_normal(), _edit.center);
break;
case TRANSFORM_X_AXIS:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized();
plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center);
break;
case TRANSFORM_Y_AXIS:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized();
plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center);
break;
case TRANSFORM_Z_AXIS:
- motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2);
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized();
plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center);
break;
case TRANSFORM_YZ:
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0), _edit.center);
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(), _edit.center);
plane_mv = true;
break;
case TRANSFORM_XZ:
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1), _edit.center);
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(), _edit.center);
plane_mv = true;
break;
case TRANSFORM_XY:
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2), _edit.center);
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(), _edit.center);
plane_mv = true;
break;
}
@@ -1956,6 +1952,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
motion_snapped.snap(Vector3(snap, snap, snap));
set_message(TTR("Translating: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " +
String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")");
+ motion = spatial_editor->get_gizmo_transform().basis.inverse().xform(motion);
List<Node *> &selection = editor_selection->get_selected_node_list();
for (Node *E : selection) {
@@ -1976,12 +1973,12 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (se->gizmo.is_valid()) {
for (KeyValue<int, Transform3D> &GE : se->subgizmos) {
Transform3D xform = GE.value;
- Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords);
+ Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords, true); // Force orthogonal with subgizmo.
new_xform = se->original.affine_inverse() * new_xform;
se->gizmo->set_subgizmo_transform(GE.key, new_xform);
}
} else {
- Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords);
+ Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS);
_transform_gizmo_apply(se->sp, new_xform, false);
}
}
@@ -2000,15 +1997,15 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
plane = Plane(_get_camera_normal(), _edit.center);
break;
case TRANSFORM_X_AXIS:
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0), _edit.center);
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(), _edit.center);
axis = Vector3(1, 0, 0);
break;
case TRANSFORM_Y_AXIS:
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1), _edit.center);
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(), _edit.center);
axis = Vector3(0, 1, 0);
break;
case TRANSFORM_Z_AXIS:
- plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2), _edit.center);
+ plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(), _edit.center);
axis = Vector3(0, 0, 1);
break;
case TRANSFORM_YZ:
@@ -2063,14 +2060,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
for (KeyValue<int, Transform3D> &GE : se->subgizmos) {
Transform3D xform = GE.value;
- Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords);
+ Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords, true); // Force orthogonal with subgizmo.
if (!local_coords) {
new_xform = se->original.affine_inverse() * new_xform;
}
se->gizmo->set_subgizmo_transform(GE.key, new_xform);
}
} else {
- Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords);
+ Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS);
_transform_gizmo_apply(se->sp, new_xform, local_coords);
}
}
@@ -2688,8 +2685,8 @@ void Node3DEditorViewport::_project_settings_changed() {
const bool use_occlusion_culling = GLOBAL_GET("rendering/occlusion_culling/use_occlusion_culling");
viewport->set_use_occlusion_culling(use_occlusion_culling);
- const float lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
- viewport->set_lod_threshold(lod_threshold);
+ const float mesh_lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
+ viewport->set_mesh_lod_threshold(mesh_lod_threshold);
}
void Node3DEditorViewport::_notification(int p_what) {
@@ -3676,8 +3673,6 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
subviewport_container->get_stretch_shrink();
Vector3 scale = Vector3(1, 1, 1) * gizmo_scale;
- xform.basis.scale(scale);
-
// if the determinant is zero, we should disable the gizmo from being rendered
// this prevents supplying bad values to the renderer and then having to filter it out again
if (xform.basis.determinant() == 0) {
@@ -3694,18 +3689,26 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
}
for (int i = 0; i < 3; i++) {
- RenderingServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform);
+ Transform3D axis_angle = Transform3D();
+ if (xform.basis.get_axis(i).normalized().dot(xform.basis.get_axis((i + 1) % 3).normalized()) < 1.0) {
+ axis_angle = axis_angle.looking_at(xform.basis.get_axis(i).normalized(), xform.basis.get_axis((i + 1) % 3).normalized());
+ }
+ axis_angle.basis.scale(scale);
+ axis_angle.origin = xform.origin;
+ RenderingServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE));
- RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], xform);
+ RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE));
- RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform);
+ RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
- RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform);
+ RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE));
- RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], xform);
+ RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE));
}
// Rotation white outline
+ xform.orthonormalize();
+ xform.basis.scale(scale);
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], xform);
RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
}
@@ -3988,6 +3991,37 @@ AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, boo
return bounds;
}
+Node *Node3DEditorViewport::_sanitize_preview_node(Node *p_node) const {
+ Node3D *node_3d = Object::cast_to<Node3D>(p_node);
+ if (node_3d == nullptr) {
+ Node3D *replacement_node = memnew(Node3D);
+ replacement_node->set_name(p_node->get_name());
+ p_node->replace_by(replacement_node);
+ memdelete(p_node);
+ p_node = replacement_node;
+ } else {
+ VisualInstance3D *visual_instance = Object::cast_to<VisualInstance3D>(node_3d);
+ if (visual_instance == nullptr) {
+ Node3D *replacement_node = memnew(Node3D);
+ replacement_node->set_name(node_3d->get_name());
+ replacement_node->set_visible(node_3d->is_visible());
+ replacement_node->set_transform(node_3d->get_transform());
+ replacement_node->set_rotation_edit_mode(node_3d->get_rotation_edit_mode());
+ replacement_node->set_rotation_order(node_3d->get_rotation_order());
+ replacement_node->set_as_top_level(node_3d->is_set_as_top_level());
+ p_node->replace_by(replacement_node);
+ memdelete(p_node);
+ p_node = replacement_node;
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _sanitize_preview_node(p_node->get_child(i));
+ }
+
+ return p_node;
+}
+
void Node3DEditorViewport::_create_preview(const Vector<String> &files) const {
for (int i = 0; i < files.size(); i++) {
String path = files[i];
@@ -4004,6 +4038,7 @@ void Node3DEditorViewport::_create_preview(const Vector<String> &files) const {
if (scene.is_valid()) {
Node *instance = scene->instantiate();
if (instance) {
+ instance = _sanitize_preview_node(instance);
preview_node->add_child(instance);
}
}
@@ -4095,7 +4130,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path));
}
- editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene);
+ editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true);
editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_owner", editor->get_edited_scene());
editor_data->get_undo_redo().add_do_reference(instantiated_scene);
editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instantiated_scene);
@@ -4883,7 +4918,6 @@ void Node3DEditor::update_transform_gizmo() {
gizmo_center += xf.origin;
if (count == 0 && local_gizmo_coords) {
gizmo_basis = xf.basis;
- gizmo_basis.orthonormalize();
}
count++;
}
@@ -4908,7 +4942,6 @@ void Node3DEditor::update_transform_gizmo() {
gizmo_center += xf.origin;
if (count == 0 && local_gizmo_coords) {
gizmo_basis = xf.basis;
- gizmo_basis.orthonormalize();
}
count++;
}
@@ -5783,6 +5816,12 @@ void fragment() {
{
//move gizmo
+ // Inverted zxy.
+ Vector3 ivec = Vector3(0, 0, -1);
+ Vector3 nivec = Vector3(-1, -1, 0);
+ Vector3 ivec2 = Vector3(-1, 0, 0);
+ Vector3 ivec3 = Vector3(0, -1, 0);
+
for (int i = 0; i < 3; i++) {
Color col;
switch (i) {
@@ -5820,16 +5859,6 @@ void fragment() {
mat_hl->set_albedo(albedo);
gizmo_color_hl[i] = mat_hl;
- Vector3 ivec;
- ivec[i] = 1;
- Vector3 nivec;
- nivec[(i + 1) % 3] = 1;
- nivec[(i + 2) % 3] = 1;
- Vector3 ivec2;
- ivec2[(i + 1) % 3] = 1;
- Vector3 ivec3;
- ivec3[(i + 2) % 3] = 1;
-
//translate
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index da28e6314f..8d42e88b53 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -385,6 +385,9 @@ private:
Vector3 _get_instance_position(const Point2 &p_pos) const;
static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform = true);
+
+ Node *_sanitize_preview_node(Node *p_node) const;
+
void _create_preview(const Vector<String> &files) const;
void _remove_preview();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
@@ -396,7 +399,7 @@ private:
void _project_settings_changed();
- Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local);
+ Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local, bool p_orthogonal);
protected:
void _notification(int p_what);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index ab5c9a0ef1..97a882c383 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -238,10 +238,6 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) {
void ScriptTextEditor::_warning_clicked(Variant p_line) {
if (p_line.get_type() == Variant::INT) {
goto_line_centered(p_line.operator int64_t());
- } else if (p_line.get_type() == Variant::DICTIONARY) {
- Dictionary meta = p_line.operator Dictionary();
- code_editor->get_text_editor()->insert_line_at(meta["line"].operator int64_t() - 1, "# warning-ignore:" + meta["code"].operator String());
- _validate_script();
}
}
@@ -468,20 +464,8 @@ void ScriptTextEditor::_validate_script() {
}
// Add script warnings.
- warnings_panel->push_table(3);
+ warnings_panel->push_table(2);
for (const ScriptLanguage::Warning &w : warnings) {
- Dictionary ignore_meta;
- ignore_meta["line"] = w.start_line;
- ignore_meta["code"] = w.string_code.to_lower();
- warnings_panel->push_cell();
- warnings_panel->push_meta(ignore_meta);
- warnings_panel->push_color(
- warnings_panel->get_theme_color(SNAME("accent_color"), SNAME("Editor")).lerp(warnings_panel->get_theme_color(SNAME("mono_color"), SNAME("Editor")), 0.5));
- warnings_panel->add_text(TTR("[Ignore]"));
- warnings_panel->pop(); // Color.
- warnings_panel->pop(); // Meta ignore.
- warnings_panel->pop(); // Cell.
-
warnings_panel->push_cell();
warnings_panel->push_meta(w.start_line - 1);
warnings_panel->push_color(warnings_panel->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 4b7380c83f..08e0f7ae30 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -204,7 +204,7 @@ private:
char fname[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- if (String(fname).ends_with("project.godot")) {
+ if (String::utf8(fname).ends_with("project.godot")) {
break;
}
@@ -524,7 +524,7 @@ private:
char fname[16384];
unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String name = fname;
+ String name = String::utf8(fname);
if (name.ends_with("project.godot")) {
zip_root = name.substr(0, name.rfind("project.godot"));
break;
@@ -544,7 +544,7 @@ private:
char fname[16384];
ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
- String path = fname;
+ String path = String::utf8(fname);
if (path.is_empty() || path == zip_root || !zip_root.is_subsequence_of(path)) {
//
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 3dffc9cde7..ffaf34cfdc 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -31,7 +31,6 @@
#ifndef SCENE_TREE_DOCK_H
#define SCENE_TREE_DOCK_H
-#include "editor/connections_dialog.h"
#include "editor/create_dialog.h"
#include "editor/editor_data.h"
#include "editor/groups_editor.h"