diff options
-rw-r--r-- | core/input/input.cpp | 10 | ||||
-rw-r--r-- | core/input/input.h | 3 | ||||
-rw-r--r-- | core/input/input_event.cpp | 12 | ||||
-rw-r--r-- | core/input/input_event.h | 4 | ||||
-rw-r--r-- | core/input/input_map.cpp | 7 | ||||
-rw-r--r-- | doc/classes/InputEventAction.xml | 3 | ||||
-rw-r--r-- | editor/editor_node.cpp | 155 | ||||
-rw-r--r-- | editor/import/resource_importer_shader_file.cpp | 1 | ||||
-rw-r--r-- | editor/plugins/animation_state_machine_editor.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/animation_tree_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | main/main.cpp | 6 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 4 | ||||
-rw-r--r-- | scene/resources/animation.h | 2 | ||||
-rw-r--r-- | scene/scene_string_names.cpp | 1 | ||||
-rw-r--r-- | scene/scene_string_names.h | 1 |
15 files changed, 144 insertions, 69 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index a8409cc06d..aa4b47934e 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -1029,6 +1029,14 @@ void Input::parse_input_event(const Ref<InputEvent> &p_event) { } } +#ifdef DEBUG_ENABLED +void Input::flush_frame_parsed_events() { + _THREAD_SAFE_METHOD_ + + frame_parsed_events.clear(); +} +#endif + void Input::flush_buffered_events() { _THREAD_SAFE_METHOD_ @@ -1244,7 +1252,7 @@ void Input::_update_action_cache(const StringName &p_action_name, ActionState &r r_action_state.cache.strength = 0.0; r_action_state.cache.raw_strength = 0.0; - int max_event = InputMap::get_singleton()->action_get_events(p_action_name)->size(); + int max_event = InputMap::get_singleton()->action_get_events(p_action_name)->size() + 1; // +1 comes from InputEventAction. for (const KeyValue<int, ActionState::DeviceState> &kv : r_action_state.device_states) { const ActionState::DeviceState &device_state = kv.value; for (int i = 0; i < max_event; i++) { diff --git a/core/input/input.h b/core/input/input.h index 6e7ab43082..4daea0c9e8 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -363,6 +363,9 @@ public: Dictionary get_joy_info(int p_device) const; void set_fallback_mapping(const String &p_guid); +#ifdef DEBUG_ENABLED + void flush_frame_parsed_events(); +#endif void flush_buffered_events(); bool is_using_input_buffering(); void set_use_input_buffering(bool p_enable); diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index bf1de8d3b2..de3efa7a3a 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -1585,6 +1585,14 @@ float InputEventAction::get_strength() const { return strength; } +void InputEventAction::set_event_index(int p_index) { + event_index = p_index; +} + +int InputEventAction::get_event_index() const { + return event_index; +} + bool InputEventAction::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) const { if (p_event.is_null()) { return false; @@ -1649,9 +1657,13 @@ void InputEventAction::_bind_methods() { ClassDB::bind_method(D_METHOD("set_strength", "strength"), &InputEventAction::set_strength); ClassDB::bind_method(D_METHOD("get_strength"), &InputEventAction::get_strength); + ClassDB::bind_method(D_METHOD("set_event_index", "index"), &InputEventAction::set_event_index); + ClassDB::bind_method(D_METHOD("get_event_index"), &InputEventAction::get_event_index); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "action"), "set_action", "get_action"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_strength", "get_strength"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "event_index", PROPERTY_HINT_RANGE, "-1,31,1"), "set_event_index", "get_event_index"); // The max value equals to Input::MAX_EVENT - 1. } /////////////////////////////////// diff --git a/core/input/input_event.h b/core/input/input_event.h index 21b61f3bc2..19176f748e 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -453,6 +453,7 @@ class InputEventAction : public InputEvent { StringName action; float strength = 1.0f; + int event_index = -1; protected: static void _bind_methods(); @@ -466,6 +467,9 @@ public: void set_strength(float p_strength); float get_strength() const; + void set_event_index(int p_index); + int get_event_index() const; + virtual bool is_action(const StringName &p_action) const; virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 7fd1806b31..178d02b987 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -274,6 +274,13 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str if (r_raw_strength != nullptr) { *r_raw_strength = strength; } + if (r_event_index) { + if (input_event_action->get_event_index() >= 0) { + *r_event_index = input_event_action->get_event_index(); + } else { + *r_event_index = E->value.inputs.size(); + } + } return input_event_action->get_action() == p_action; } diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml index 4715f9fe95..e082adeca0 100644 --- a/doc/classes/InputEventAction.xml +++ b/doc/classes/InputEventAction.xml @@ -16,6 +16,9 @@ <member name="action" type="StringName" setter="set_action" getter="get_action" default="&"""> The action's name. Actions are accessed via this [String]. </member> + <member name="event_index" type="int" setter="set_event_index" getter="get_event_index" default="-1"> + The real event index in action this event corresponds to (from events defined for this action in the [InputMap]). If [code]-1[/code], a unique ID will be used and actions pressed with this ID will need to be released with another [InputEventAction]. + </member> <member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> If [code]true[/code], the action's state is pressed. If [code]false[/code], the action's state is released. </member> diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0df4df36bc..af06ccb885 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1067,7 +1067,7 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) { reload_instances_with_path_in_edited_scenes(E); } - scene_tabs->set_current_tab(current_tab); + _set_current_scene_nocheck(current_tab); } void EditorNode::_sources_changed(bool p_exist) { @@ -5719,8 +5719,14 @@ void EditorNode::reload_scene(const String &p_path) { if (scene_idx == -1) { if (get_edited_scene()) { + int current_history_id = editor_data.get_current_edited_scene_history_id(); + bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id); + // Scene is not open, so at it might be instantiated. We'll refresh the whole scene later. - EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_current_edited_scene_history_id()); + EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id); + if (is_unsaved) { + EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id); + } } return; } @@ -5770,7 +5776,6 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node * } void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_instance_path) { - int original_edited_scene_idx = editor_data.get_edited_scene(); HashMap<int, List<Node *>> edited_scene_map; Array replaced_nodes; @@ -5801,14 +5806,34 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins HashMap<String, Ref<PackedScene>> local_scene_cache; local_scene_cache[p_instance_path] = instance_scene_packed_scene; + // Save the current scene state/selection in case of lost. + Dictionary editor_state = _get_main_scene_state(); + editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state); + editor_selection->clear(); + + int original_edited_scene_idx = editor_data.get_edited_scene(); + Node *original_edited_scene_root = editor_data.get_edited_scene_root(); + + // Prevent scene roots with the same name from being in the tree at the same time. + scene_root->remove_child(original_edited_scene_root); + for (const KeyValue<int, List<Node *>> &edited_scene_map_elem : edited_scene_map) { // Set the current scene. int current_scene_idx = edited_scene_map_elem.key; editor_data.set_edited_scene(current_scene_idx); Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx); - // Clear the history for this tab (should we allow history to be retained?). - EditorUndoRedoManager::get_singleton()->clear_history(); + // Make sure the node is in the tree so that editor_selection can add node smoothly. + scene_root->add_child(current_edited_scene); + + // Restore the state so that the selection can be updated. + editor_state = editor_data.restore_edited_scene_state(editor_selection, &editor_history); + + int current_history_id = editor_data.get_current_edited_scene_history_id(); + bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id); + + // Clear the history for this affected tab. + EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id); // Update the version editor_data.is_scene_changed(current_scene_idx); @@ -5818,6 +5843,52 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins update_node_reference_modification_table_for_node(current_edited_scene, current_edited_scene, edited_scene_map_elem.value, edited_scene_global_modification_table); for (Node *original_node : edited_scene_map_elem.value) { + String original_node_file_path = original_node->get_scene_file_path(); + + // Load a replacement scene for the node. + Ref<PackedScene> current_packed_scene; + if (original_node_file_path == p_instance_path) { + // If the node file name directly matches the scene we're replacing, + // just load it since we already cached it. + current_packed_scene = instance_scene_packed_scene; + } else { + // Otherwise, check the inheritance chain, reloading and caching any scenes + // we require along the way. + List<String> required_load_paths; + + // Do we need to check if the paths are empty? + if (!original_node_file_path.is_empty()) { + required_load_paths.push_front(original_node_file_path); + } + Ref<SceneState> inherited_state = original_node->get_scene_inherited_state(); + while (inherited_state.is_valid()) { + String inherited_path = inherited_state->get_path(); + // Do we need to check if the paths are empty? + if (!inherited_path.is_empty()) { + required_load_paths.push_front(inherited_path); + } + inherited_state = inherited_state->get_base_scene_state(); + } + + // Ensure the inheritance chain is loaded in the correct order so that cache can + // be properly updated. + for (String path : required_load_paths) { + if (!local_scene_cache.find(path)) { + current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP, &err); + local_scene_cache[path] = current_packed_scene; + } else { + current_packed_scene = local_scene_cache[path]; + } + } + } + + ERR_FAIL_COND(current_packed_scene.is_null()); + + // Instantiate early so that caches cleared on load in SceneState can be rebuilt early. + Node *instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); + + ERR_FAIL_NULL(instantiated_node); + // Walk the tree for the current node and extract relevant diff data, storing it in the modification table. // For additional nodes which are part of the current scene, they get added to the addition table. HashMap<NodePath, ModificationNodeEntry> modification_table; @@ -5875,53 +5946,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins is_editable = owner->is_editable_instance(original_node); } - // Load a replacement scene for the node. - Ref<PackedScene> current_packed_scene; - if (original_node->get_scene_file_path() == p_instance_path) { - // If the node file name directly matches the scene we're replacing, - // just load it since we already cached it. - current_packed_scene = instance_scene_packed_scene; - } else { - // Otherwise, check the inheritance chain, reloading and caching any scenes - // we require along the way. - List<String> required_load_paths; - String scene_path = original_node->get_scene_file_path(); - // Do we need to check if the paths are empty? - if (!scene_path.is_empty()) { - required_load_paths.push_front(scene_path); - } - Ref<SceneState> inherited_state = original_node->get_scene_inherited_state(); - while (inherited_state.is_valid()) { - String inherited_path = inherited_state->get_path(); - // Do we need to check if the paths are empty? - if (!inherited_path.is_empty()) { - required_load_paths.push_front(inherited_path); - } - inherited_state = inherited_state->get_base_scene_state(); - } - - // Ensure the inheritance chain is loaded in the correct order so that cache can - // be properly updated. - for (String path : required_load_paths) { - if (!local_scene_cache.find(path)) { - current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP, &err); - local_scene_cache[path] = current_packed_scene; - } else { - current_packed_scene = local_scene_cache[path]; - } - } - } - - ERR_FAIL_COND(current_packed_scene.is_null()); - - // Instantiate the node. - Node *instantiated_node = nullptr; - if (current_packed_scene.is_valid()) { - instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); - } - - ERR_FAIL_NULL(instantiated_node); - // For clear instance state for path recaching. instantiated_node->set_scene_instance_state(Ref<SceneState>()); @@ -5932,7 +5956,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins instantiated_node->set_name(original_node->get_name()); // Is this replacing the edited root node? - String original_node_file_path = original_node->get_scene_file_path(); if (current_edited_scene == original_node) { instantiated_node->set_scene_instance_state(original_node->get_scene_instance_state()); @@ -5943,13 +5966,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins instantiated_node->set_scene_inherited_state(state); instantiated_node->set_scene_file_path(String()); } - editor_data.set_edited_scene_root(instantiated_node); current_edited_scene = instantiated_node; - - if (original_node->is_inside_tree()) { - SceneTreeDock::get_singleton()->set_edited_scene(current_edited_scene); - original_node->get_tree()->set_edited_scene_root(instantiated_node); - } } // Replace the original node with the instantiated version. @@ -6046,8 +6063,18 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins } } + if (is_unsaved) { + EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id); + } + + // Save the current handled scene state. + editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state); + editor_selection->clear(); + // Cleanup the history of the changes. editor_history.cleanup_history(); + + scene_root->remove_child(current_edited_scene); } // For the whole editor, call the _notify_nodes_scene_reimported with a list of replaced nodes. @@ -6055,10 +6082,14 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins _notify_nodes_scene_reimported(this, replaced_nodes); edited_scene_map.clear(); - } - editor_data.set_edited_scene(original_edited_scene_idx); - _edit_current(); + editor_data.set_edited_scene(original_edited_scene_idx); + + original_edited_scene_root = editor_data.get_edited_scene_root(); + scene_root->add_child(original_edited_scene_root); + + editor_data.restore_edited_scene_state(editor_selection, &editor_history); + } } int EditorNode::plugin_init_callback_count = 0; diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index 6b20a8c9d5..b7508e7644 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -92,6 +92,7 @@ static String _include_function(const String &p_path, void *userpointer) { Error ResourceImporterShaderFile::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { /* STEP 1, Read shader code */ ERR_FAIL_COND_V_EDMSG((OS::get_singleton()->get_current_rendering_method() == "gl_compatibility"), ERR_UNAVAILABLE, "Cannot import custom .glsl shaders when using the gl_compatibility rendering_method. Please switch to the forward_plus or mobile rendering methods to use custom shaders."); + ERR_FAIL_COND_V_EDMSG((DisplayServer::get_singleton()->get_name() == "headless"), ERR_UNAVAILABLE, "Cannot import custom .glsl shaders when running in headless mode."); Error err; Ref<FileAccess> file = FileAccess::open(p_source_file, FileAccess::READ, &err); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index b6d81ce461..449e99d692 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -118,7 +118,7 @@ String AnimationNodeStateMachineEditor::_get_root_playback_path(String &r_node_d if (node_directory_path.size()) { r_node_directory += "/"; } - base_path = !edited_path.size() ? String(SceneStringName(parameters_base_path)) + "playback" : String(SceneStringName(parameters_base_path)) + base_path + "/playback"; + base_path = !edited_path.size() ? Animation::PARAMETERS_BASE_PATH + "playback" : Animation::PARAMETERS_BASE_PATH + base_path + "/playback"; } else { // Hmmm, we have to return Grouped state machine playback... // It will give the user the error that Root/Nested state machine should be retrieved, that would be kind :-) diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index cc1f51348d..757d410b78 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -220,7 +220,7 @@ void AnimationTreeEditor::remove_plugin(AnimationTreeNodeEditorPlugin *p_editor) } String AnimationTreeEditor::get_base_path() { - String path = SceneStringName(parameters_base_path); + String path = Animation::PARAMETERS_BASE_PATH; for (int i = 0; i < edited_path.size(); i++) { path += edited_path[i] + "/"; } diff --git a/main/main.cpp b/main/main.cpp index 2bd421e5af..6b17c55efc 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -4182,6 +4182,12 @@ void Main::cleanup(bool p_force) { ERR_FAIL_COND(!_start_success); } +#ifdef DEBUG_ENABLED + if (input) { + input->flush_frame_parsed_events(); + } +#endif + for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { TextServerManager::get_singleton()->get_interface(i)->cleanup(); } diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index d4061ab167..69287478db 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -626,7 +626,7 @@ bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const for (int i = 0; i < p_track_count; i++) { src_blendsw[i] = 1.0; // By default all go to 1 for the root input. } - root_animation_node->node_state.base_path = SceneStringName(parameters_base_path); + root_animation_node->node_state.base_path = SNAME(Animation::PARAMETERS_BASE_PATH.ascii().get_data()); root_animation_node->node_state.parent = nullptr; } @@ -787,7 +787,7 @@ void AnimationTree::_update_properties() { input_activity_map_get.clear(); if (root_animation_node.is_valid()) { - _update_properties_for_node(SceneStringName(parameters_base_path), root_animation_node); + _update_properties_for_node(Animation::PARAMETERS_BASE_PATH, root_animation_node); } properties_dirty = false; diff --git a/scene/resources/animation.h b/scene/resources/animation.h index cc7bbae8a3..604bce497a 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -43,6 +43,8 @@ class Animation : public Resource { public: typedef uint32_t TypeHash; + static inline String PARAMETERS_BASE_PATH = "parameters/"; + enum TrackType { TYPE_VALUE, // Set a value in a property, can be interpolated. TYPE_POSITION_3D, // Position 3D track, can be compressed. diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 2ee27c95e1..ac3ff7f38c 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -123,7 +123,6 @@ SceneStringNames::SceneStringNames() { window_input = StaticCString::create("window_input"); theme_changed = StaticCString::create("theme_changed"); - parameters_base_path = "parameters/"; shader_overrides_group = StaticCString::create("_shader_overrides_group_"); shader_overrides_group_active = StaticCString::create("_shader_overrides_group_active_"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 7ed86cde46..5f68e5180c 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -134,7 +134,6 @@ public: StringName Master; - StringName parameters_base_path; StringName window_input; StringName theme_changed; |