summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/project_settings.cpp50
-rw-r--r--core/project_settings.h2
-rw-r--r--doc/base/classes.xml24
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp7
-rw-r--r--editor/plugins/theme_editor_plugin.cpp59
-rw-r--r--editor/plugins/theme_editor_plugin.h3
-rw-r--r--editor/project_manager.cpp27
-rw-r--r--modules/visual_script/visual_script_editor.cpp10
-rw-r--r--platform/android/export/export.cpp27
-rw-r--r--platform/osx/os_osx.h1
-rw-r--r--platform/osx/os_osx.mm82
-rw-r--r--scene/gui/graph_edit.cpp2
-rw-r--r--scene/gui/tabs.cpp2
13 files changed, 202 insertions, 94 deletions
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index 0426af3fa0..b31f78ec20 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -455,8 +455,10 @@ Error ProjectSettings::_load_settings(const String p_path) {
memdelete(f);
ERR_FAIL_COND_V(config_version > FORMAT_VERSION, ERR_FILE_CANT_OPEN);
}
+ } else {
+ // config_version is checked and dropped
+ set(section + "/" + assign, value);
}
- set(section + "/" + assign, value);
} else if (next_tag.name != String()) {
section = next_tag.name;
}
@@ -600,6 +602,15 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
ERR_FAIL_COND_V(err, err)
}
+ file->store_line("; Engine configuration file.");
+ file->store_line("; It's best edited using the editor UI and not directly,");
+ file->store_line("; since the parameters that go here are not all obvious.");
+ file->store_line("; ");
+ file->store_line("; Format: ");
+ file->store_line("; [section] ; section goes between []");
+ file->store_line("; param=value ; assign values to parameters");
+ file->store_line("");
+
file->store_string("config_version=" + itos(FORMAT_VERSION) + "\n");
if (p_custom_features != String())
file->store_string("custom_features=\"" + p_custom_features + "\"\n");
@@ -640,38 +651,43 @@ Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other par
return save_custom(p_file);
};
-Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features) {
+Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) {
ERR_FAIL_COND_V(p_path == "", ERR_INVALID_PARAMETER);
Set<_VCSort> vclist;
- for (Map<StringName, VariantContainer>::Element *G = props.front(); G; G = G->next()) {
+ if (p_merge_with_current) {
+ for (Map<StringName, VariantContainer>::Element *G = props.front(); G; G = G->next()) {
- const VariantContainer *v = &G->get();
+ const VariantContainer *v = &G->get();
- if (v->hide_from_editor)
- continue;
+ if (v->hide_from_editor)
+ continue;
- if (p_custom.has(G->key()))
- continue;
+ if (p_custom.has(G->key()))
+ continue;
- _VCSort vc;
- vc.name = G->key(); //*k;
- vc.order = v->order;
- vc.type = v->variant.get_type();
- vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
- if (v->variant == v->initial)
- continue;
+ _VCSort vc;
+ vc.name = G->key(); //*k;
+ vc.order = v->order;
+ vc.type = v->variant.get_type();
+ vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
+ if (v->variant == v->initial)
+ continue;
- vclist.insert(vc);
+ vclist.insert(vc);
+ }
}
for (const Map<String, Variant>::Element *E = p_custom.front(); E; E = E->next()) {
+ // Lookup global prop to store in the same order
+ Map<StringName, VariantContainer>::Element *global_prop = props.find(E->key());
+
_VCSort vc;
vc.name = E->key();
- vc.order = 0xFFFFFFF;
+ vc.order = global_prop ? global_prop->get().order : 0xFFFFFFF;
vc.type = E->get().get_type();
vc.flags = PROPERTY_USAGE_STORAGE;
vclist.insert(vc);
diff --git a/core/project_settings.h b/core/project_settings.h
index 278d4b8132..c58ac3ca49 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -138,7 +138,7 @@ public:
Error setup(const String &p_path, const String &p_main_pack);
- Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>());
+ Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true);
Error save();
void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info);
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index cd366f01f8..058753132e 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -245,7 +245,7 @@
<description>
Returns the floating-point remainder of x/y (rounded towards zero):
[codeblock]
- fmod = x - tquot * y
+ fmod = x - tquot * y
[/codeblock]
Where tquot is the truncated (i.e., rounded towards zero) result of: x/y.
</description>
@@ -22387,7 +22387,16 @@
<argument index="0" name="rel_vec" type="Vector3">
</argument>
<description>
- Move the body in the given direction, stopping if there is an obstacle. The returned vector is how much movement was remaining before being stopped.
+ Move the body in the given direction, stopping if there is an obstacle. If as a result of a movement there will be any collision then informations about this collision will be in returned dictionary. Dictionary will contains those keys:
+ - "position" - collision position
+ - "normal" - collision normal
+ - "local_shape" - id of this kinematic body shape that took part in a collision
+ - "travel" - traveled movement before being stopped
+ - "remainder" - remaining movement before being stopped
+ - "collider_id" - id of the collider, it can be used when dealing with [PhysicsServer]
+ - "collider" - colliding body
+ - "collider_shape_index" - index of the colliding shape, inside collider body "collider_metadata"
+ If the body did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead. Please note that this method is less user friendly than [method move_and_slide]. If you don't want to program each edge case manually, then it's recommended to use [method move_and_slide] instead.
</description>
</method>
<method name="move_and_slide">
@@ -22569,7 +22578,16 @@
<argument index="0" name="rel_vec" type="Vector2">
</argument>
<description>
- Move the body in the given direction, stopping if there is an obstacle. The returned vector is how much movement was remaining before being stopped.
+ Move the body in the given direction, stopping if there is an obstacle. If as a result of a movement there will be any collision then informations about this collision will be in returned dictionary. Dictionary will contains those keys:
+ - "position" - collision position
+ - "normal" - collision normal
+ - "local_shape" - id of this kinematic body shape that took part in a collision
+ - "travel" - traveled movement before being stopped
+ - "remainder" - remaining movement before being stopped
+ - "collider_id" - id of the collider, it can be used when dealing with [Physics2DServer]
+ - "collider" - colliding body
+ - "collider_shape_index" - index of the colliding shape, inside collider body "collider_metadata"
+ If the body did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead. Please note that this method is less user friendly than [method move_and_slide]. If you don't want to program each edge case manually, then it's recommended to use [method move_and_slide] instead.
</description>
</method>
<method name="move_and_slide">
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 2a9f078d8c..89bea1e8cc 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -5999,6 +5999,13 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
static const int msaa_value[] = { 0, 2, 4, 8, 16 };
int msaa = msaa_value[rt->msaa];
+ int max_samples = 0;
+ glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+ if (msaa > max_samples) {
+ WARN_PRINTS("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples));
+ msaa = max_samples;
+ }
+
//regular fbo
glGenFramebuffers(1, &rt->buffers.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index a83ea70508..f5bb9d4a35 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -493,11 +493,10 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
Ref<Theme> base_theme;
- type_select->show();
- type_select_label->show();
name_select_label->show();
- name_edit->show();
- name_menu->show();
+ name_hbc->show();
+ type_select_label->show();
+ type_select->show();
if (p_option == POPUP_ADD) { //add
@@ -515,11 +514,10 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
base_theme = Theme::get_default();
- type_select->hide();
name_select_label->hide();
+ name_hbc->hide();
type_select_label->hide();
- name_edit->hide();
- name_menu->hide();
+ type_select->hide();
} else if (p_option == POPUP_REMOVE) {
@@ -537,11 +535,10 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
base_theme = Theme::get_default();
- type_select->hide();
name_select_label->hide();
+ name_hbc->hide();
type_select_label->hide();
- name_edit->hide();
- name_menu->hide();
+ type_select->hide();
}
popup_mode = p_option;
@@ -832,48 +829,46 @@ ThemeEditor::ThemeEditor() {
add_del_dialog->hide();
add_child(add_del_dialog);
+ VBoxContainer *dialog_vbc = memnew(VBoxContainer);
+ add_del_dialog->add_child(dialog_vbc);
+
Label *l = memnew(Label);
- l->set_position(Point2(5, 5) * EDSCALE);
l->set_text(TTR("Type:"));
- add_del_dialog->add_child(l);
- dtype_select_label = l;
+ dialog_vbc->add_child(l);
+
+ type_hbc = memnew(HBoxContainer);
+ dialog_vbc->add_child(type_hbc);
type_edit = memnew(LineEdit);
- type_edit->set_position(Point2(5, 25) * EDSCALE);
- type_edit->set_size(Point2(150, 5) * EDSCALE);
- add_del_dialog->add_child(type_edit);
+ type_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ type_hbc->add_child(type_edit);
type_menu = memnew(MenuButton);
- type_menu->set_position(Point2(160, 25) * EDSCALE);
- type_menu->set_size(Point2(30, 5) * EDSCALE);
type_menu->set_text("..");
- add_del_dialog->add_child(type_menu);
+ type_hbc->add_child(type_menu);
type_menu->get_popup()->connect("id_pressed", this, "_type_menu_cbk");
l = memnew(Label);
- l->set_position(Point2(200, 5) * EDSCALE);
l->set_text(TTR("Name:"));
- add_del_dialog->add_child(l);
+ dialog_vbc->add_child(l);
name_select_label = l;
+ name_hbc = memnew(HBoxContainer);
+ dialog_vbc->add_child(name_hbc);
+
name_edit = memnew(LineEdit);
- name_edit->set_position(Point2(200, 25) * EDSCALE);
- name_edit->set_size(Point2(150, 5) * EDSCALE);
- add_del_dialog->add_child(name_edit);
+ name_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ name_hbc->add_child(name_edit);
name_menu = memnew(MenuButton);
- name_menu->set_position(Point2(360, 25) * EDSCALE);
- name_menu->set_size(Point2(30, 5) * EDSCALE);
name_menu->set_text("..");
-
- add_del_dialog->add_child(name_menu);
+ name_hbc->add_child(name_menu);
name_menu->get_popup()->connect("about_to_show", this, "_name_menu_about_to_show");
name_menu->get_popup()->connect("id_pressed", this, "_name_menu_cbk");
type_select_label = memnew(Label);
- type_select_label->set_position(Point2(400, 5) * EDSCALE);
type_select_label->set_text(TTR("Data Type:"));
- add_del_dialog->add_child(type_select_label);
+ dialog_vbc->add_child(type_select_label);
type_select = memnew(OptionButton);
type_select->add_item(TTR("Icon"));
@@ -881,10 +876,8 @@ ThemeEditor::ThemeEditor() {
type_select->add_item(TTR("Font"));
type_select->add_item(TTR("Color"));
type_select->add_item(TTR("Constant"));
- type_select->set_position(Point2(400, 25) * EDSCALE);
- type_select->set_size(Point2(80, 5) * EDSCALE);
- add_del_dialog->add_child(type_select);
+ dialog_vbc->add_child(type_select);
add_del_dialog->get_ok()->connect("pressed", this, "_dialog_cbk");
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 6db01c6246..a75b83e76a 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -54,14 +54,15 @@ class ThemeEditor : public Control {
MenuButton *theme_menu;
ConfirmationDialog *add_del_dialog;
+ HBoxContainer *type_hbc;
MenuButton *type_menu;
LineEdit *type_edit;
+ HBoxContainer *name_hbc;
MenuButton *name_menu;
LineEdit *name_edit;
OptionButton *type_select;
Label *type_select_label;
Label *name_select_label;
- Label *dtype_select_label;
enum PopupMode {
POPUP_ADD,
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index acf5fe02cc..82f17b80d5 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -187,30 +187,17 @@ private:
} else {
if (mode == MODE_NEW) {
- FileAccess *f = FileAccess::open(dir.plus_file("/project.godot"), FileAccess::WRITE);
- if (!f) {
+ ProjectSettings::CustomMap initial_settings;
+ initial_settings["application/config/name"] = project_name->get_text();
+ initial_settings["application/config/icon"] = "res://icon.png";
+ initial_settings["rendering/environment/default_environment"] = "res://default_env.tres";
+
+ if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("/project.godot"), initial_settings, Vector<String>(), false)) {
error->set_text(TTR("Couldn't create project.godot in project path."));
} else {
-
- f->store_line("; Engine configuration file.");
- f->store_line("; It's best edited using the editor UI and not directly,");
- f->store_line("; since the parameters that go here are not all obvious.");
- f->store_line("; ");
- f->store_line("; Format: ");
- f->store_line("; [section] ; section goes between []");
- f->store_line("; param=value ; assign values to parameters");
- f->store_line("\n");
- f->store_line("[application]");
- f->store_line("\n");
- f->store_line("config/name=\"" + project_name->get_text() + "\"");
- f->store_line("config/icon=\"res://icon.png\"");
- f->store_line("[rendering]");
- f->store_line("environment/default_environment=\"res://default_env.tres\"");
- memdelete(f);
-
ResourceSaver::save(dir.plus_file("/icon.png"), get_icon("DefaultProjectIcon", "EditorIcons"));
- f = FileAccess::open(dir.plus_file("/default_env.tres"), FileAccess::WRITE);
+ FileAccess *f = FileAccess::open(dir.plus_file("/default_env.tres"), FileAccess::WRITE);
if (!f) {
error->set_text(TTR("Couldn't create project.godot in project path."));
} else {
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index ba3463445d..35358d5a1f 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -2328,6 +2328,16 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot,
undo_redo->add_do_method(script.ptr(), "sequence_connect", edited_func, p_from.to_int(), from_port, p_to.to_int());
undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int());
} else {
+
+ // disconect current, and connect the new one
+ if (script->is_input_value_port_connected(edited_func, p_to.to_int(), to_port)) {
+ int conn_from;
+ int conn_port;
+ script->get_input_value_port_connection_source(edited_func, p_to.to_int(), to_port, &conn_from, &conn_port);
+ undo_redo->add_do_method(script.ptr(), "data_disconnect", edited_func, conn_from, conn_port, p_to.to_int(), to_port);
+ undo_redo->add_undo_method(script.ptr(), "data_connect", edited_func, conn_from, conn_port, p_to.to_int(), to_port);
+ }
+
undo_redo->add_do_method(script.ptr(), "data_connect", edited_func, p_from.to_int(), from_port, p_to.to_int(), to_port);
undo_redo->add_undo_method(script.ptr(), "data_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int(), to_port);
//update nodes in sgraph
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 97f239c4da..a722cd1b8c 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -2050,6 +2050,7 @@ class EditorExportAndroid : public EditorExportPlatform {
String id;
String name;
String description;
+ int release;
};
struct APKExportData {
@@ -2123,6 +2124,7 @@ class EditorExportAndroid : public EditorExportPlatform {
if (ea->devices[j].id == ldevices[i]) {
d.description = ea->devices[j].description;
d.name = ea->devices[j].name;
+ d.release = ea->devices[j].release;
}
}
@@ -2143,6 +2145,7 @@ class EditorExportAndroid : public EditorExportPlatform {
String vendor;
String device;
d.description + "Device ID: " + d.id + "\n";
+ d.release = 0;
for (int j = 0; j < props.size(); j++) {
String p = props[j];
@@ -2153,7 +2156,9 @@ class EditorExportAndroid : public EditorExportPlatform {
} else if (p.begins_with("ro.build.display.id=")) {
d.description += "Build: " + p.get_slice("=", 1).strip_edges() + "\n";
} else if (p.begins_with("ro.build.version.release=")) {
- d.description += "Release: " + p.get_slice("=", 1).strip_edges() + "\n";
+ const String release_str = p.get_slice("=", 1).strip_edges();
+ d.description += "Release: " + release_str + "\n";
+ d.release = release_str.to_int();
} else if (p.begins_with("ro.product.cpu.abi=")) {
d.description += "CPU: " + p.get_slice("=", 1).strip_edges() + "\n";
} else if (p.begins_with("ro.product.manufacturer=")) {
@@ -3005,15 +3010,19 @@ public:
if (use_adb_over_usb) {
args.clear();
+ args.push_back("-s");
+ args.push_back(devices[p_device].id);
args.push_back("reverse");
args.push_back("--remove-all");
err = OS::get_singleton()->execute(adb, args, true, NULL, NULL, &rv);
- int port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
+ int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
args.clear();
+ args.push_back("-s");
+ args.push_back(devices[p_device].id);
args.push_back("reverse");
- args.push_back("tcp:" + itos(port));
- args.push_back("tcp:" + itos(port));
+ args.push_back("tcp:" + itos(dbg_port));
+ args.push_back("tcp:" + itos(dbg_port));
err = OS::get_singleton()->execute(adb, args, true, NULL, NULL, &rv);
print_line("Reverse result: " + itos(rv));
@@ -3021,6 +3030,8 @@ public:
int fs_port = EditorSettings::get_singleton()->get("filesystem/file_server/port");
args.clear();
+ args.push_back("-s");
+ args.push_back(devices[p_device].id);
args.push_back("reverse");
args.push_back("tcp:" + itos(fs_port));
args.push_back("tcp:" + itos(fs_port));
@@ -3036,7 +3047,10 @@ public:
args.push_back("shell");
args.push_back("am");
args.push_back("start");
- args.push_back("--user 0");
+ if ((bool)EditorSettings::get_singleton()->get("export/android/force_system_user") && devices[p_device].release >= 17) { // Multi-user introduced in Android 17
+ args.push_back("--user");
+ args.push_back("0");
+ }
args.push_back("-a");
args.push_back("android.intent.action.MAIN");
args.push_back("-n");
@@ -3044,7 +3058,7 @@ public:
err = OS::get_singleton()->execute(adb, args, true, NULL, NULL, &rv);
if (err || rv != 0) {
- EditorNode::add_io_error("Could not execute ondevice.");
+ EditorNode::add_io_error("Could not execute on device.");
device_lock->unlock();
return ERR_CANT_CREATE;
}
@@ -3586,6 +3600,7 @@ void register_android_exporter() {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "keystore"));
EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey");
EDITOR_DEF("export/android/debug_keystore_pass", "android");
+ EDITOR_DEF("export/android/force_system_user", false);
EDITOR_DEF("export/android/timestamping_authority_url", "");
EDITOR_DEF("export/android/use_remote_debug_over_adb", false);
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 44f4334786..fc80088846 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -105,7 +105,6 @@ public:
Vector<int> screen_dpi;
Size2 window_size;
- int current_screen;
Rect2 restore_rect;
power_osx *power_manager;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 924417fb36..fce38b6a8b 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -152,6 +152,16 @@ static bool mouse_down_control = false;
return NO;
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+- (void)windowDidEnterFullScreen:(NSNotification *)notification {
+ OS_OSX::singleton->zoomed = true;
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification {
+ OS_OSX::singleton->zoomed = false;
+}
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED
+
- (void)windowDidResize:(NSNotification *)notification {
[OS_OSX::singleton->context update];
@@ -161,6 +171,12 @@ static bool mouse_down_control = false;
OS_OSX::singleton->window_size.width = fbRect.size.width * OS_OSX::singleton->display_scale;
OS_OSX::singleton->window_size.height = fbRect.size.height * OS_OSX::singleton->display_scale;
+ if (OS_OSX::singleton->main_loop) {
+ Main::force_redraw();
+ //Event retrieval blocks until resize is over. Call Main::iteration() directly.
+ Main::iteration();
+ }
+
/*
_GodotInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
_GodotInputWindowSize(window, contentRect.size.width, contentRect.size.height);
@@ -1233,13 +1249,21 @@ int OS_OSX::get_screen_count() const {
};
int OS_OSX::get_current_screen() const {
-
- return current_screen;
+ Vector2 wpos = get_window_position();
+
+ int count = get_screen_count();
+ for (int i = 0; i < count; i++) {
+ Point2 pos = get_screen_position(i);
+ Size2 size = get_screen_size(i);
+ if ((wpos.x >= pos.x && wpos.x < pos.x + size.width) && (wpos.y >= pos.y && wpos.y < pos.y + size.height))
+ return i;
+ }
+ return 0;
};
void OS_OSX::set_current_screen(int p_screen) {
-
- current_screen = p_screen;
+ Vector2 wpos = get_window_position() - get_screen_position(get_current_screen());
+ set_window_position(wpos + get_screen_position(p_screen));
};
Point2 OS_OSX::get_screen_position(int p_screen) const {
@@ -1383,7 +1407,7 @@ void OS_OSX::set_window_maximized(bool p_enabled) {
if (p_enabled) {
restore_rect = Rect2(get_window_position(), get_window_size());
- [window_object setFrame:[[[NSScreen screens] objectAtIndex:current_screen] visibleFrame] display:YES];
+ [window_object setFrame:[[[NSScreen screens] objectAtIndex:get_current_screen()] visibleFrame] display:YES];
} else {
set_window_size(restore_rect.size);
set_window_position(restore_rect.position);
@@ -1661,12 +1685,52 @@ OS_OSX::OS_OSX() {
// In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-#if 0
// Menu bar setup must go between sharedApplication above and
// finishLaunching below, in order to properly emulate the behavior
// of NSApplicationMain
- createMenuBar();
-#endif
+ NSMenuItem *menu_item;
+ NSString *title;
+
+ NSString *nsappname = [[[NSBundle mainBundle] performSelector:@selector(localizedInfoDictionary)] objectForKey:@"CFBundleName"];
+ if (nsappname == nil)
+ nsappname = [[NSProcessInfo processInfo] processName];
+
+ // Setup Apple menu
+ NSMenu *apple_menu = [[NSMenu alloc] initWithTitle:@""];
+ title = [NSString stringWithFormat:NSLocalizedString(@"About %@", nil), nsappname];
+ [apple_menu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+
+ [apple_menu addItem:[NSMenuItem separatorItem]];
+
+ NSMenu *services = [[NSMenu alloc] initWithTitle:@""];
+ menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Services", nil) action:nil keyEquivalent:@""];
+ [apple_menu setSubmenu:services forItem:menu_item];
+ [NSApp setServicesMenu:services];
+ [services release];
+
+ [apple_menu addItem:[NSMenuItem separatorItem]];
+
+ title = [NSString stringWithFormat:NSLocalizedString(@"Hide %@", nil), nsappname];
+ [apple_menu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+
+ menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Hide Others", nil) action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+ [menu_item setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)];
+
+ [apple_menu addItemWithTitle:NSLocalizedString(@"Show all", nil) action:@selector(unhideAllApplications:) keyEquivalent:@""];
+
+ [apple_menu addItem:[NSMenuItem separatorItem]];
+
+ title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname];
+ [apple_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+
+ // Setup menu bar
+ NSMenu *main_menu = [[NSMenu alloc] initWithTitle:@""];
+ menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
+ [main_menu setSubmenu:apple_menu forItem:menu_item];
+ [NSApp setMainMenu:main_menu];
+
+ [main_menu release];
+ [apple_menu release];
[NSApp finishLaunching];
@@ -1676,8 +1740,6 @@ OS_OSX::OS_OSX() {
cursor_shape = CURSOR_ARROW;
- current_screen = 0;
-
maximized = false;
minimized = false;
window_size = Vector2(1024, 600);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 1d37529a87..11f750ea70 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -601,7 +601,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
int cp_neg_len = get_constant("bezier_len_neg");
if (diff > 0) {
- cp_offset = MAX(cp_len, diff * 0.5);
+ cp_offset = MIN(cp_len, diff * 0.5);
} else {
cp_offset = MAX(MIN(cp_len - diff, cp_neg_len), -diff * 0.5);
}
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index c477a3156f..24eb19fbc2 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -793,7 +793,7 @@ void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &Tabs::set_tab_disabled);
ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &Tabs::get_tab_disabled);
ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &Tabs::remove_tab);
- ClassDB::bind_method(D_METHOD("add_tab", "title", "icon:Texture"), &Tabs::add_tab);
+ ClassDB::bind_method(D_METHOD("add_tab", "title", "icon:Texture"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align);
ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align);
ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible);