diff options
-rw-r--r-- | core/math/math_2d.h | 2 | ||||
-rw-r--r-- | editor/editor_node.cpp | 81 | ||||
-rw-r--r-- | editor/editor_node.h | 17 | ||||
-rw-r--r-- | editor/editor_plugin.cpp | 13 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 1 | ||||
-rw-r--r-- | editor/plugins/spatial_editor_plugin.cpp | 14 | ||||
-rw-r--r-- | editor/project_settings_editor.cpp | 17 | ||||
-rw-r--r-- | editor/scene_tree_dock.cpp | 66 | ||||
-rw-r--r-- | platform/osx/os_osx.h | 1 | ||||
-rw-r--r-- | platform/osx/os_osx.mm | 50 | ||||
-rw-r--r-- | scene/3d/camera.cpp | 9 | ||||
-rw-r--r-- | scene/3d/camera.h | 2 | ||||
-rw-r--r-- | scene/3d/scenario_fx.cpp | 10 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 11 | ||||
-rw-r--r-- | scene/gui/rich_text_label.h | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 5 | ||||
-rw-r--r-- | servers/arvr_server.cpp | 50 | ||||
-rw-r--r-- | servers/arvr_server.h | 17 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_compressor.cpp | 2 | ||||
-rw-r--r-- | servers/visual/visual_server_viewport.cpp | 10 |
20 files changed, 264 insertions, 116 deletions
diff --git a/core/math/math_2d.h b/core/math/math_2d.h index 02d921b67e..e7188da85b 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -303,7 +303,7 @@ struct Rect2 { inline real_t distance_to(const Vector2 &p_point) const { - real_t dist; + real_t dist = 0.0; bool inside = true; if (p_point.x < position.x) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c58f1cffa0..364e989c84 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -190,6 +190,8 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed() && !k->is_echo() && !gui_base->get_viewport()->gui_has_modal_stack()) { + EditorPlugin *old_editor = editor_plugin_screen; + if (ED_IS_SHORTCUT("editor/next_tab", p_event)) { int next_tab = editor_data.get_edited_scene() + 1; next_tab %= editor_data.get_edited_scene_count(); @@ -225,6 +227,10 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) { _bottom_panel_switch(false, i); } } + + if (old_editor != editor_plugin_screen) { + get_tree()->set_input_as_handled(); + } } } @@ -1599,7 +1605,8 @@ void EditorNode::_edit_current() { // special case if use of external editor is true if (main_plugin->get_name() == "Script" && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) { - main_plugin->edit(current_obj); + if (!changing_scene) + main_plugin->edit(current_obj); } else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) { @@ -2122,10 +2129,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { log->add_message("REDO: " + action); } break; - case TOOLS_ORPHAN_RESOURCES: { - - orphan_resources->show(); - } break; case EDIT_REVERT: { @@ -2571,6 +2574,30 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } +void EditorNode::_tool_menu_option(int p_idx) { + switch (tool_menu->get_item_id(p_idx)) { + case TOOLS_ORPHAN_RESOURCES: { + orphan_resources->show(); + } break; + case TOOLS_CUSTOM: { + if (tool_menu->get_item_submenu(p_idx) == "") { + Array params = tool_menu->get_item_metadata(p_idx); + + Object *handler = ObjectDB::get_instance(params[0]); + String callback = params[1]; + Variant *ud = ¶ms[2]; + Variant::CallError ce; + + handler->call(callback, (const Variant **)&ud, 1, ce); + if (ce.error != Variant::CallError::CALL_OK) { + String err = Variant::get_call_error_text(handler, callback, (const Variant **)&ud, 1, ce); + ERR_PRINTS("Error calling function from tool menu: " + err); + } + } // else it's a submenu so don't do anything. + } break; + } +} + int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { for (int i = p_start; i < editor_data.get_edited_scene_count(); i++) { @@ -4463,6 +4490,45 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control * return drag_data; } +void EditorNode::add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud) { + ERR_FAIL_NULL(p_handler); + int idx = tool_menu->get_item_count(); + tool_menu->add_item(p_name, TOOLS_CUSTOM); + + Array parameters; + parameters.push_back(p_handler->get_instance_id()); + parameters.push_back(p_callback); + parameters.push_back(p_ud); + + tool_menu->set_item_metadata(idx, parameters); +} + +void EditorNode::add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu) { + ERR_FAIL_NULL(p_submenu); + ERR_FAIL_COND(p_submenu->get_parent() != NULL); + + tool_menu->add_child(p_submenu); + tool_menu->add_submenu_item(p_name, p_submenu->get_name(), TOOLS_CUSTOM); +} + +void EditorNode::remove_tool_menu_item(const String &p_name) { + for (int i = 0; i < tool_menu->get_item_count(); i++) { + if (tool_menu->get_item_id(i) != TOOLS_CUSTOM) + continue; + + if (tool_menu->get_item_text(i) == p_name) { + if (tool_menu->get_item_submenu(i) != "") { + Node *n = tool_menu->get_node(tool_menu->get_item_submenu(i)); + tool_menu->remove_child(n); + memdelete(n); + } + tool_menu->remove_item(i); + tool_menu->set_as_minsize(); + return; + } + } +} + void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_current_path()); @@ -4659,6 +4725,7 @@ Vector<Ref<EditorResourceConversionPlugin> > EditorNode::find_resource_conversio void EditorNode::_bind_methods() { ClassDB::bind_method("_menu_option", &EditorNode::_menu_option); + ClassDB::bind_method("_tool_menu_option", &EditorNode::_tool_menu_option); ClassDB::bind_method("_menu_confirm_current", &EditorNode::_menu_confirm_current); ClassDB::bind_method("_dialog_action", &EditorNode::_dialog_action); ClassDB::bind_method("_resource_selected", &EditorNode::_resource_selected, DEFVAL("")); @@ -5257,9 +5324,9 @@ EditorNode::EditorNode() { p->connect("id_pressed", this, "_menu_option"); p->add_item(TTR("Export"), FILE_EXPORT_PROJECT); - PopupMenu *tool_menu = memnew(PopupMenu); + tool_menu = memnew(PopupMenu); tool_menu->set_name("Tools"); - tool_menu->connect("id_pressed", this, "_menu_option"); + tool_menu->connect("index_pressed", this, "_tool_menu_option"); p->add_child(tool_menu); p->add_submenu_item(TTR("Tools"), "Tools"); tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES); diff --git a/editor/editor_node.h b/editor/editor_node.h index 9090066dea..90bebffca6 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -141,6 +141,7 @@ private: EDIT_REDO, EDIT_REVERT, TOOLS_ORPHAN_RESOURCES, + TOOLS_CUSTOM, RESOURCE_NEW, RESOURCE_LOAD, RESOURCE_SAVE, @@ -426,6 +427,7 @@ private: void _menu_option(int p_option); void _menu_confirm_current(); void _menu_option_confirm(int p_option, bool p_confirmed); + void _tool_menu_option(int p_idx); void _update_debug_options(); void _property_editor_forward(); @@ -600,21 +602,6 @@ private: static int build_callback_count; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; - bool _initializing_tool_menu; - - struct ToolMenuItem { - String name; - String submenu; - Variant ud; - ObjectID handler; - String callback; - }; - - Vector<ToolMenuItem> tool_menu_items; - - void _tool_menu_insert_item(const ToolMenuItem &p_item); - void _rebuild_tool_menu() const; - bool _dimming; float _dim_time; Timer *_dim_timer; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 31d0bfa8a9..4f38c0188d 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -429,21 +429,18 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati } void EditorPlugin::add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud) { - - //EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud); + EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud); } void EditorPlugin::add_tool_submenu_item(const String &p_name, Object *p_submenu) { - ERR_FAIL_NULL(p_submenu); PopupMenu *submenu = Object::cast_to<PopupMenu>(p_submenu); ERR_FAIL_NULL(submenu); - //EditorNode::get_singleton()->add_tool_submenu_item(p_name, submenu); + EditorNode::get_singleton()->add_tool_submenu_item(p_name, submenu); } void EditorPlugin::remove_tool_menu_item(const String &p_name) { - - //EditorNode::get_singleton()->remove_tool_menu_item(p_name); + EditorNode::get_singleton()->remove_tool_menu_item(p_name); } void EditorPlugin::set_input_event_forwarding_always_enabled() { @@ -707,9 +704,9 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_control_from_docks", "control"), &EditorPlugin::remove_control_from_docks); ClassDB::bind_method(D_METHOD("remove_control_from_bottom_panel", "control"), &EditorPlugin::remove_control_from_bottom_panel); ClassDB::bind_method(D_METHOD("remove_control_from_container", "container", "control"), &EditorPlugin::remove_control_from_container); - //ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "handler", "callback", "ud"), &EditorPlugin::add_tool_menu_item, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("add_tool_submenu_item", "name", "submenu"), &EditorPlugin::add_tool_submenu_item); - //ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item); + ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"), &EditorPlugin::remove_tool_menu_item); ClassDB::bind_method(D_METHOD("add_custom_type", "type", "base", "script", "icon"), &EditorPlugin::add_custom_type); ClassDB::bind_method(D_METHOD("remove_custom_type", "type"), &EditorPlugin::remove_custom_type); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 26649ad2ec..85f6d99c67 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -409,6 +409,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // navigation _initial_set("editors/3d/navigation/navigation_scheme", 0); + _initial_set("editors/3d/navigation/invert_y-axis", false); hints["editors/3d/navigation/navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/navigation/navigation_scheme", PROPERTY_HINT_ENUM, "Godot,Maya,Modo"); _initial_set("editors/3d/navigation/zoom_style", 0); hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal"); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 9e7bfd5787..e484140527 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -1907,8 +1907,13 @@ void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, con real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); - cursor.x_rot += p_relative.y * radians_per_pixel; + if (invert_y_axis) { + cursor.x_rot -= p_relative.y * radians_per_pixel; + } else { + cursor.x_rot += p_relative.y * radians_per_pixel; + } cursor.y_rot += p_relative.x * radians_per_pixel; if (cursor.x_rot > Math_PI / 2.0) cursor.x_rot = Math_PI / 2.0; @@ -1925,11 +1930,16 @@ void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, cons if (!orthogonal) { real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". Transform prev_camera_transform = to_camera_transform(cursor); - cursor.x_rot += p_relative.y * radians_per_pixel; + if (invert_y_axis) { + cursor.x_rot -= p_relative.y * radians_per_pixel; + } else { + cursor.x_rot += p_relative.y * radians_per_pixel; + } cursor.y_rot += p_relative.x * radians_per_pixel; if (cursor.x_rot > Math_PI / 2.0) cursor.x_rot = Math_PI / 2.0; diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 8080a04a67..75523cd843 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -123,6 +123,15 @@ void ProjectSettingsEditor::_notification(int p_what) { } } +static bool _validate_action_name(const String &p_name) { + const CharType *cstr = p_name.c_str(); + for (int i = 0; cstr[i]; i++) + if (cstr[i] == '/' || cstr[i] == ':' || cstr[i] == '"' || + cstr[i] == '=' || cstr[i] == '\\' || cstr[i] < 32) + return false; + return true; +} + void ProjectSettingsEditor::_action_selected() { TreeItem *ti = input_editor->get_selected(); @@ -145,12 +154,12 @@ void ProjectSettingsEditor::_action_edited() { if (new_name == old_name) return; - if (new_name.find("/") != -1 || new_name.find(":") != -1 || new_name.find("\"") != -1 || new_name == "") { + if (new_name == "" || !_validate_action_name(new_name)) { ti->set_text(0, old_name); add_at = "input/" + old_name; - message->set_text(TTR("Invalid action (anything goes but '/', ':' or '\"').")); + message->set_text(TTR("Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or '\"'")); message->popup_centered(Size2(300, 100) * EDSCALE); return; } @@ -838,9 +847,9 @@ void ProjectSettingsEditor::_action_check(String p_action) { action_add->set_disabled(true); } else { - if (p_action.find("/") != -1 || p_action.find(":") != -1 || p_action.find("\"") != -1) { + if (!_validate_action_name(p_action)) { - action_add_error->set_text(TTR("Can't contain '/', ':' or '\"'")); + action_add_error->set_text(TTR("Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or '\"'")); action_add_error->show(); action_add->set_disabled(true); return; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 002d702bac..d5ec858c37 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -345,17 +345,30 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } break; case TOOL_CLEAR_SCRIPT: { - Node *selected = scene_tree->get_selected(); - if (!selected) - break; - Ref<Script> existing = selected->get_script(); - if (existing.is_valid()) { - const RefPtr empty; - selected->set_script(empty); - _update_script_button(); + List<Node *> selection = editor_selection->get_selected_node_list(); + + if (selection.empty()) + return; + + editor_data->get_undo_redo().create_action(TTR("Clear Script")); + editor_data->get_undo_redo().add_do_method(editor, "push_item", (Script *)NULL); + + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + + Ref<Script> existing = E->get()->get_script(); + if (existing.is_valid()) { + const RefPtr empty; + editor_data->get_undo_redo().add_do_method(E->get(), "set_script", empty); + editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + } } + editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); + editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); + + editor_data->get_undo_redo().commit_action(); + } break; case TOOL_MOVE_UP: case TOOL_MOVE_DOWN: { @@ -1208,12 +1221,26 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V void SceneTreeDock::_script_created(Ref<Script> p_script) { - Node *selected = scene_tree->get_selected(); - if (!selected) + List<Node *> selected = editor_selection->get_selected_node_list(); + + if (selected.empty()) return; - selected->set_script(p_script.get_ref_ptr()); - editor->push_item(p_script.operator->()); - _update_script_button(); + + editor_data->get_undo_redo().create_action(TTR("Attach Script")); + for (List<Node *>::Element *E = selected.front(); E; E = E->next()) { + + Ref<Script> existing = E->get()->get_script(); + editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script.get_ref_ptr()); + editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + } + + editor_data->get_undo_redo().add_do_method(editor, "push_item", p_script.operator->()); + editor_data->get_undo_redo().add_undo_method(editor, "push_item", (Script *)NULL); + + editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); + editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); + + editor_data->get_undo_redo().commit_action(); } void SceneTreeDock::_delete_confirm() { @@ -1669,8 +1696,12 @@ void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) { ERR_FAIL_COND(!scr.is_valid()); Node *n = get_node(p_to); if (n) { - n->set_script(scr.get_ref_ptr()); - _update_script_button(); + editor_data->get_undo_redo().create_action(TTR("Attach Script")); + editor_data->get_undo_redo().add_do_method(n, "set_script", scr); + editor_data->get_undo_redo().add_undo_method(n, "set_script", n->get_script()); + editor_data->get_undo_redo().add_do_method(this, "_update_script_button"); + editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); + editor_data->get_undo_redo().commit_action(); } } @@ -1807,6 +1838,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder); } } + } else { + menu->add_separator(); + menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); } menu->add_separator(); menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); @@ -1925,6 +1960,7 @@ void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_focus_node"), &SceneTreeDock::_focus_node); ClassDB::bind_method(D_METHOD("_remote_tree_selected"), &SceneTreeDock::_remote_tree_selected); ClassDB::bind_method(D_METHOD("_local_tree_selected"), &SceneTreeDock::_local_tree_selected); + ClassDB::bind_method(D_METHOD("_update_script_button"), &SceneTreeDock::_update_script_button); ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance); diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 72ca8969d0..fee25e98cb 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -195,7 +195,6 @@ public: virtual VideoMode get_video_mode(int p_screen = 0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; - virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool p_read_stderr); virtual String get_executable_path() const; virtual LatinKeyboardVariant get_latin_keyboard_variant() const; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 56a6b5de23..ef23d61141 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -263,6 +263,7 @@ static Vector2 get_mouse_pos(NSEvent *event) { NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -2045,55 +2046,6 @@ bool OS_OSX::get_borderless_window() { return [window_object styleMask] == NSWindowStyleMaskBorderless; } -Error OS_OSX::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool p_read_stderr) { - - NSTask *task = [[NSTask alloc] init]; - NSPipe *stdout_pipe = nil; - [task setLaunchPath:[NSString stringWithUTF8String:p_path.utf8().get_data()]]; - - NSMutableArray *arguments = [[NSMutableArray alloc] initWithCapacity:p_arguments.size()]; - for (int i = 0; i < p_arguments.size(); i++) { - [arguments addObject:[NSString stringWithUTF8String:p_arguments[i].utf8().get_data()]]; - } - [task setArguments:arguments]; - - if (p_blocking && r_pipe) { - stdout_pipe = [NSPipe pipe]; - [task setStandardOutput:stdout_pipe]; - if (p_read_stderr) [task setStandardError:[task standardOutput]]; - } - - @try { - [task launch]; - if (r_child_id) - *r_child_id = [task processIdentifier]; - - if (p_blocking) { - if (r_pipe) { - NSFileHandle *read_handle = [stdout_pipe fileHandleForReading]; - NSData *data = nil; - while ((data = [read_handle availableData]) && [data length]) { - NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - (*r_pipe) += [string UTF8String]; - [string release]; - } - } else { - [task waitUntilExit]; - } - } - - [arguments release]; - [task release]; - return OK; - } @catch (NSException *exception) { - ERR_PRINTS("NSException: " + String([exception reason].UTF8String) + "; Path: " + p_path); - - [arguments release]; - [task release]; - return ERR_CANT_OPEN; - } -} - String OS_OSX::get_executable_path() const { int ret; diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 6998b34cfd..9de189c158 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -201,7 +201,7 @@ void Camera::make_current() { //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); } -void Camera::clear_current() { +void Camera::clear_current(bool p_enable_next) { current = false; if (!is_inside_tree()) @@ -209,7 +209,10 @@ void Camera::clear_current() { if (get_viewport()->get_camera() == this) { get_viewport()->_camera_set(NULL); - get_viewport()->_camera_make_next_current(this); + + if (p_enable_next) { + get_viewport()->_camera_make_next_current(this); + } } } @@ -439,7 +442,7 @@ void Camera::_bind_methods() { ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera::set_perspective); ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal); ClassDB::bind_method(D_METHOD("make_current"), &Camera::make_current); - ClassDB::bind_method(D_METHOD("clear_current"), &Camera::clear_current); + ClassDB::bind_method(D_METHOD("clear_current", "enable_next"), &Camera::clear_current, DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_current"), &Camera::set_current); ClassDB::bind_method(D_METHOD("is_current"), &Camera::is_current); ClassDB::bind_method(D_METHOD("get_camera_transform"), &Camera::get_camera_transform); diff --git a/scene/3d/camera.h b/scene/3d/camera.h index e2679870de..109bf3adc6 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -113,7 +113,7 @@ public: void set_projection(Camera::Projection p_mode); void make_current(); - void clear_current(); + void clear_current(bool p_enable_next = true); void set_current(bool p_current); bool is_current() const; diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/scenario_fx.cpp index 02768ac91f..d5bff676cb 100644 --- a/scene/3d/scenario_fx.cpp +++ b/scene/3d/scenario_fx.cpp @@ -79,7 +79,11 @@ Ref<Environment> WorldEnvironment::get_environment() const { String WorldEnvironment::get_configuration_warning() const { - if (/*!is_visible_in_tree() ||*/ !is_inside_tree() || !environment.is_valid()) + if (!environment.is_valid()) { + return TTR("WorldEnvironment needs an Environment resource."); + } + + if (/*!is_visible_in_tree() ||*/ !is_inside_tree()) return String(); List<Node *> nodes; @@ -89,6 +93,10 @@ String WorldEnvironment::get_configuration_warning() const { return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."); } + if (environment.is_valid() && get_viewport() && !get_viewport()->get_camera() && environment->get_background() != Environment::BG_CANVAS) { + return TTR("This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set this environment's Background Mode to Canvas (for 2D scenes)."); + } + return String(); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 5bc5d8e690..ae07d5e671 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -125,6 +125,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & l.descent_caches.clear(); l.char_count = 0; l.minimum_width = 0; + l.maximum_width = 0; } int wofs = margin; @@ -200,7 +201,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & #define ENSURE_WIDTH(m_width) \ if (p_mode == PROCESS_CACHE) { \ - l.minimum_width = MAX(l.minimum_width, wofs + m_width); \ + l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \ + l.minimum_width = MAX(l.minimum_width, m_width); \ } \ if (wofs + m_width > p_width) { \ if (p_mode == PROCESS_CACHE) { \ @@ -469,6 +471,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & //set minimums to zero for (int i = 0; i < table->columns.size(); i++) { table->columns[i].min_width = 0; + table->columns[i].max_width = 0; table->columns[i].width = 0; } //compute minimum width for each cell @@ -486,6 +489,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color()); table->columns[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); + table->columns[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width); } idx++; } @@ -498,12 +502,13 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < table->columns.size(); i++) { remaining_width -= table->columns[i].min_width; + if (table->columns[i].max_width > table->columns[i].min_width) + table->columns[i].expand = true; if (table->columns[i].expand) total_ratio += table->columns[i].expand_ratio; } //assign actual widths - for (int i = 0; i < table->columns.size(); i++) { table->columns[i].width = table->columns[i].min_width; if (table->columns[i].expand) @@ -1633,7 +1638,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { tag_stack.push_front(tag); } else if (tag.begins_with("cell=")) { - int ratio = tag.substr(6, tag.length()).to_int(); + int ratio = tag.substr(5, tag.length()).to_int(); if (ratio < 1) ratio = 1; //use monospace font diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index e7d5e6bb1b..83938cff61 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -87,6 +87,7 @@ private: int height_accum_cache; int char_count; int minimum_width; + int maximum_width; Line() { from = NULL; @@ -199,6 +200,7 @@ private: bool expand; int expand_ratio; int min_width; + int max_width; int width; }; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index cf22383e36..28b4540573 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2502,7 +2502,10 @@ void Node::replace_by(Node *p_node, bool p_keep_data) { Node *child = get_child(0); remove_child(child); - p_node->add_child(child); + if (!child->is_owned_by_parent()) { + // add the custom children to the p_node + p_node->add_child(child); + } } p_node->set_owner(owner); diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp index 8620b182df..f9d402fe7b 100644 --- a/servers/arvr_server.cpp +++ b/servers/arvr_server.cpp @@ -44,6 +44,7 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_world_scale"), &ARVRServer::set_world_scale); ClassDB::bind_method(D_METHOD("get_reference_frame"), &ARVRServer::get_reference_frame); ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &ARVRServer::center_on_hmd); + ClassDB::bind_method(D_METHOD("get_hmd_transform"), &ARVRServer::get_hmd_transform); ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale"); @@ -54,8 +55,13 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tracker_count"), &ARVRServer::get_tracker_count); ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &ARVRServer::get_tracker); + ClassDB::bind_method(D_METHOD("get_primary_interface"), &ARVRServer::get_primary_interface); ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &ARVRServer::set_primary_interface); + ClassDB::bind_method(D_METHOD("get_last_process_usec"), &ARVRServer::get_last_process_usec); + ClassDB::bind_method(D_METHOD("get_last_commit_usec"), &ARVRServer::get_last_commit_usec); + ClassDB::bind_method(D_METHOD("get_last_frame_usec"), &ARVRServer::get_last_frame_usec); + BIND_ENUM_CONSTANT(TRACKER_CONTROLLER); BIND_ENUM_CONSTANT(TRACKER_BASESTATION); BIND_ENUM_CONSTANT(TRACKER_ANCHOR); @@ -132,6 +138,14 @@ void ARVRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) }; }; +Transform ARVRServer::get_hmd_transform() { + Transform hmd_transform; + if (primary_interface != NULL) { + hmd_transform = primary_interface->get_transform_for_eye(ARVRInterface::EYE_MONO, hmd_transform); + }; + return hmd_transform; +}; + void ARVRServer::add_interface(const Ref<ARVRInterface> &p_interface) { ERR_FAIL_COND(p_interface.is_null()); @@ -314,6 +328,42 @@ void ARVRServer::clear_primary_interface_if(const Ref<ARVRInterface> &p_primary_ }; }; +uint64_t ARVRServer::get_last_process_usec() { + return last_process_usec; +}; + +uint64_t ARVRServer::get_last_commit_usec() { + return last_commit_usec; +}; + +uint64_t ARVRServer::get_last_frame_usec() { + return last_frame_usec; +}; + +void ARVRServer::_process() { + /* called from visual_server_viewport.draw_viewports right before we start drawing our viewports */ + + /* mark for our frame timing */ + last_process_usec = OS::get_singleton()->get_ticks_usec(); + + /* process all active interfaces */ + for (int i = 0; i < interfaces.size(); i++) { + if (!interfaces[i].is_valid()) { + // ignore, not a valid reference + } else if (interfaces[i]->is_initialized()) { + interfaces[i]->process(); + }; + }; +}; + +void ARVRServer::_mark_commit() { + /* time this */ + last_commit_usec = OS::get_singleton()->get_ticks_usec(); + + /* now store our difference as we may overwrite last_process_usec before this is accessed */ + last_frame_usec = last_commit_usec - last_process_usec; +}; + ARVRServer::ARVRServer() { singleton = this; world_scale = 1.0; diff --git a/servers/arvr_server.h b/servers/arvr_server.h index 63b7edc73b..1f4d84fe19 100644 --- a/servers/arvr_server.h +++ b/servers/arvr_server.h @@ -31,6 +31,7 @@ #ifndef ARVR_SERVER_H #define ARVR_SERVER_H +#include "os/os.h" #include "os/thread_safe.h" #include "reference.h" #include "rid.h" @@ -84,6 +85,10 @@ private: Transform world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */ Transform reference_frame; /* our reference frame */ + uint64_t last_process_usec; /* for frame timing, usec when we did our processing */ + uint64_t last_commit_usec; /* for frame timing, usec when we finished committing both eyes */ + uint64_t last_frame_usec; /* time it took between process and commiting, we should probably average this over the last x frames */ + protected: static ARVRServer *singleton; @@ -134,6 +139,11 @@ public: void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height); /* + get_hmd_transform gets our hmd transform (centered between eyes) with most up to date tracking, relative to the origin + */ + Transform get_hmd_transform(); + + /* Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc. */ void add_interface(const Ref<ARVRInterface> &p_interface); @@ -163,6 +173,13 @@ public: ARVRPositionalTracker *get_tracker(int p_index) const; ARVRPositionalTracker *find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const; + uint64_t get_last_process_usec(); + uint64_t get_last_commit_usec(); + uint64_t get_last_frame_usec(); + + void _process(); + void _mark_commit(); + ARVRServer(); ~ARVRServer(); }; diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index 0252b2f341..8c70b51f8d 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -236,7 +236,7 @@ void AudioEffectCompressor::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "attack_us", PROPERTY_HINT_RANGE, "20,2000,1"), "set_attack_us", "get_attack_us"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1"), "set_release_ms", "get_release_ms"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_mix", "get_mix"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain"); } AudioEffectCompressor::AudioEffectCompressor() { diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 3eb8953c1f..83e05f6f25 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -239,10 +239,9 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E void VisualServerViewport::draw_viewports() { // get our arvr interface in case we need it Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - if (arvr_interface.is_valid()) { - // update our positioning information as late as possible... - arvr_interface->process(); - } + + // process all our active interfaces + ARVRServer::get_singleton()->_process(); clear_color = GLOBAL_GET("rendering/environment/default_clear_color"); @@ -286,6 +285,9 @@ void VisualServerViewport::draw_viewports() { _draw_viewport(vp, ARVRInterface::EYE_RIGHT); arvr_interface->commit_for_eye(ARVRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect); } + + // and for our frame timing, mark when we've finished commiting our eyes + ARVRServer::get_singleton()->_mark_commit(); } else { VSG::rasterizer->set_current_render_target(vp->render_target); |