summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Window.xml9
-rwxr-xr-xdoc/tools/make_rst.py78
-rw-r--r--editor/action_map_editor.cpp105
-rw-r--r--editor/action_map_editor.h9
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/project_manager.cpp2
-rw-r--r--editor/project_manager.h2
-rw-r--r--scene/gui/graph_edit.cpp19
-rw-r--r--scene/main/window.cpp2
-rw-r--r--servers/text_server.cpp41
11 files changed, 150 insertions, 121 deletions
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index 9853f906bc..87a65db192 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -349,6 +349,15 @@
<argument index="0" name="files" type="PackedStringArray" />
<description>
Emitted when files are dragged from the OS file manager and dropped in the game window. The argument is a list of file paths.
+ Note that this method only works with non-embedded windows, i.e. the main window and [Window]-derived nodes when [member Viewport.gui_embed_subwindows] is disabled in the main viewport.
+ Example usage:
+ [codeblock]
+ func _ready():
+ get_viewport().files_dropped.connect(on_files_dropped)
+
+ func on_files_dropped(files):
+ print(files)
+ [/codeblock]
</description>
</signal>
<signal name="focus_entered">
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 365beb434b..eba4cee33a 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -58,7 +58,7 @@ strings_l10n = {}
def print_error(error, state): # type: (str, State) -> None
print("ERROR: {}".format(error))
- state.errored = True
+ state.num_errors += 1
class TypeName:
@@ -163,8 +163,7 @@ class ClassDef:
class State:
def __init__(self): # type: () -> None
- # Has any error been reported?
- self.errored = False
+ self.num_errors = 0
self.classes = OrderedDict() # type: OrderedDict[str, ClassDef]
self.current_class = "" # type: str
@@ -194,7 +193,7 @@ class State:
property_name = property.attrib["name"]
if property_name in class_def.properties:
- print_error("Duplicate property '{}', file: {}".format(property_name, class_name), self)
+ print_error('{}.xml: Duplicate property "{}".'.format(class_name, property_name), self)
continue
type_name = TypeName.from_element(property)
@@ -305,7 +304,7 @@ class State:
constant_def = ConstantDef(constant_name, value, constant.text)
if enum is None:
if constant_name in class_def.constants:
- print_error("Duplicate constant '{}', file: {}".format(constant_name, class_name), self)
+ print_error('{}.xml: Duplicate constant "{}".'.format(class_name, constant_name), self)
continue
class_def.constants[constant_name] = constant_def
@@ -328,7 +327,7 @@ class State:
signal_name = signal.attrib["name"]
if signal_name in class_def.signals:
- print_error("Duplicate signal '{}', file: {}".format(signal_name, class_name), self)
+ print_error('{}.xml: Duplicate signal "{}".'.format(class_name, signal_name), self)
continue
params = parse_arguments(signal)
@@ -351,8 +350,8 @@ class State:
theme_item_id = "{}_{}".format(theme_item_data_name, theme_item_name)
if theme_item_id in class_def.theme_items:
print_error(
- "Duplicate theme property '{}' of type '{}', file: {}".format(
- theme_item_name, theme_item_data_name, class_name
+ '{}.xml: Duplicate theme item "{}" of type "{}".'.format(
+ class_name, theme_item_name, theme_item_data_name
),
self,
)
@@ -430,7 +429,7 @@ def main(): # type: () -> None
if entry.msgid in BASE_STRINGS:
strings_l10n[entry.msgid] = entry.msgstr
else:
- print("No PO file at '{}' for language '{}'.".format(lang_file, args.lang))
+ print('No PO file at "{}" for language "{}".'.format(lang_file, args.lang))
print("Checking for errors in the XML class reference...")
@@ -453,7 +452,7 @@ def main(): # type: () -> None
elif os.path.isfile(path):
if not path.endswith(".xml"):
- print("Got non-.xml file '{}' in input, skipping.".format(path))
+ print('Got non-.xml file "{}" in input, skipping.'.format(path))
continue
file_list.append(path)
@@ -465,17 +464,17 @@ def main(): # type: () -> None
try:
tree = ET.parse(cur_file)
except ET.ParseError as e:
- print_error("Parse error reading file '{}': {}".format(cur_file, e), state)
+ print_error("{}.xml: Parse error while reading the file: {}".format(cur_file, e), state)
continue
doc = tree.getroot()
if "version" not in doc.attrib:
- print_error("Version missing from 'doc', file: {}".format(cur_file), state)
+ print_error('{}.xml: "version" attribute missing from "doc".'.format(cur_file), state)
continue
name = doc.attrib["name"]
if name in classes:
- print_error("Duplicate class '{}'".format(name), state)
+ print_error('{}.xml: Duplicate class "{}".'.format(cur_file, name), state)
continue
classes[name] = (doc, cur_file)
@@ -484,7 +483,7 @@ def main(): # type: () -> None
try:
state.parse_class(data[0], data[1])
except Exception as e:
- print_error("Exception while parsing class '{}': {}".format(name, e), state)
+ print_error("{}.xml: Exception while parsing class: {}".format(name, e), state)
state.sort_classes()
@@ -499,12 +498,17 @@ def main(): # type: () -> None
state.current_class = class_name
make_rst_class(class_def, state, args.dry_run, args.output)
- if not state.errored:
- print("No errors found.")
+ if state.num_errors == 0:
+ print("No errors found in the class reference XML.")
if not args.dry_run:
print("Wrote reStructuredText files for each class to: %s" % args.output)
else:
- print("Errors were found in the class reference XML. Please check the messages above.")
+ if state.num_errors >= 2:
+ print(
+ "%d errors were found in the class reference XML. Please check the messages above." % state.num_errors
+ )
+ else:
+ print("1 error was found in the class reference XML. Please check the messages above.")
exit(1)
@@ -856,7 +860,7 @@ def escape_rst(text, until_pos=-1): # type: (str) -> str
def format_codeblock(code_type, post_text, indent_level, state): # types: str, str, int, state
end_pos = post_text.find("[/" + code_type + "]")
if end_pos == -1:
- print_error("[" + code_type + "] without a closing tag, file: {}".format(state.current_class), state)
+ print_error("{}.xml: [" + code_type + "] without a closing tag.".format(state.current_class), state)
return None
code_text = post_text[len("[" + code_type + "]") : end_pos]
@@ -875,9 +879,9 @@ def format_codeblock(code_type, post_text, indent_level, state): # types: str,
if to_skip > indent_level:
print_error(
- "Four spaces should be used for indentation within ["
+ "{}.xml: Four spaces should be used for indentation within ["
+ code_type
- + "], file: {}".format(state.current_class),
+ + "].".format(state.current_class),
state,
)
@@ -987,7 +991,7 @@ def rstize_text(text, state): # type: (str, State) -> str
if param.find(".") != -1:
ss = param.split(".")
if len(ss) > 2:
- print_error("Bad reference: '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Bad reference: "{}".'.format(state.current_class, param), state)
class_param, method_param = ss
else:
@@ -1000,33 +1004,31 @@ def rstize_text(text, state): # type: (str, State) -> str
if cmd.startswith("constructor"):
if method_param not in class_def.constructors:
print_error(
- "Unresolved constructor '{}', file: {}".format(param, state.current_class), state
+ '{}.xml: Unresolved constructor "{}".'.format(state.current_class, param), state
)
ref_type = "_constructor"
if cmd.startswith("method"):
if method_param not in class_def.methods:
- print_error("Unresolved method '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved method "{}".'.format(state.current_class, param), state)
ref_type = "_method"
if cmd.startswith("operator"):
if method_param not in class_def.operators:
- print_error("Unresolved operator '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved operator "{}".'.format(state.current_class, param), state)
ref_type = "_operator"
elif cmd.startswith("member"):
if method_param not in class_def.properties:
- print_error("Unresolved member '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved member "{}".'.format(state.current_class, param), state)
ref_type = "_property"
elif cmd.startswith("theme_item"):
if method_param not in class_def.theme_items:
- print_error(
- "Unresolved theme item '{}', file: {}".format(param, state.current_class), state
- )
+ print_error('{}.xml: Unresolved theme item "{}".'.format(state.current_class, param), state)
ref_type = "_theme_{}".format(class_def.theme_items[method_param].data_name)
elif cmd.startswith("signal"):
if method_param not in class_def.signals:
- print_error("Unresolved signal '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved signal "{}".'.format(state.current_class, param), state)
ref_type = "_signal"
elif cmd.startswith("constant"):
@@ -1052,13 +1054,13 @@ def rstize_text(text, state): # type: (str, State) -> str
break
if not found:
- print_error("Unresolved constant '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved constant "{}".'.format(state.current_class, param), state)
ref_type = "_constant"
else:
print_error(
- "Unresolved type reference '{}' in method reference '{}', file: {}".format(
- class_param, param, state.current_class
+ '{}.xml: Unresolved type reference "{}" in method reference "{}".'.format(
+ state.current_class, class_param, param
),
state,
)
@@ -1078,7 +1080,7 @@ def rstize_text(text, state): # type: (str, State) -> str
endurl_pos = text.find("[/url]", endq_pos + 1)
if endurl_pos == -1:
print_error(
- "Tag depth mismatch for [url]: no closing [/url], file: {}".format(state.current_class), state
+ "{}.xml: Tag depth mismatch for [url]: no closing [/url]".format(state.current_class), state
)
break
link_title = text[endq_pos + 1 : endurl_pos]
@@ -1203,7 +1205,9 @@ def rstize_text(text, state): # type: (str, State) -> str
previous_pos = pos
if tag_depth > 0:
- print_error("Tag depth mismatch: too many/little open/close tags, file: {}".format(state.current_class), state)
+ print_error(
+ "{}.xml: Tag depth mismatch: too many (or too little) open/close tags.".format(state.current_class), state
+ )
return text
@@ -1247,7 +1251,7 @@ def make_type(klass, state): # type: (str, State) -> str
link_type = link_type[:-2]
if link_type in state.classes:
return ":ref:`{}<class_{}>`".format(klass, link_type)
- print_error("Unresolved type '{}', file: {}".format(klass, state.current_class), state)
+ print_error('{}.xml: Unresolved type "{}".'.format(state.current_class, klass), state)
return klass
@@ -1271,7 +1275,7 @@ def make_enum(t, state): # type: (str, State) -> str
# Don't fail for `Vector3.Axis`, as this enum is a special case which is expected not to be resolved.
if "{}.{}".format(c, e) != "Vector3.Axis":
- print_error("Unresolved enum '{}', file: {}".format(t, state.current_class), state)
+ print_error('{}.xml: Unresolved enum "{}".'.format(state.current_class, t), state)
return t
@@ -1429,7 +1433,7 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str
else:
clear_name = "xxx"
- print_error("Unsupported operator type '{}', please add the missing rule.".format(dirty_name), state)
+ print_error('Unsupported operator type "{}", please add the missing rule.'.format(dirty_name), state)
return clear_name
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 96931efd3b..86b40a311e 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -61,29 +61,37 @@ static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
TTRC("Joystick 4 Down"),
};
-String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event) {
+String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const {
ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
- // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
- Ref<InputEventJoypadMotion> jpmotion = p_event;
- if (jpmotion.is_valid()) {
+ String text = p_event->as_text();
+
+ Ref<InputEventMouse> mouse = p_event;
+ Ref<InputEventJoypadMotion> jp_motion = p_event;
+ Ref<InputEventJoypadButton> jp_button = p_event;
+ if (jp_motion.is_valid()) {
+ // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
String desc = TTR("Unknown Joypad Axis");
- if (jpmotion->get_axis() < JoyAxis::MAX) {
- desc = RTR(_joy_axis_descriptions[2 * (size_t)jpmotion->get_axis() + (jpmotion->get_axis_value() < 0 ? 0 : 1)]);
+ if (jp_motion->get_axis() < JoyAxis::MAX) {
+ desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]);
}
- return vformat("Joypad Axis %s %s (%s)", itos((int64_t)jpmotion->get_axis()), jpmotion->get_axis_value() < 0 ? "-" : "+", desc);
- } else {
- return p_event->as_text();
+ text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc);
+ }
+ if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) {
+ String device_string = _get_device_string(p_event->get_device());
+ text += vformat(" - %s", device_string);
}
+
+ return text;
}
-void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
+void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, bool p_update_input_list_selection) {
if (p_event.is_valid()) {
event = p_event;
// Update Label
- event_as_text->set_text(get_event_text(event));
+ event_as_text->set_text(get_event_text(event, true));
Ref<InputEventKey> k = p_event;
Ref<InputEventMouseButton> mb = p_event;
@@ -122,7 +130,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
additional_options_container->show();
// Update selected item in input list.
- if (k.is_valid() || joyb.is_valid() || joym.is_valid() || mb.is_valid()) {
+ if (p_update_input_list_selection && (k.is_valid() || joyb.is_valid() || joym.is_valid() || mb.is_valid())) {
TreeItem *category = input_list_tree->get_root()->get_first_child();
while (category) {
TreeItem *input_item = category->get_first_child();
@@ -234,10 +242,13 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &
}
}
+ // Create an editable reference
+ Ref<InputEvent> received_event = p_event;
+
// Check what the type is and if it is allowed.
- Ref<InputEventKey> k = p_event;
- Ref<InputEventJoypadButton> joyb = p_event;
- Ref<InputEventJoypadMotion> joym = p_event;
+ Ref<InputEventKey> k = received_event;
+ Ref<InputEventJoypadButton> joyb = received_event;
+ Ref<InputEventJoypadMotion> joym = received_event;
int type = 0;
if (k.is_valid()) {
@@ -266,7 +277,7 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &
}
if (k.is_valid()) {
- k->set_pressed(false); // to avoid serialisation of 'pressed' property - doesn't matter for actions anyway.
+ k->set_pressed(false); // To avoid serialisation of 'pressed' property - doesn't matter for actions anyway.
// Maintain physical keycode option state
if (physical_key_checkbox->is_pressed()) {
k->set_keycode(Key::NONE);
@@ -275,15 +286,17 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &
}
}
- Ref<InputEventWithModifiers> mod = p_event;
+ Ref<InputEventWithModifiers> mod = received_event;
if (mod.is_valid()) {
// Maintain store command option state
mod->set_store_command(store_command_checkbox->is_pressed());
-
mod->set_window_id(0);
}
- _set_event(p_event);
+ // Maintain device selection.
+ received_event->set_device(_get_current_device());
+
+ _set_event(received_event);
set_input_as_handled();
}
@@ -331,7 +344,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventMouseButton> mb;
mb.instantiate();
mb->set_button_index(mouse_buttons[i]);
- String desc = get_event_text(mb);
+ String desc = get_event_text(mb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -354,7 +367,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventJoypadButton> joyb;
joyb.instantiate();
joyb->set_button_index((JoyButton)i);
- String desc = get_event_text(joyb);
+ String desc = get_event_text(joyb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -380,7 +393,7 @@ void InputEventConfigurationDialog::_update_input_list() {
joym.instantiate();
joym->set_axis((JoyAxis)axis);
joym->set_axis_value(direction);
- String desc = get_event_text(joym);
+ String desc = get_event_text(joym, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -495,7 +508,7 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
k->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed());
k->set_store_command(store_command_checkbox->is_pressed());
- _set_event(k);
+ _set_event(k, false);
} break;
case InputEventConfigurationDialog::INPUT_MOUSE_BUTTON: {
MouseButton idx = (MouseButton)(int)selected->get_meta("__index");
@@ -510,12 +523,19 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
mb->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed());
mb->set_store_command(store_command_checkbox->is_pressed());
- _set_event(mb);
+ // Maintain selected device
+ mb->set_device(_get_current_device());
+
+ _set_event(mb, false);
} break;
case InputEventConfigurationDialog::INPUT_JOY_BUTTON: {
JoyButton idx = (JoyButton)(int)selected->get_meta("__index");
Ref<InputEventJoypadButton> jb = InputEventJoypadButton::create_reference(idx);
- _set_event(jb);
+
+ // Maintain selected device
+ jb->set_device(_get_current_device());
+
+ _set_event(jb, false);
} break;
case InputEventConfigurationDialog::INPUT_JOY_MOTION: {
JoyAxis axis = (JoyAxis)(int)selected->get_meta("__axis");
@@ -525,24 +545,35 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
jm.instantiate();
jm->set_axis(axis);
jm->set_axis_value(value);
- _set_event(jm);
+
+ // Maintain selected device
+ jm->set_device(_get_current_device());
+
+ _set_event(jm, false);
} break;
}
}
-void InputEventConfigurationDialog::_set_current_device(int i_device) {
- device_id_option->select(i_device + 1);
+void InputEventConfigurationDialog::_device_selection_changed(int p_option_button_index) {
+ // Subtract 1 as option index 0 corresponds to "All Devices" (value of -1)
+ // and option index 1 corresponds to device 0, etc...
+ event->set_device(p_option_button_index - 1);
+ event_as_text->set_text(get_event_text(event, true));
+}
+
+void InputEventConfigurationDialog::_set_current_device(int p_device) {
+ device_id_option->select(p_device + 1);
}
int InputEventConfigurationDialog::_get_current_device() const {
return device_id_option->get_selected() - 1;
}
-String InputEventConfigurationDialog::_get_device_string(int i_device) const {
- if (i_device == InputMap::ALL_DEVICES) {
+String InputEventConfigurationDialog::_get_device_string(int p_device) const {
+ if (p_device == InputMap::ALL_DEVICES) {
return TTR("All Devices");
}
- return TTR("Device") + " " + itos(i_device);
+ return TTR("Device") + " " + itos(p_device);
}
void InputEventConfigurationDialog::_notification(int p_what) {
@@ -588,6 +619,9 @@ void InputEventConfigurationDialog::popup_and_configure(const Ref<InputEvent> &p
// Switch to "Listen" tab
tab_container->set_current_tab(0);
+
+ // Select "All Devices" by default.
+ device_id_option->select(0);
}
popup_centered();
@@ -673,12 +707,13 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_id_option = memnew(OptionButton);
device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- device_container->add_child(device_id_option);
-
for (int i = -1; i < 8; i++) {
device_id_option->add_item(_get_device_string(i));
}
- _set_current_device(0);
+ device_id_option->connect("item_selected", callable_mp(this, &InputEventConfigurationDialog::_device_selection_changed));
+ _set_current_device(InputMap::ALL_DEVICES);
+ device_container->add_child(device_id_option);
+
device_container->hide();
additional_options_container->add_child(device_container);
@@ -1096,7 +1131,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
TreeItem *event_item = action_tree->create_item(action_item);
// First Column - Text
- event_item->set_text(0, event_config_dialog->get_event_text(event)); // Need to us the special description for JoypadMotion here, so don't use as_text() directly.
+ event_item->set_text(0, event_config_dialog->get_event_text(event, true));
event_item->set_meta("__event", event);
event_item->set_meta("__index", evnt_idx);
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index e96139e070..0da7708422 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -97,7 +97,7 @@ private:
CheckBox *physical_key_checkbox = nullptr;
- void _set_event(const Ref<InputEvent> &p_event);
+ void _set_event(const Ref<InputEvent> &p_event, bool p_update_input_list_selection = true);
void _tab_selected(int p_tab);
void _listen_window_input(const Ref<InputEvent> &p_event);
@@ -110,9 +110,10 @@ private:
void _store_command_toggled(bool p_checked);
void _physical_keycode_toggled(bool p_checked);
- void _set_current_device(int i_device);
+ void _device_selection_changed(int p_option_button_index);
+ void _set_current_device(int p_device);
int _get_current_device() const;
- String _get_device_string(int i_device) const;
+ String _get_device_string(int p_device) const;
protected:
void _notification(int p_what);
@@ -121,7 +122,7 @@ public:
// Pass an existing event to configure it. Alternatively, pass no event to start with a blank configuration.
void popup_and_configure(const Ref<InputEvent> &p_event = Ref<InputEvent>());
Ref<InputEvent> get_event() const;
- String get_event_text(const Ref<InputEvent> &p_event);
+ String get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const;
void set_allowed_input_types(int p_type_masks);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index e81d0dae0e..99e30593a9 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -5478,7 +5478,7 @@ void EditorNode::_global_menu_new_window(const Variant &p_tag) {
}
}
-void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
+void EditorNode::_dropped_files(const Vector<String> &p_files) {
String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_selected_path());
_add_dropped_files_recursive(p_files, to_path);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 685714cb47..c6c1f09938 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -575,7 +575,7 @@ private:
void _open_recent_scene(int p_idx);
void _global_menu_scene(const Variant &p_tag);
void _global_menu_new_window(const Variant &p_tag);
- void _dropped_files(const Vector<String> &p_files, int p_screen);
+ void _dropped_files(const Vector<String> &p_files);
void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path);
void _update_from_settings();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 060661b509..2b24c231ea 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -2398,7 +2398,7 @@ void ProjectManager::_install_project(const String &p_zip_path, const String &p_
npdialog->show_dialog();
}
-void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
+void ProjectManager::_files_dropped(PackedStringArray p_files) {
if (p_files.size() == 1 && p_files[0].ends_with(".zip")) {
const String file = p_files[0].get_file();
_install_project(p_files[0], file.substr(0, file.length() - 4).capitalize());
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 9cea6e163f..00f8cfc721 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -127,7 +127,7 @@ class ProjectManager : public Control {
void _dim_window();
virtual void shortcut_input(const Ref<InputEvent> &p_ev) override;
- void _files_dropped(PackedStringArray p_files, int p_screen);
+ void _files_dropped(PackedStringArray p_files);
void _version_button_pressed();
void _on_order_option_changed(int p_idx);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 1394b4192f..e39791642a 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -696,7 +696,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
int type = gn->get_connection_output_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_output_hotzone(gn, j, mpos, port_size)) {
+ if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_output_hotzone(gn, j, mpos, port_size)) {
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -708,7 +708,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
int type = gn->get_connection_input_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_input_hotzone(gn, j, mpos, port_size)) {
+ if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_input_hotzone(gn, j, mpos, port_size)) {
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -1568,26 +1568,17 @@ void GraphEdit::_update_zoom_label() {
}
void GraphEdit::add_valid_connection_type(int p_type, int p_with_type) {
- ConnType ct;
- ct.type_a = p_type;
- ct.type_b = p_with_type;
-
+ ConnType ct(p_type, p_with_type);
valid_connection_types.insert(ct);
}
void GraphEdit::remove_valid_connection_type(int p_type, int p_with_type) {
- ConnType ct;
- ct.type_a = p_type;
- ct.type_b = p_with_type;
-
+ ConnType ct(p_type, p_with_type);
valid_connection_types.erase(ct);
}
bool GraphEdit::is_valid_connection_type(int p_type, int p_with_type) const {
- ConnType ct;
- ct.type_a = p_type;
- ct.type_b = p_with_type;
-
+ ConnType ct(p_type, p_with_type);
return valid_connection_types.has(ct);
}
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 2faa107fb4..2858ffba6d 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -981,7 +981,7 @@ void Window::_window_input_text(const String &p_text) {
}
void Window::_window_drop_files(const Vector<String> &p_files) {
- emit_signal(SNAME("files_dropped"), p_files, current_screen);
+ emit_signal(SNAME("files_dropped"), p_files);
}
Viewport *Window::get_parent_viewport() const {
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 2f32e81f06..6183fa2cbc 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -979,6 +979,14 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(co
}
}
+_FORCE_INLINE_ void _push_range(Vector<Vector2> &r_vector, real_t p_start, real_t p_end) {
+ if (!r_vector.is_empty() && Math::is_equal_approx(r_vector[r_vector.size() - 1].y, p_start, (real_t)UNIT_EPSILON)) {
+ r_vector.write[r_vector.size() - 1].y = p_end;
+ } else {
+ r_vector.push_back(Vector2(p_start, p_end));
+ }
+}
+
Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
Vector<Vector2> ranges;
@@ -1003,7 +1011,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
- ranges.push_back(Vector2(off, off + advance));
+ _push_range(ranges, off, off + advance);
}
// Only start of grapheme is in selection range.
if (glyphs[i].start >= start && glyphs[i].end > end) {
@@ -1013,9 +1021,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + advance));
+ _push_range(ranges, off + char_adv * (glyphs[i].end - end), off + advance);
} else {
- ranges.push_back(Vector2(off, off + char_adv * (end - glyphs[i].start)));
+ _push_range(ranges, off, off + char_adv * (end - glyphs[i].start));
}
}
// Only end of grapheme is in selection range.
@@ -1026,9 +1034,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off, off + char_adv * (glyphs[i].end - start)));
+ _push_range(ranges, off, off + char_adv * (glyphs[i].end - start));
} else {
- ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + advance));
+ _push_range(ranges, off + char_adv * (start - glyphs[i].start), off + advance);
}
}
// Selection range is within grapheme.
@@ -1039,9 +1047,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start)));
+ _push_range(ranges, off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start));
} else {
- ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + char_adv * (end - glyphs[i].start)));
+ _push_range(ranges, off + char_adv * (start - glyphs[i].start), off + char_adv * (end - glyphs[i].start));
}
}
}
@@ -1050,25 +1058,6 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
}
- // Merge intersecting ranges.
- int i = 0;
- while (i < ranges.size()) {
- i++;
- }
- i = 0;
- while (i < ranges.size()) {
- int j = i + 1;
- while (j < ranges.size()) {
- if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) {
- ranges.write[i].y = ranges[j].y;
- ranges.remove_at(j);
- continue;
- }
- j++;
- }
- i++;
- }
-
return ranges;
}