summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/os/dir_access.cpp97
-rw-r--r--core/os/dir_access.h4
-rw-r--r--core/os/os.cpp27
-rw-r--r--core/script_debugger_remote.cpp157
-rw-r--r--core/script_language.h7
-rw-r--r--core/ustring.cpp11
-rw-r--r--core/ustring.h2
-rw-r--r--doc/classes/@GDScript.xml22
-rw-r--r--editor/dictionary_property_edit.cpp189
-rw-r--r--editor/dictionary_property_edit.h (renamed from misc/dist/ios_xcode/godot_ios/main.m)41
-rw-r--r--editor/editor_export.cpp122
-rw-r--r--editor/editor_export.h65
-rw-r--r--editor/editor_node.cpp15
-rw-r--r--editor/editor_path.cpp10
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/filesystem_dock.cpp11
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp12
-rw-r--r--editor/project_export.cpp6
-rw-r--r--editor/project_export.h2
-rw-r--r--editor/property_editor.cpp34
-rw-r--r--editor/scene_tree_dock.cpp2
-rw-r--r--editor/script_editor_debugger.cpp199
-rw-r--r--editor/script_editor_debugger.h13
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.debug.fat0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.arm0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.arm640
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.fat0
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj91
-rw-r--r--misc/dist/ios_xcode/godot_ios/dummy.cpp1
-rw-r--r--misc/dist/ios_xcode/godot_ios/dylibs/empty1
-rw-r--r--misc/dist/ios_xcode/godot_ios/export_options.plist (renamed from misc/dist/ios_xcode/export_options.plist)10
-rw-r--r--misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist3
-rw-r--r--[-rwxr-xr-x]misc/dist/ios_xcode/libgodot.iphone.debug.fat.a (renamed from misc/dist/ios_xcode/godot.iphone.debug.arm)0
-rw-r--r--[-rwxr-xr-x]misc/dist/ios_xcode/libgodot.iphone.release.fat.a (renamed from misc/dist/ios_xcode/godot.iphone.debug.arm64)0
-rw-r--r--modules/etc/image_etc.cpp14
-rw-r--r--modules/gdnative/gdnative.cpp8
-rw-r--r--modules/gdnative/gdnative.h2
-rw-r--r--modules/gdnative/register_types.cpp89
-rw-r--r--modules/gdscript/gdscript.cpp19
-rw-r--r--modules/gdscript/gdscript.h8
-rw-r--r--modules/gdscript/gdscript_compiler.cpp25
-rw-r--r--modules/gdscript/gdscript_editor.cpp60
-rw-r--r--modules/gdscript/gdscript_functions.cpp30
-rw-r--r--modules/gdscript/gdscript_functions.h2
-rw-r--r--modules/gdscript/gdscript_parser.cpp35
-rw-r--r--modules/mono/glue/cs_files/Mathf.cs10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml50
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp38
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h2
-rw-r--r--modules/webm/config.py2
-rw-r--r--platform/android/os_android.cpp19
-rw-r--r--platform/iphone/SCsub12
-rw-r--r--platform/iphone/detect.py19
-rw-r--r--platform/iphone/export/export.cpp451
-rw-r--r--platform/iphone/game_center.mm14
-rw-r--r--platform/iphone/os_iphone.cpp69
-rw-r--r--platform/iphone/os_iphone.h7
-rw-r--r--platform/javascript/export/export.cpp1
-rw-r--r--platform/osx/export/export.cpp1
-rw-r--r--scene/gui/item_list.cpp6
-rw-r--r--version.py2
62 files changed, 1758 insertions, 393 deletions
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 35e4443f2a..6d4b46f4da 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -98,6 +98,7 @@ static Error _erase_recursive(DirAccess *da) {
err = _erase_recursive(da);
if (err) {
print_line("err recurso " + E->get());
+ da->change_dir("..");
return err;
}
err = da->change_dir("..");
@@ -340,6 +341,102 @@ Error DirAccess::copy(String p_from, String p_to, int chmod_flags) {
return err;
}
+// Changes dir for the current scope, returning back to the original dir
+// when scope exits
+class DirChanger {
+ DirAccess *da;
+ String original_dir;
+
+public:
+ DirChanger(DirAccess *p_da, String p_dir) {
+ da = p_da;
+ original_dir = p_da->get_current_dir();
+ p_da->change_dir(p_dir);
+ }
+
+ ~DirChanger() {
+ da->change_dir(original_dir);
+ }
+};
+
+Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) {
+ List<String> dirs;
+
+ String curdir = get_current_dir();
+ list_dir_begin();
+ String n = get_next();
+ while (n != String()) {
+
+ if (n != "." && n != "..") {
+
+ if (current_is_dir())
+ dirs.push_back(n);
+ else {
+ String rel_path = n;
+ if (!n.is_rel_path()) {
+ list_dir_end();
+ return ERR_BUG;
+ }
+ Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags);
+ if (err) {
+ list_dir_end();
+ return err;
+ }
+ }
+ }
+
+ n = get_next();
+ }
+
+ list_dir_end();
+
+ for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
+ String rel_path = E->get();
+ String target_dir = p_to + rel_path;
+ if (!p_target_da->dir_exists(target_dir)) {
+ Error err = p_target_da->make_dir(target_dir);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ Error err = change_dir(E->get());
+ ERR_FAIL_COND_V(err, err);
+ err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
+ if (err) {
+ change_dir("..");
+ ERR_PRINT("Failed to copy recursively");
+ return err;
+ }
+ err = change_dir("..");
+ if (err) {
+ ERR_PRINT("Failed to go back");
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
+ ERR_FAIL_COND_V(!dir_exists(p_from), ERR_FILE_NOT_FOUND);
+
+ DirAccess *target_da = DirAccess::create_for_path(p_to);
+ ERR_FAIL_COND_V(!target_da, ERR_CANT_CREATE);
+
+ if (!target_da->dir_exists(p_to)) {
+ Error err = target_da->make_dir_recursive(p_to);
+ if (err) {
+ memdelete(target_da);
+ }
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ DirChanger dir_changer(this, p_from);
+ Error err = _copy_dir(target_da, p_to + "/", p_chmod_flags);
+ memdelete(target_da);
+
+ return err;
+}
+
bool DirAccess::exists(String p_dir) {
DirAccess *da = DirAccess::create_for_path(p_dir);
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 7fa3ce5cf1..f3d1320041 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -52,6 +52,9 @@ public:
private:
AccessType _access_type;
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+
+ Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags);
+
protected:
String _get_root_path() const;
String _get_root_string() const;
@@ -89,6 +92,7 @@ public:
static bool exists(String p_dir);
virtual size_t get_space_left() = 0;
+ Error copy_dir(String p_from, String p_to, int chmod_flags = -1);
virtual Error copy(String p_from, String p_to, int chmod_flags = -1);
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 65d0b2e05d..dd71f8a9c6 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -548,6 +548,33 @@ bool OS::has_feature(const String &p_feature) {
if (sizeof(void *) == 4 && p_feature == "32") {
return true;
}
+#if defined(__x86_64) || defined(__x86_64__)
+ if (p_feature == "x86_64") {
+ return true;
+ }
+#elif (defined(__i386) || defined(__i386__))
+ if (p_feature == "x86") {
+ return true;
+ }
+#elif defined(__aarch64__)
+ if (p_feature == "arm64") {
+ return true;
+ }
+#elif defined(__arm__)
+#if defined(__ARM_ARCH_7A__)
+ if (p_feature == "armv7a" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+#if defined(__ARM_ARCH_7S__)
+ if (p_feature == "armv7s" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+ if (p_feature == "arm") {
+ return true;
+ }
+#endif
if (_check_internal_feature_support(p_feature))
return true;
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 5655a4d5e4..5e06339b9e 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -35,6 +35,8 @@
#include "os/input.h"
#include "os/os.h"
#include "project_settings.h"
+#include "scene/main/node.h"
+
void ScriptDebuggerRemote::_send_video_memory() {
List<ResourceUsage> usage;
@@ -201,20 +203,39 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
List<String> members;
List<Variant> member_vals;
-
+ if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) {
+ members.push_back("self");
+ member_vals.push_back(inst->get_owner());
+ }
p_script->debug_get_stack_level_members(lv, &members, &member_vals);
-
ERR_CONTINUE(members.size() != member_vals.size());
List<String> locals;
List<Variant> local_vals;
-
p_script->debug_get_stack_level_locals(lv, &locals, &local_vals);
-
ERR_CONTINUE(locals.size() != local_vals.size());
+ List<String> globals;
+ List<Variant> globals_vals;
+ p_script->debug_get_globals(&globals, &globals_vals);
+ ERR_CONTINUE(globals.size() != globals_vals.size());
+
packet_peer_stream->put_var("stack_frame_vars");
- packet_peer_stream->put_var(2 + locals.size() * 2 + members.size() * 2);
+ packet_peer_stream->put_var(3 + (locals.size() + members.size() + globals.size()) * 2);
+
+ { //locals
+ packet_peer_stream->put_var(locals.size());
+
+ List<String>::Element *E = locals.front();
+ List<Variant>::Element *F = local_vals.front();
+
+ while (E) {
+ _put_variable(E->get(), F->get());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
{ //members
packet_peer_stream->put_var(members.size());
@@ -231,11 +252,11 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
}
}
- { //locals
- packet_peer_stream->put_var(locals.size());
+ { //globals
+ packet_peer_stream->put_var(globals.size());
- List<String>::Element *E = locals.front();
- List<Variant>::Element *F = local_vals.front();
+ List<String>::Element *E = globals.front();
+ List<Variant>::Element *F = globals_vals.front();
while (E) {
_put_variable(E->get(), F->get());
@@ -532,56 +553,88 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
if (!obj)
return;
- List<PropertyInfo> pinfo;
- obj->get_property_list(&pinfo, true);
+ typedef Pair<PropertyInfo, Variant> PropertyDesc;
+ List<PropertyDesc> properties;
- int props_to_send = 0;
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ if (ScriptInstance *si = obj->get_script_instance()) {
+ if (!si->get_script().is_null()) {
- if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
- props_to_send++;
- }
- }
+ Set<StringName> members;
+ si->get_script()->get_members(&members);
+ for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
- packet_peer_stream->put_var("message:inspect_object");
- packet_peer_stream->put_var(props_to_send * 5 + 4);
- packet_peer_stream->put_var(p_id);
- packet_peer_stream->put_var(obj->get_class());
- if (obj->is_class("Resource") || obj->is_class("Node"))
- packet_peer_stream->put_var(obj->call("get_path"));
- else
- packet_peer_stream->put_var("");
+ Variant m;
+ if (si->get(E->get(), m)) {
+ PropertyInfo pi(m.get_type(), String("Members/") + E->get());
+ properties.push_back(PropertyDesc(pi, m));
+ }
+ }
- packet_peer_stream->put_var(props_to_send);
+ Map<StringName, Variant> constants;
+ si->get_script()->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key()));
+ properties.push_back(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ if (Node *node = Object::cast_to<Node>(obj)) {
+ PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
+ properties.push_front(PropertyDesc(pi, node->get_path()));
+ } else if (Resource *res = Object::cast_to<Resource>(obj)) {
+ if (Script *s = Object::cast_to<Script>(res)) {
+ Map<StringName, Variant> constants;
+ s->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key());
+ properties.push_front(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ List<PropertyInfo> pinfo;
+ obj->get_property_list(&pinfo, true);
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
-
if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
+ properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name)));
+ }
+ }
- if (E->get().usage & PROPERTY_USAGE_CATEGORY) {
- packet_peer_stream->put_var("*" + E->get().name);
- } else {
- packet_peer_stream->put_var(E->get().name);
- }
-
- Variant var = obj->get(E->get().name);
- packet_peer_stream->put_var(E->get().type);
- //only send information that can be sent..
-
- int len = 0; //test how big is this to encode
- encode_variant(var, NULL, len);
-
- if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
- packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_TOO_BIG);
- packet_peer_stream->put_var("");
- packet_peer_stream->put_var(Variant());
- } else {
- packet_peer_stream->put_var(E->get().hint);
- packet_peer_stream->put_var(E->get().hint_string);
- packet_peer_stream->put_var(var);
- }
+ Array send_props;
+ for (int i = 0; i < properties.size(); i++) {
+ const PropertyInfo &pi = properties[i].first;
+ const Variant &var = properties[i].second;
+ RES res = var;
+
+ Array prop;
+ prop.push_back(pi.name);
+ prop.push_back(pi.type);
+
+ //only send information that can be sent..
+ int len = 0; //test how big is this to encode
+ encode_variant(var, NULL, len);
+ if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
+ prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG);
+ prop.push_back("");
+ prop.push_back(pi.usage);
+ prop.push_back(Variant());
+ } else {
+ prop.push_back(pi.hint);
+ if (res.is_null())
+ prop.push_back(pi.hint_string);
+ else
+ prop.push_back(String("RES:") + res->get_path());
+ prop.push_back(pi.usage);
+ prop.push_back(var);
}
+ send_props.push_back(prop);
}
+
+ packet_peer_stream->put_var("message:inspect_object");
+ packet_peer_stream->put_var(3);
+ packet_peer_stream->put_var(p_id);
+ packet_peer_stream->put_var(obj->get_class());
+ packet_peer_stream->put_var(send_props);
}
void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) {
@@ -590,7 +643,11 @@ void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_p
if (!obj)
return;
- obj->set(p_property, p_value);
+ String prop_name = p_property;
+ if (p_property.begins_with("Members/"))
+ prop_name = p_property.substr(8, p_property.length());
+
+ obj->set(prop_name, p_value);
}
void ScriptDebuggerRemote::_poll_events() {
diff --git a/core/script_language.h b/core/script_language.h
index 5da72d0492..3d01381f3b 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -120,6 +120,9 @@ public:
virtual int get_member_line(const StringName &p_member) const { return -1; }
+ virtual void get_constants(Map<StringName, Variant> *p_constants) {}
+ virtual void get_members(Set<StringName> *p_constants) {}
+
Script() {}
};
@@ -130,6 +133,7 @@ public:
virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0;
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const = 0;
+ virtual Object *get_owner() { return NULL; }
virtual void get_property_state(List<Pair<StringName, Variant> > &state);
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
@@ -244,7 +248,8 @@ public:
virtual String debug_get_stack_level_source(int p_level) const = 0;
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level) { return NULL; }
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0;
struct StackInfo {
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 7c3a784c5b..8d40f56386 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -862,6 +862,17 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo
return ret;
}
+String String::join(Vector<String> parts) {
+ String ret;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (i > 0) {
+ ret += *this;
+ }
+ ret += parts[i];
+ }
+ return ret;
+}
+
CharType String::char_uppercase(CharType p_char) {
return _find_upper(p_char);
diff --git a/core/ustring.h b/core/ustring.h
index 353c8e6c1d..9c24133b55 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -169,6 +169,8 @@ public:
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
+ String join(Vector<String> parts);
+
static CharType char_uppercase(CharType p_char);
static CharType char_lowercase(CharType p_char);
String to_upper() const;
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index 49ec412ba0..15ada7fdfa 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -138,6 +138,17 @@
Decodes a byte array back to a value.
</description>
</method>
+ <method name="cartesian2polar">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="x" type="float">
+ </argument>
+ <argument index="1" name="y" type="float">
+ </argument>
+ <description>
+ Converts a 2D point expressed in the cartesian coordinate system (x and y axis) to the polar coordinate system (a distance from the origin and an angle).
+ </description>
+ </method>
<method name="ceil">
<return type="float">
</return>
@@ -604,6 +615,17 @@
[/codeblock]
</description>
</method>
+ <method name="polar2cartesian">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="r" type="float">
+ </argument>
+ <argument index="1" name="th" type="float">
+ </argument>
+ <description>
+ Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (x and y axis).
+ </description>
+ </method>
<method name="pow">
<return type="float">
</return>
diff --git a/editor/dictionary_property_edit.cpp b/editor/dictionary_property_edit.cpp
new file mode 100644
index 0000000000..5b5a7ec9b0
--- /dev/null
+++ b/editor/dictionary_property_edit.cpp
@@ -0,0 +1,189 @@
+/*************************************************************************/
+/* dictionary_property_edit.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "dictionary_property_edit.h"
+#include "editor_node.h"
+
+void DictionaryPropertyEdit::_notif_change() {
+ _change_notify();
+}
+
+void DictionaryPropertyEdit::_notif_changev(const String &p_v) {
+ _change_notify(p_v.utf8().get_data());
+}
+
+void DictionaryPropertyEdit::_set_key(const Variant &p_old_key, const Variant &p_new_key) {
+
+ // TODO: Set key of a dictionary is not allowd yet
+ return;
+}
+
+void DictionaryPropertyEdit::_set_value(const Variant &p_key, const Variant &p_value) {
+
+ Dictionary dict = get_dictionary();
+ dict[p_key] = p_value;
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return;
+
+ o->set(property, dict);
+}
+
+Variant DictionaryPropertyEdit::get_dictionary() const {
+
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return Dictionary();
+ Variant dict = o->get(property);
+ if (dict.get_type() != Variant::DICTIONARY)
+ return Dictionary();
+ return dict;
+}
+
+void DictionaryPropertyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
+
+ Dictionary dict = get_dictionary();
+
+ Array keys = dict.keys();
+ keys.sort();
+
+ for (int i = 0; i < keys.size(); i++) {
+ String index = itos(i);
+
+ const Variant &key = keys[i];
+ PropertyInfo pi(key.get_type(), index + ": key");
+ p_list->push_back(pi);
+
+ const Variant &value = dict[key];
+ pi = PropertyInfo(value.get_type(), index + ": value");
+ p_list->push_back(pi);
+ }
+}
+
+void DictionaryPropertyEdit::edit(Object *p_obj, const StringName &p_prop) {
+
+ property = p_prop;
+ obj = p_obj->get_instance_id();
+}
+
+Node *DictionaryPropertyEdit::get_node() {
+
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return NULL;
+
+ return cast_to<Node>(o);
+}
+
+void DictionaryPropertyEdit::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_set_key"), &DictionaryPropertyEdit::_set_key);
+ ClassDB::bind_method(D_METHOD("_set_value"), &DictionaryPropertyEdit::_set_value);
+ ClassDB::bind_method(D_METHOD("_notif_change"), &DictionaryPropertyEdit::_notif_change);
+ ClassDB::bind_method(D_METHOD("_notif_changev"), &DictionaryPropertyEdit::_notif_changev);
+}
+
+bool DictionaryPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
+
+ Dictionary dict = get_dictionary();
+ Array keys = dict.keys();
+ keys.sort();
+
+ String pn = p_name;
+ int slash = pn.find(": ");
+ if (slash != -1 && pn.length() > slash) {
+ String type = pn.substr(slash + 2, pn.length());
+ int index = pn.substr(0, slash).to_int();
+ if (type == "key" && index < keys.size()) {
+
+ const Variant &key = keys[index];
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Change Dictionary Key"));
+ ur->add_do_method(this, "_set_key", key, p_value);
+ ur->add_undo_method(this, "_set_key", p_value, key);
+ ur->add_do_method(this, "_notif_changev", p_name);
+ ur->add_undo_method(this, "_notif_changev", p_name);
+ ur->commit_action();
+
+ return true;
+ } else if (type == "value" && index < keys.size()) {
+ const Variant &key = keys[index];
+ if (dict.has(key)) {
+
+ Variant value = dict[key];
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Change Dictionary Value"));
+ ur->add_do_method(this, "_set_value", key, p_value);
+ ur->add_undo_method(this, "_set_value", key, value);
+ ur->add_do_method(this, "_notif_changev", p_name);
+ ur->add_undo_method(this, "_notif_changev", p_name);
+ ur->commit_action();
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool DictionaryPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const {
+
+ Dictionary dict = get_dictionary();
+ Array keys = dict.keys();
+ keys.sort();
+
+ String pn = p_name;
+ int slash = pn.find(": ");
+
+ if (slash != -1 && pn.length() > slash) {
+
+ String type = pn.substr(slash + 2, pn.length());
+ int index = pn.substr(0, slash).to_int();
+
+ if (type == "key" && index < keys.size()) {
+ r_ret = keys[index];
+ return true;
+ } else if (type == "value" && index < keys.size()) {
+ const Variant &key = keys[index];
+ if (dict.has(key)) {
+ r_ret = dict[key];
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+DictionaryPropertyEdit::DictionaryPropertyEdit() {
+ obj = 0;
+}
diff --git a/misc/dist/ios_xcode/godot_ios/main.m b/editor/dictionary_property_edit.h
index bb63364d8f..7a86727fb2 100644
--- a/misc/dist/ios_xcode/godot_ios/main.m
+++ b/editor/dictionary_property_edit.h
@@ -1,9 +1,9 @@
/*************************************************************************/
-/* main.m */
+/* dictionary_property_edit.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
-/* https://godotengine.org */
+/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
@@ -27,13 +27,36 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef DICTIONARY_PROPERTY_EDIT_H
+#define DICTIONARY_PROPERTY_EDIT_H
-#import <UIKit/UIKit.h>
+#include "scene/main/node.h"
-#import "AppDelegate.h"
+class DictionaryPropertyEdit : public Reference {
+ GDCLASS(DictionaryPropertyEdit, Reference);
-int main(int argc, char *argv[]) {
- @autoreleasepool {
- return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
- }
-}
+ ObjectID obj;
+ StringName property;
+
+ void _notif_change();
+ void _notif_changev(const String &p_v);
+ void _set_key(const Variant &p_old_key, const Variant &p_new_key);
+ void _set_value(const Variant &p_key, const Variant &p_value);
+
+ Variant get_dictionary() const;
+
+protected:
+ static void _bind_methods();
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+ void edit(Object *p_obj, const StringName &p_prop);
+
+ Node *get_node();
+
+ DictionaryPropertyEdit();
+};
+
+#endif // DICTIONARY_PROPERTY_EDIT_H
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 519bc33d42..8c8d9c4c79 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -470,9 +470,52 @@ void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p
extra_files.push_back(ef);
}
-void EditorExportPlugin::add_shared_object(const String &p_path) {
+void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &tags) {
- shared_objects.push_back(p_path);
+ shared_objects.push_back(SharedObject(p_path, tags));
+}
+
+void EditorExportPlugin::add_ios_framework(const String &p_path) {
+ ios_frameworks.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_frameworks() const {
+ return ios_frameworks;
+}
+
+void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) {
+ ios_plist_content += p_plist_content + "\n";
+}
+
+String EditorExportPlugin::get_ios_plist_content() const {
+ return ios_plist_content;
+}
+
+void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) {
+ if (ios_linker_flags.length() > 0) {
+ ios_linker_flags += ' ';
+ }
+ ios_linker_flags += p_flags;
+}
+
+String EditorExportPlugin::get_ios_linker_flags() const {
+ return ios_linker_flags;
+}
+
+void EditorExportPlugin::add_ios_bundle_file(const String &p_path) {
+ ios_bundle_files.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_bundle_files() const {
+ return ios_bundle_files;
+}
+
+void EditorExportPlugin::add_ios_cpp_code(const String &p_code) {
+ ios_cpp_code += p_code;
+}
+
+String EditorExportPlugin::get_ios_cpp_code() const {
+ return ios_cpp_code;
}
void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const PoolVector<String> &p_features) {
@@ -482,17 +525,17 @@ void EditorExportPlugin::_export_file_script(const String &p_path, const String
}
}
-void EditorExportPlugin::_export_begin_script(const PoolVector<String> &p_features) {
+void EditorExportPlugin::_export_begin_script(const PoolVector<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
if (get_script_instance()) {
- get_script_instance()->call("_export_begin", p_features);
+ get_script_instance()->call("_export_begin", p_features, p_debug, p_path, p_flags);
}
}
void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
}
-void EditorExportPlugin::_export_begin(const Set<String> &p_features) {
+void EditorExportPlugin::_export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
}
void EditorExportPlugin::skip() {
@@ -502,33 +545,58 @@ void EditorExportPlugin::skip() {
void EditorExportPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_shared_object", "path"), &EditorExportPlugin::add_shared_object);
+ ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags"), &EditorExportPlugin::add_shared_object);
ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
+ ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
+ ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content);
+ ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
+ ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
+ ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
BIND_VMETHOD(MethodInfo("_export_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "type"), PropertyInfo(Variant::POOL_STRING_ARRAY, "features")));
- BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features")));
+ BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features"), PropertyInfo(Variant::BOOL, "is_debug"), PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags")));
}
EditorExportPlugin::EditorExportPlugin() {
skipped = false;
}
-Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) {
-
+EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset) {
Ref<EditorExportPlatform> platform = p_preset->get_platform();
List<String> feature_list;
+ platform->get_platform_features(&feature_list);
platform->get_preset_features(p_preset, &feature_list);
- //figure out features
- Set<String> features;
- PoolVector<String> features_pv;
+
+ FeatureContainers result;
for (List<String>::Element *E = feature_list.front(); E; E = E->next()) {
- features.insert(E->get());
- features_pv.push_back(E->get());
+ result.features.insert(E->get());
+ result.features_pv.push_back(E->get());
}
+ return result;
+}
+EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ FeatureContainers features = p_platform.get_feature_containers(p_preset);
Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ //initial export plugin callback
+ for (int i = 0; i < export_plugins.size(); i++) {
+ if (export_plugins[i]->get_script_instance()) { //script based
+ export_plugins[i]->_export_begin_script(features.features_pv, p_debug, p_path, p_flags);
+ } else {
+ export_plugins[i]->_export_begin(features.features, p_debug, p_path, p_flags);
+ }
+ }
+}
+
+EditorExportPlatform::ExportNotifier::~ExportNotifier() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ for (int i = 0; i < export_plugins.size(); i++) {
+ export_plugins[i]->_export_end();
+ }
+}
+Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) {
//figure out paths of files that will be exported
Set<String> paths;
Vector<String> path_remaps;
@@ -551,13 +619,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
_edit_filter_list(paths, p_preset->get_include_filter(), false);
_edit_filter_list(paths, p_preset->get_exclude_filter(), true);
- //initial export plugin callback
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
- if (export_plugins[i]->get_script_instance()) { //script based
- export_plugins[i]->_export_begin_script(features_pv);
- } else {
- export_plugins[i]->_export_begin(features);
- }
if (p_so_func) {
for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) {
p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
@@ -570,6 +633,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
export_plugins[i]->_clear();
}
+ FeatureContainers feature_containers = get_feature_containers(p_preset);
+ Set<String> &features = feature_containers.features;
+ PoolVector<String> &features_pv = feature_containers.features_pv;
+
//store everything in the export medium
int idx = 0;
int total = paths.size();
@@ -686,7 +753,16 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
return OK;
}
-Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObject &p_so) {
+ PackData *pack_data = (PackData *)p_userdata;
+ if (pack_data->so_files) {
+ pack_data->so_files->push_back(p_so);
+ }
+
+ return OK;
+}
+
+Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files) {
EditorProgress ep("savepack", TTR("Packing"), 102);
@@ -697,8 +773,9 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
PackData pd;
pd.ep = &ep;
pd.f = ftmp;
+ pd.so_files = p_so_files;
- Error err = export_project_files(p_preset, _save_pack_file, &pd);
+ Error err = export_project_files(p_preset, _save_pack_file, &pd, _add_shared_object);
memdelete(ftmp); //close tmp file
@@ -1203,6 +1280,7 @@ String EditorExportPlatformPC::get_binary_extension() const {
}
Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 50379b9683..346c3b58e1 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -118,13 +118,24 @@ public:
EditorExportPreset();
};
+struct SharedObject {
+ String path;
+ Vector<String> tags;
+
+ SharedObject(const String &p_path, const Vector<String> &p_tags)
+ : path(p_path), tags(p_tags) {
+ }
+
+ SharedObject() {}
+};
+
class EditorExportPlatform : public Reference {
GDCLASS(EditorExportPlatform, Reference)
public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
- typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const String &p_path);
+ typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
private:
struct SavedData {
@@ -144,6 +155,7 @@ private:
FileAccess *f;
Vector<SavedData> file_ofs;
EditorProgress *ep;
+ Vector<SharedObject> *so_files;
};
struct ZipData {
@@ -152,6 +164,11 @@ private:
EditorProgress *ep;
};
+ struct FeatureContainers {
+ Set<String> features;
+ PoolVector<String> features_pv;
+ };
+
void _export_find_resources(EditorFileSystemDirectory *p_dir, Set<String> &p_paths);
void _export_find_dependencies(const String &p_path, Set<String> &p_paths);
@@ -162,7 +179,16 @@ private:
void _edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
void _edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude);
+ static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);
+
protected:
+ struct ExportNotifier {
+ ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
+ ~ExportNotifier();
+ };
+
+ FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset);
+
bool exists_export_template(String template_file_name, String *err) const;
String find_export_template(String template_file_name, String *err = NULL) const;
void gen_export_flags(Vector<String> &r_flags, int p_flags);
@@ -192,7 +218,7 @@ public:
Error export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = NULL);
- Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path);
+ Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files = NULL);
Error save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path);
virtual bool poll_devices() { return false; }
@@ -225,7 +251,7 @@ class EditorExportPlugin : public Reference {
friend class EditorExportPlatform;
- Vector<String> shared_objects;
+ Vector<SharedObject> shared_objects;
struct ExtraFile {
String path;
Vector<uint8_t> data;
@@ -234,26 +260,53 @@ class EditorExportPlugin : public Reference {
Vector<ExtraFile> extra_files;
bool skipped;
+ Vector<String> ios_frameworks;
+ String ios_plist_content;
+ String ios_linker_flags;
+ Vector<String> ios_bundle_files;
+ String ios_cpp_code;
+
_FORCE_INLINE_ void _clear() {
shared_objects.clear();
extra_files.clear();
skipped = false;
}
+ _FORCE_INLINE_ void _export_end() {
+ ios_frameworks.clear();
+ ios_bundle_files.clear();
+ ios_plist_content = "";
+ ios_linker_flags = "";
+ ios_cpp_code = "";
+ }
+
void _export_file_script(const String &p_path, const String &p_type, const PoolVector<String> &p_features);
- void _export_begin_script(const PoolVector<String> &p_features);
+ void _export_begin_script(const PoolVector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
protected:
void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
- void add_shared_object(const String &p_path);
+ void add_shared_object(const String &p_path, const Vector<String> &tags);
+
+ void add_ios_framework(const String &p_path);
+ void add_ios_plist_content(const String &p_plist_content);
+ void add_ios_linker_flags(const String &p_flags);
+ void add_ios_bundle_file(const String &p_path);
+ void add_ios_cpp_code(const String &p_code);
+
void skip();
virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
- virtual void _export_begin(const Set<String> &p_features);
+ virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags);
static void _bind_methods();
public:
+ Vector<String> get_ios_frameworks() const;
+ String get_ios_plist_content() const;
+ String get_ios_linker_flags() const;
+ Vector<String> get_ios_bundle_files() const;
+ String get_ios_cpp_code() const;
+
EditorExportPlugin();
};
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index c0e2e46f14..109f132d76 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -303,8 +303,7 @@ void EditorNode::_notification(int p_what) {
if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
- property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
- Ref<Theme> theme = create_custom_theme(theme_base->get_theme());
+ Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
theme_base->set_theme(theme);
gui_base->set_theme(theme);
@@ -1368,6 +1367,8 @@ void EditorNode::_prepare_history() {
}
} else if (Object::cast_to<Node>(obj)) {
text = Object::cast_to<Node>(obj)->get_name();
+ } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) {
+ text = obj->call("get_title");
} else {
text = obj->get_class();
}
@@ -1463,6 +1464,7 @@ void EditorNode::_edit_current() {
object_menu->set_disabled(true);
+ bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true));
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
resource_save_button->set_disabled(!is_resource);
@@ -1516,6 +1518,11 @@ void EditorNode::_edit_current() {
} else {
+ if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) {
+ editable_warning = TTR("This is a remote object so changes to it will not be kept.\nPlease read the documentation relevant to debugging to better understand this workflow.");
+ capitalize = false;
+ }
+
property_editor->edit(current_obj);
node_dock->set_node(NULL);
}
@@ -1525,6 +1532,10 @@ void EditorNode::_edit_current() {
property_editable_warning_dialog->set_text(editable_warning);
}
+ if (property_editor->is_capitalize_paths_enabled() != capitalize) {
+ property_editor->set_enable_capitalize_paths(capitalize);
+ }
+
/* Take care of PLUGIN EDITOR */
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index 0587939a1a..f0d3c29c11 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -149,14 +149,14 @@ void EditorPath::_notification(int p_what) {
if (name == "")
name = r->get_class();
- } else if (Object::cast_to<Node>(obj)) {
-
+ } else if (obj->is_class("ScriptEditorDebuggerInspectedObject"))
+ name = obj->call("get_title");
+ else if (Object::cast_to<Node>(obj))
name = Object::cast_to<Node>(obj)->get_name();
- } else if (Object::cast_to<Resource>(obj) && Object::cast_to<Resource>(obj)->get_name() != "") {
+ else if (Object::cast_to<Resource>(obj) && Object::cast_to<Resource>(obj)->get_name() != "")
name = Object::cast_to<Resource>(obj)->get_name();
- } else {
+ else
name = obj->get_class();
- }
set_tooltip(obj->get_class());
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index cf28582e5d..582bb977b8 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -424,6 +424,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.9));
_initial_set("editors/2d/keep_margins_when_changing_anchors", false);
_initial_set("editors/2d/warped_mouse_panning", true);
+ _initial_set("editors/2d/simple_spacebar_panning", false);
_initial_set("editors/2d/scroll_to_pan", false);
_initial_set("editors/2d/pan_speed", 20);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index eea8177687..9c432323f4 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1447,6 +1447,15 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
file_options->popup();
}
+void FileSystemDock::_rmb_pressed(const Vector2 &p_pos) {
+ folder_options->clear();
+ folder_options->set_size(Size2(1, 1));
+
+ folder_options->add_item(TTR("New Folder.."), FOLDER_NEW_FOLDER);
+ folder_options->set_position(files->get_global_position() + p_pos);
+ folder_options->popup();
+}
+
void FileSystemDock::select_file(const String &p_file) {
navigate_to_path(p_file);
@@ -1547,6 +1556,7 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_file_selected"), &FileSystemDock::_file_selected);
ClassDB::bind_method(D_METHOD("_file_multi_selected"), &FileSystemDock::_file_multi_selected);
ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
+ ClassDB::bind_method(D_METHOD("_rmb_pressed"), &FileSystemDock::_rmb_pressed);
ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("open"));
@@ -1665,6 +1675,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
files->connect("item_rmb_selected", this, "_files_list_rmb_select");
files->connect("item_selected", this, "_file_selected");
files->connect("multi_selected", this, "_file_multi_selected");
+ files->connect("rmb_clicked", this, "_rmb_pressed");
files->set_allow_rmb_select(true);
file_list_vb->add_child(files);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index d100de8b72..f1fd342052 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -192,6 +192,7 @@ private:
void _dir_rmb_pressed(const Vector2 &p_pos);
void _files_list_rmb_select(int p_item, const Vector2 &p_pos);
+ void _rmb_pressed(const Vector2 &p_pos);
struct FileInfo {
String name;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index b6ba09fb58..6cb4171f5a 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1858,7 +1858,17 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
}
if (drag == DRAG_NONE) {
- if (((m->get_button_mask() & BUTTON_MASK_LEFT) && tool == TOOL_PAN) || (m->get_button_mask() & BUTTON_MASK_MIDDLE) || ((m->get_button_mask() & BUTTON_MASK_LEFT) && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+ bool space_pressed = Input::get_singleton()->is_key_pressed(KEY_SPACE);
+ bool simple_panning = EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning");
+ int button = m->get_button_mask();
+
+ // Check if any of the panning triggers are activated
+ bool panning_tool = (button & BUTTON_MASK_LEFT) && tool == TOOL_PAN;
+ bool panning_middle_button = button & BUTTON_MASK_MIDDLE;
+ bool panning_spacebar = (button & BUTTON_MASK_LEFT) && space_pressed;
+ bool panning_spacebar_simple = space_pressed && simple_panning;
+
+ if (panning_tool || panning_middle_button || panning_spacebar || panning_spacebar_simple) {
// Pan the viewport
Point2i relative;
if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index dda2851166..6500b10a3a 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -717,6 +717,7 @@ void ProjectExportDialog::_export_project() {
export_project->set_access(FileDialog::ACCESS_FILESYSTEM);
export_project->clear_filters();
+ export_project->set_current_file(default_filename);
String extension = platform->get_binary_extension();
if (extension != String()) {
export_project->add_filter("*." + extension + " ; " + platform->get_name() + " Export");
@@ -726,6 +727,9 @@ void ProjectExportDialog::_export_project() {
}
void ProjectExportDialog::_export_project_to_path(const String &p_path) {
+ // Save this name for use in future exports (but drop the file extension)
+ default_filename = p_path.get_basename().get_file();
+ EditorSettings::get_singleton()->set_project_metadata("export_options", "default_filename", default_filename);
Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
ERR_FAIL_COND(current.is_null());
@@ -970,6 +974,8 @@ ProjectExportDialog::ProjectExportDialog() {
set_hide_on_ok(false);
editor_icons = "EditorIcons";
+
+ default_filename = EditorSettings::get_singleton()->get_project_metadata("export_options", "default_filename", String());
}
ProjectExportDialog::~ProjectExportDialog() {
diff --git a/editor/project_export.h b/editor/project_export.h
index 288b0c290f..b258112fa8 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -99,6 +99,8 @@ private:
Label *export_error;
HBoxContainer *export_templates_error;
+ String default_filename;
+
void _patch_selected(const String &p_path);
void _patch_deleted();
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 9733f49f42..bc7d8f4b14 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -40,6 +40,7 @@
#include "core/project_settings.h"
#include "editor/array_property_edit.h"
#include "editor/create_dialog.h"
+#include "editor/dictionary_property_edit.h"
#include "editor/editor_export.h"
#include "editor/editor_file_system.h"
#include "editor/editor_help.h"
@@ -1157,7 +1158,8 @@ void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
node = Object::cast_to<Node>(owner);
else if (owner->is_class("ArrayPropertyEdit"))
node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node();
-
+ else if (owner->is_class("DictionaryPropertyEdit"))
+ node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node();
if (!node) {
v = p_path;
emit_signal("variant_changed");
@@ -3215,9 +3217,14 @@ void PropertyEditor::update_tree() {
} break;
case Variant::DICTIONARY: {
+ Variant v = obj->get(p.name);
+
item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
- item->set_editable(1, false);
- item->set_text(1, obj->get(p.name).operator String());
+ item->set_text(1, String("Dictionary{") + itos(v.call("size")) + "}");
+ item->add_button(1, get_icon("EditResource", "EditorIcons"));
+
+ if (show_type_icons)
+ item->set_icon(0, get_icon("DictionaryData", "EditorIcons"));
} break;
@@ -3416,7 +3423,9 @@ void PropertyEditor::update_tree() {
type = p.hint_string;
RES res = obj->get(p.name).operator RefPtr();
-
+ if (type.begins_with("RES:") && type != "RES:") { // Remote resources
+ res = ResourceLoader::load(type.substr(4, type.length()));
+ }
Ref<EncodedObjectAsID> encoded = obj->get(p.name); //for debugger and remote tools
if (encoded.is_valid()) {
@@ -3427,6 +3436,7 @@ void PropertyEditor::update_tree() {
item->set_editable(1, true);
} else if (obj->get(p.name).get_type() == Variant::NIL || res.is_null()) {
+
item->set_text(1, "<null>");
item->set_icon(1, Ref<Texture>());
item->set_custom_as_button(1, false);
@@ -3585,7 +3595,7 @@ void PropertyEditor::_edit_set(const String &p_name, const Variant &p_value, boo
}
}
- if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(obj)) { //kind of hacky
+ if (!undo_redo || Object::cast_to<ArrayPropertyEdit>(obj) || Object::cast_to<DictionaryPropertyEdit>(obj)) { //kind of hacky
obj->set(p_name, p_value);
if (p_refresh_all)
@@ -3983,8 +3993,20 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
Ref<ArrayPropertyEdit> ape = memnew(ArrayPropertyEdit);
ape->edit(obj, n, ht, Variant::Type(t));
-
EditorNode::get_singleton()->push_item(ape.ptr());
+
+ } else if (t == Variant::DICTIONARY) {
+
+ Variant v = obj->get(n);
+
+ if (v.get_type() != t) {
+ Variant::CallError ce;
+ v = Variant::construct(Variant::Type(t), NULL, 0, ce);
+ }
+
+ Ref<DictionaryPropertyEdit> dpe = memnew(DictionaryPropertyEdit);
+ dpe->edit(obj, n);
+ EditorNode::get_singleton()->push_item(dpe.ptr());
}
}
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index e7e57a7079..1d2647badc 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1853,6 +1853,8 @@ void SceneTreeDock::_local_tree_selected() {
remote_tree->hide();
edit_remote->set_pressed(false);
edit_local->set_pressed(true);
+
+ _node_selected();
}
void SceneTreeDock::_bind_methods() {
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index bc2423fffd..2a3e47b2a6 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -116,7 +116,7 @@ class ScriptEditorDebuggerInspectedObject : public Object {
protected:
bool _set(const StringName &p_name, const Variant &p_value) {
- if (!prop_values.has(p_name))
+ if (!prop_values.has(p_name) || String(p_name).begins_with("Constants/"))
return false;
emit_signal("value_edited", p_name, p_value);
@@ -132,6 +132,7 @@ protected:
r_ret = prop_values[p_name];
return true;
}
+
void _get_property_list(List<PropertyInfo> *p_list) const {
p_list->clear(); //sorry, no want category
@@ -142,23 +143,52 @@ protected:
static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_title"), &ScriptEditorDebuggerInspectedObject::get_title);
+ ClassDB::bind_method(D_METHOD("get_variant"), &ScriptEditorDebuggerInspectedObject::get_variant);
+ ClassDB::bind_method(D_METHOD("clear"), &ScriptEditorDebuggerInspectedObject::clear);
+ ClassDB::bind_method(D_METHOD("get_remote_object_id"), &ScriptEditorDebuggerInspectedObject::get_remote_object_id);
+
ADD_SIGNAL(MethodInfo("value_edited"));
}
public:
- ObjectID last_edited_id;
+ String type_name;
+ ObjectID remote_object_id;
List<PropertyInfo> prop_list;
Map<StringName, Variant> prop_values;
+ ObjectID get_remote_object_id() {
+ return remote_object_id;
+ }
+
+ String get_title() {
+ if (remote_object_id)
+ return TTR("Remote ") + String(type_name) + ": " + itos(remote_object_id);
+ else
+ return "<null>";
+ }
+ Variant get_variant(const StringName &p_name) {
+
+ Variant var;
+ _get(p_name, var);
+ return var;
+ }
+
+ void clear() {
+
+ prop_list.clear();
+ prop_values.clear();
+ }
void update() {
_change_notify();
}
-
void update_single(const char *p_prop) {
_change_notify(p_prop);
}
- ScriptEditorDebuggerInspectedObject() { last_edited_id = 0; }
+ ScriptEditorDebuggerInspectedObject() {
+ remote_object_id = 0;
+ }
};
void ScriptEditorDebugger::debug_next() {
@@ -297,7 +327,6 @@ Size2 ScriptEditorDebugger::get_minimum_size() const {
void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_data) {
if (p_msg == "debug_enter") {
-
Array msg;
msg.push_back("get_stack_dump");
ppeer->put_var(msg);
@@ -315,12 +344,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
if (error != "") {
tabs->set_current_tab(0);
}
-
profiler->set_enabled(false);
-
EditorNode::get_singleton()->get_pause_button()->set_pressed(true);
-
EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ _clear_remote_objects();
} else if (p_msg == "debug_exit") {
@@ -337,9 +364,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
//tabs->set_current_tab(0);
profiler->set_enabled(true);
profiler->disable_seeking();
-
+ inspector->edit(NULL);
EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
-
} else if (p_msg == "message:click_ctrl") {
clicked_ctrl->set_text(p_data[0]);
@@ -399,55 +425,57 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
le_set->set_disabled(false);
} else if (p_msg == "message:inspect_object") {
+ ScriptEditorDebuggerInspectedObject *debugObj = NULL;
+
ObjectID id = p_data[0];
String type = p_data[1];
- Variant path = p_data[2]; //what to do yet, i don't know
- int prop_count = p_data[3];
-
- int idx = 4;
+ Array properties = p_data[2];
- if (inspected_object->last_edited_id != id) {
- inspected_object->prop_list.clear();
- inspected_object->prop_values.clear();
+ bool is_new_object = false;
+ if (remote_objects.has(id)) {
+ debugObj = remote_objects[id];
+ } else {
+ debugObj = memnew(ScriptEditorDebuggerInspectedObject);
+ debugObj->remote_object_id = id;
+ debugObj->type_name = type;
+ remote_objects[id] = debugObj;
+ is_new_object = true;
+ debugObj->connect("value_edited", this, "_scene_tree_property_value_edited");
}
- for (int i = 0; i < prop_count; i++) {
+ for (int i = 0; i < properties.size(); i++) {
+
+ Array prop = properties[i];
+ if (prop.size() != 6)
+ continue;
PropertyInfo pinfo;
- pinfo.name = p_data[idx++];
- pinfo.type = Variant::Type(int(p_data[idx++]));
- pinfo.hint = PropertyHint(int(p_data[idx++]));
- pinfo.hint_string = p_data[idx++];
- if (pinfo.name.begins_with("*")) {
- pinfo.name = pinfo.name.substr(1, pinfo.name.length());
- pinfo.usage = PROPERTY_USAGE_CATEGORY;
- } else {
- pinfo.usage = PROPERTY_USAGE_EDITOR;
+ pinfo.name = prop[0];
+ pinfo.type = Variant::Type(int(prop[1]));
+ pinfo.hint = PropertyHint(int(prop[2]));
+ pinfo.hint_string = prop[3];
+ pinfo.usage = PropertyUsageFlags(int(prop[4]));
+ Variant var = prop[5];
+
+ String hint_string = pinfo.hint_string;
+ if (hint_string.begins_with("RES:") && hint_string != "RES:") {
+ String path = hint_string.substr(4, hint_string.length());
+ var = ResourceLoader::load(path);
}
- if (inspected_object->last_edited_id != id) {
+ if (is_new_object) {
//don't update.. it's the same, instead refresh
- inspected_object->prop_list.push_back(pinfo);
+ debugObj->prop_list.push_back(pinfo);
}
- inspected_object->prop_values[pinfo.name] = p_data[idx++];
-
- if (inspected_object->last_edited_id == id) {
- //same, just update value, don't rebuild
- inspected_object->update_single(pinfo.name.ascii().get_data());
- }
+ debugObj->prop_values[pinfo.name] = var;
}
- if (inspected_object->last_edited_id != id) {
- //only if different
- inspected_object->update();
+ if (editor->get_editor_history()->get_current() != debugObj->get_instance_id()) {
+ editor->push_item(debugObj, "");
+ } else {
+ debugObj->update();
}
-
- inspected_object->last_edited_id = id;
-
- tabs->set_current_tab(inspect_info->get_index());
- inspect_properties->edit(inspected_object);
-
} else if (p_msg == "message:video_mem") {
vmem_tree->clear();
@@ -502,7 +530,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
int ofs = 0;
int mcount = p_data[ofs];
-
ofs++;
for (int i = 0; i < mcount; i++) {
@@ -521,12 +548,34 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
v = s.get_slice(":", 1).to_int();
}
- variables->add_property("members/" + n, v, h, hs);
+ variables->add_property("Locals/" + n, v, h, hs);
}
- ofs += mcount * 2;
+ ofs += mcount * 2;
mcount = p_data[ofs];
+ ofs++;
+ for (int i = 0; i < mcount; i++) {
+
+ String n = p_data[ofs + i * 2 + 0];
+ Variant v = p_data[ofs + i * 2 + 1];
+ PropertyHint h = PROPERTY_HINT_NONE;
+ String hs = String();
+
+ if (n.begins_with("*")) {
+
+ n = n.substr(1, n.length());
+ h = PROPERTY_HINT_OBJECT_ID;
+ String s = v;
+ s = s.replace("[", "");
+ hs = s.get_slice(":", 0);
+ v = s.get_slice(":", 1).to_int();
+ }
+
+ variables->add_property("Members/" + n, v, h, hs);
+ }
+ ofs += mcount * 2;
+ mcount = p_data[ofs];
ofs++;
for (int i = 0; i < mcount; i++) {
@@ -545,7 +594,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
v = s.get_slice(":", 1).to_int();
}
- variables->add_property("locals/" + n, v, h, hs);
+ variables->add_property("Globals/" + n, v, h, hs);
}
variables->update();
@@ -1101,6 +1150,8 @@ void ScriptEditorDebugger::start() {
EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), true);
return;
}
+
+ EditorNode::get_singleton()->get_scene_tree_dock()->show_remote_tree();
set_process(true);
}
@@ -1133,11 +1184,11 @@ void ScriptEditorDebugger::stop() {
le_set->set_disabled(true);
profiler->set_enabled(true);
- inspect_properties->edit(NULL);
inspect_scene_tree->clear();
EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
EditorNode::get_singleton()->get_pause_button()->set_disabled(true);
+ EditorNode::get_singleton()->get_scene_tree_dock()->hide_remote_tree();
if (hide_on_stop) {
if (is_visible_in_tree())
@@ -1604,6 +1655,24 @@ void ScriptEditorDebugger::_paused() {
}
}
+void ScriptEditorDebugger::_set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj) {
+
+ if (remote_objects.has(p_id))
+ memdelete(remote_objects[p_id]);
+ remote_objects[p_id] = p_obj;
+}
+
+void ScriptEditorDebugger::_clear_remote_objects() {
+
+ for (Map<ObjectID, ScriptEditorDebuggerInspectedObject *>::Element *E = remote_objects.front(); E; E = E->next()) {
+ if (editor->get_editor_history()->get_current() == E->value()->get_instance_id()) {
+ editor->push_item(NULL);
+ }
+ memdelete(E->value());
+ }
+ remote_objects.clear();
+}
+
void ScriptEditorDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"), &ScriptEditorDebugger::_stack_dump_frame_selected);
@@ -1649,6 +1718,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
ppeer = Ref<PacketPeerStream>(memnew(PacketPeerStream));
ppeer->set_input_buffer_max_size(1024 * 1024 * 8); //8mb should be enough
editor = p_editor;
+ editor->get_property_editor()->connect("object_id_selected", this, "_scene_tree_property_select_object");
tabs = memnew(TabContainer);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
@@ -1761,41 +1831,18 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
tabs->add_child(error_split);
}
- { // inquire
-
- inspect_info = memnew(HSplitContainer);
- inspect_info->set_name(TTR("Remote Inspector"));
- tabs->add_child(inspect_info);
-
- VBoxContainer *info_left = memnew(VBoxContainer);
- info_left->set_h_size_flags(SIZE_EXPAND_FILL);
- inspect_info->add_child(info_left);
+ { // remote scene tree
inspect_scene_tree = memnew(Tree);
- info_left->add_margin_child(TTR("Live Scene Tree:"), inspect_scene_tree, true);
+ EditorNode::get_singleton()->get_scene_tree_dock()->add_remote_tree_editor(inspect_scene_tree);
+ inspect_scene_tree->set_v_size_flags(SIZE_EXPAND_FILL);
inspect_scene_tree->connect("cell_selected", this, "_scene_tree_selected");
inspect_scene_tree->connect("item_collapsed", this, "_scene_tree_folded");
- //
-
- VBoxContainer *info_right = memnew(VBoxContainer);
- info_right->set_h_size_flags(SIZE_EXPAND_FILL);
- inspect_info->add_child(info_right);
-
- inspect_properties = memnew(PropertyEditor);
- inspect_properties->hide_top_label();
- inspect_properties->set_show_categories(true);
- inspect_properties->connect("object_id_selected", this, "_scene_tree_property_select_object");
-
- info_right->add_margin_child(TTR("Remote Object Properties: "), inspect_properties, true);
-
inspect_scene_tree_timeout = EDITOR_DEF("debugger/scene_tree_refresh_interval", 1.0);
inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2);
inspected_object_id = 0;
updating_scene_tree = false;
-
- inspected_object = memnew(ScriptEditorDebuggerInspectedObject);
- inspected_object->connect("value_edited", this, "_scene_tree_property_value_edited");
}
{ //profiler
@@ -1952,5 +1999,5 @@ ScriptEditorDebugger::~ScriptEditorDebugger() {
ppeer->set_stream_peer(Ref<StreamPeer>());
server->stop();
- memdelete(inspected_object);
+ _clear_remote_objects();
}
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index d18a625eef..dc851dd575 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -72,19 +72,18 @@ class ScriptEditorDebugger : public Control {
Button *le_set;
Button *le_clear;
- Tree *inspect_scene_tree;
- HSplitContainer *inspect_info;
- PropertyEditor *inspect_properties;
+ bool updating_scene_tree;
float inspect_scene_tree_timeout;
float inspect_edited_object_timeout;
ObjectID inspected_object_id;
- ScriptEditorDebuggerInspectedObject *inspected_object;
- bool updating_scene_tree;
+ ScriptEditorDebuggerVariables *variables;
+ Map<ObjectID, ScriptEditorDebuggerInspectedObject *> remote_objects;
Set<ObjectID> unfold_cache;
HSplitContainer *error_split;
ItemList *error_list;
ItemList *error_stack;
+ Tree *inspect_scene_tree;
int error_count;
int last_error_count;
@@ -96,7 +95,6 @@ class ScriptEditorDebugger : public Control {
TabContainer *tabs;
Label *reason;
- ScriptEditorDebuggerVariables *variables;
Button *step;
Button *next;
@@ -174,6 +172,9 @@ class ScriptEditorDebugger : public Control {
void _paused();
+ void _set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj);
+ void _clear_remote_objects();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.fat b/misc/dist/ios_xcode/godot.iphone.debug.fat
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.debug.fat
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm b/misc/dist/ios_xcode/godot.iphone.release.arm
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.release.arm
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm64 b/misc/dist/ios_xcode/godot.iphone.release.arm64
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.release.arm64
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot.iphone.release.fat b/misc/dist/ios_xcode/godot.iphone.release.fat
deleted file mode 100755
index e69de29bb2..0000000000
--- a/misc/dist/ios_xcode/godot.iphone.release.fat
+++ /dev/null
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index 3f2db94193..ab15e35f63 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -8,8 +8,20 @@
/* Begin PBXBuildFile section */
1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; };
+ 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */; };
+ 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926951FBBF7C400F53A6F /* Security.framework */; };
+ 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */; };
+ 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */; };
+ 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926921FBBF7A000F53A6F /* GameController.framework */; };
+ 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926911FBBF79500F53A6F /* CoreMotion.framework */; };
+ 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */; };
+ 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */; };
+ 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */; };
+ DEADBEEF2F582BE20003B888 /* $binary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.a */; };
+ 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; };
1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; };
1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1861F584E5600A41E41 /* StoreKit.framework */; };
+ 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1881F584E7600A41E41 /* StoreKit.framework */; };
D07CD43F1C5D573600B7FB28 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */; };
D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */; };
D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */; };
@@ -26,14 +38,25 @@
D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; };
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; };
D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; };
- D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* $binary.iphone */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = dylibs; sourceTree = "<group>"; };
+ 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = "<group>"; };
+ 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
+ 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+ 1FE926911FBBF79500F53A6F /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
+ 1FE926921FBBF7A000F53A6F /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
+ 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
+ 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 1FE926951FBBF7C400F53A6F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+ 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ DEADBEEF1F582BE20003B888 /* $binary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot; path = "$binary.a"; sourceTree = "<group>"; };
1FF4C1841F584E3F00A41E41 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
1FF4C1861F584E5600A41E41 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
+ 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = $binary.entitlements; sourceTree = "<group>"; };
+ 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; };
D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = "<group>"; };
D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait-736h@3x.png"; sourceTree = "<group>"; };
@@ -51,24 +74,35 @@
D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; };
D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
- D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "$binary-Prefix.pch"; sourceTree = "<group>"; };
- D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = $binary.pck; sourceTree = "<group>"; };
- D0BCFE7918AEC06A004A7AAE /* $binary.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = $binary.iphone; sourceTree = "<group>"; };
/* End PBXFileReference section */
+ $additional_pbx_files
+
/* Begin PBXFrameworksBuildPhase section */
D0BCFE3118AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */,
+ 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */,
+ 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */,
+ 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */,
+ 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */,
+ 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */,
+ 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */,
+ 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */,
+ 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */,
+ 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */,
D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */,
1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */,
- D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */,
+ 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */,
D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */,
1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */,
D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */,
D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */,
+ DEADBEEF2F582BE20003B888 /* $binary.a */,
+ $additional_pbx_frameworks_build
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -79,11 +113,11 @@
isa = PBXGroup;
children = (
1F1575711F582BE20003B888 /* dylibs */,
- D0BCFE7918AEC06A004A7AAE /* $binary.iphone */,
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */,
D0BCFE4118AEBDA2004A7AAE /* $binary */,
D0BCFE3618AEBDA2004A7AAE /* Frameworks */,
D0BCFE3518AEBDA2004A7AAE /* Products */,
+ $additional_pbx_resources_refs
);
sourceTree = "<group>";
};
@@ -98,14 +132,25 @@
D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */,
+ 1FE926951FBBF7C400F53A6F /* Security.framework */,
+ 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */,
+ 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */,
+ 1FE926921FBBF7A000F53A6F /* GameController.framework */,
+ 1FE926911FBBF79500F53A6F /* CoreMotion.framework */,
+ 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */,
+ 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */,
+ 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */,
1FF4C1861F584E5600A41E41 /* StoreKit.framework */,
1FF4C1841F584E3F00A41E41 /* GameKit.framework */,
+ 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */,
D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */,
D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */,
D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */,
D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */,
D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */,
- D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */,
+ DEADBEEF1F582BE20003B888 /* $binary.a */,
+ $additional_pbx_frameworks_refs
);
name = Frameworks;
sourceTree = "<group>";
@@ -124,6 +169,7 @@
D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */,
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */,
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */,
+ 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */,
);
path = $binary;
sourceTree = "<group>";
@@ -133,7 +179,6 @@
children = (
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */,
D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */,
- D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
@@ -218,7 +263,7 @@
D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */,
D07CD4481C5D573600B7FB28 /* Default-Portrait-1366h@2x.png in Resources */,
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */,
- D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */,
+ $additional_pbx_resources_build
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -229,6 +274,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -250,7 +296,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+ ARCHS = "$godot_archs";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -265,6 +311,8 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug";
COPY_PHASE_STRIP = NO;
+ ENABLE_BITCODE = NO;
+ "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -280,7 +328,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -290,7 +338,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+ ARCHS = "$godot_archs";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -306,6 +354,8 @@
CODE_SIGN_IDENTITY = "$code_sign_identity_release";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release";
COPY_PHASE_STRIP = YES;
+ ENABLE_BITCODE = NO;
+ "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -315,6 +365,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ OTHER_LDFLAGS = "$linker_flags";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -324,26 +375,23 @@
D0BCFE7218AEBDA3004A7AAE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD)";
+ ARCHS = "$godot_archs";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements;
CODE_SIGN_IDENTITY = "$code_sign_identity_debug";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
DEVELOPMENT_TEAM = $team_id;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch";
INFOPLIST_FILE = "$binary/$binary-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/dylibs",
);
PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug";
TARGETED_DEVICE_FAMILY = "1,2";
- VALID_ARCHS = "armv7 armv7s";
+ VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
name = Debug;
@@ -351,26 +399,23 @@
D0BCFE7318AEBDA3004A7AAE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD)";
+ ARCHS = "$godot_archs";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements;
CODE_SIGN_IDENTITY = "$code_sign_identity_release";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
DEVELOPMENT_TEAM = $team_id;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch";
INFOPLIST_FILE = "$binary/$binary-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)/dylibs",
);
PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "$provisioning_profile_uuid_release";
TARGETED_DEVICE_FAMILY = "1,2";
- VALID_ARCHS = "armv7 armv7s";
+ VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64";
WRAPPER_EXTENSION = app;
};
name = Release;
diff --git a/misc/dist/ios_xcode/godot_ios/dummy.cpp b/misc/dist/ios_xcode/godot_ios/dummy.cpp
new file mode 100644
index 0000000000..78ec87fc10
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/dummy.cpp
@@ -0,0 +1 @@
+$cpp_code \ No newline at end of file
diff --git a/misc/dist/ios_xcode/godot_ios/dylibs/empty b/misc/dist/ios_xcode/godot_ios/dylibs/empty
new file mode 100644
index 0000000000..4b5614362b
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/dylibs/empty
@@ -0,0 +1 @@
+Dummy file to make dylibs folder exported \ No newline at end of file
diff --git a/misc/dist/ios_xcode/export_options.plist b/misc/dist/ios_xcode/godot_ios/export_options.plist
index 86d89a6e42..3878a4dbe6 100644
--- a/misc/dist/ios_xcode/export_options.plist
+++ b/misc/dist/ios_xcode/godot_ios/export_options.plist
@@ -4,7 +4,17 @@
<dict>
<key>method</key>
<string>$export_method</string>
+
<key>teamID</key>
<string>$team_id</string>
+
+ <key>provisioningProfiles</key>
+ <dict>
+ <key>$identifier</key>
+ <string>$provisioning_profile_uuid</string>
+ </dict>
+
+ <key>compileBitcode</key>
+ <false/>
</dict>
</plist> \ No newline at end of file
diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
index 1531a41bd0..70932c1943 100644
--- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
+++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
@@ -7,7 +7,7 @@
<key>CFBundleDisplayName</key>
<string>$name</string>
<key>CFBundleExecutable</key>
- <string>$binary.iphone</string>
+ <string>$binary</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
@@ -47,5 +47,6 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
+ $additional_plist_content
</dict>
</plist>
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.arm b/misc/dist/ios_xcode/libgodot.iphone.debug.fat.a
index e69de29bb2..e69de29bb2 100755..100644
--- a/misc/dist/ios_xcode/godot.iphone.debug.arm
+++ b/misc/dist/ios_xcode/libgodot.iphone.debug.fat.a
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.arm64 b/misc/dist/ios_xcode/libgodot.iphone.release.fat.a
index e69de29bb2..e69de29bb2 100755..100644
--- a/misc/dist/ios_xcode/godot.iphone.debug.arm64
+++ b/misc/dist/ios_xcode/libgodot.iphone.release.fat.a
diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp
index dc7d23bbd7..941df41694 100644
--- a/modules/etc/image_etc.cpp
+++ b/modules/etc/image_etc.cpp
@@ -129,7 +129,7 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
PoolVector<uint8_t>::Read r = img->get_data().read();
int target_size = Image::get_image_data_size(imgw, imgh, etc_format, p_img->has_mipmaps() ? -1 : 0);
- int mmc = p_img->has_mipmaps() ? Image::get_image_required_mipmaps(imgw, imgh, etc_format) : 0;
+ int mmc = 1 + (p_img->has_mipmaps() ? Image::get_image_required_mipmaps(imgw, imgh, etc_format) : 0);
PoolVector<uint8_t> dst_data;
dst_data.resize(target_size);
@@ -155,7 +155,7 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
print_line("begin encoding, format: " + Image::get_format_name(etc_format));
uint64_t t = OS::get_singleton()->get_ticks_msec();
- for (int i = 0; i < mmc + 1; i++) {
+ for (int i = 0; i < mmc; i++) {
// convert source image to internal etc2comp format (which is equivalent to Image::FORMAT_RGBAF)
// NOTE: We can alternatively add a case to Image::convert to handle Image::FORMAT_RGBAF conversion.
int mipmap_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0;
@@ -163,9 +163,9 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
const uint8_t *src = &r[mipmap_ofs];
Etc::ColorFloatRGBA *src_rgba_f = new Etc::ColorFloatRGBA[mipmap_w * mipmap_h];
- for (int i = 0; i < mipmap_w * mipmap_h; i++) {
- int si = i * 4; // RGBA8
- src_rgba_f[i] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]);
+ for (int j = 0; j < mipmap_w * mipmap_h; j++) {
+ int si = j * 4; // RGBA8
+ src_rgba_f[j] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]);
}
unsigned char *etc_data = NULL;
@@ -173,15 +173,17 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
unsigned int extended_width = 0, extended_height = 0;
Etc::Encode((float *)src_rgba_f, mipmap_w, mipmap_h, etc2comp_etc_format, error_metric, effort, num_cpus, num_cpus, &etc_data, &etc_data_len, &extended_width, &extended_height, &encoding_time);
+ CRASH_COND(wofs + etc_data_len > target_size);
memcpy(&w[wofs], etc_data, etc_data_len);
wofs += etc_data_len;
delete[] etc_data;
delete[] src_rgba_f;
}
+
print_line("time encoding: " + rtos(OS::get_singleton()->get_ticks_msec() - t));
- p_img->create(imgw, imgh, mmc > 1 ? true : false, etc_format, dst_data);
+ p_img->create(imgw, imgh, p_img->has_mipmaps(), etc_format, dst_data);
}
static void _compress_etc1(Image *p_img, float p_lossy_quality) {
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index f98a16a5d7..de118043ca 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -123,7 +123,7 @@ bool GDNative::initialize() {
return false;
}
#ifdef IPHONE_ENABLED
- String path = lib_path.replace("res://", "dylibs/");
+ String path = "";
#else
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
#endif
@@ -148,7 +148,7 @@ bool GDNative::initialize() {
// we cheat here a little bit. you saw nothing
initialized = true;
- err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init);
+ err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init, false);
initialized = false;
@@ -280,7 +280,7 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced
return *(Variant *)&result;
}
-Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle) {
+Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional) {
if (!initialized) {
ERR_PRINT("No valid library handle, can't get symbol from GDNative object");
@@ -291,7 +291,7 @@ Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle) {
native_handle,
p_procedure_name,
r_handle,
- true);
+ p_optional);
return result;
}
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index 052ce1fef1..bb260bdd1b 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -141,7 +141,7 @@ public:
Variant call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments = Array());
- Error get_symbol(StringName p_procedure_name, void *&r_handle);
+ Error get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional = true);
};
class GDNativeLibraryResourceLoader : public ResourceFormatLoader {
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 8af643df50..34099bf528 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -123,6 +123,11 @@ protected:
virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
};
+struct LibrarySymbol {
+ char *name;
+ bool is_required;
+};
+
void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
if (p_type != "GDNativeLibrary") {
return;
@@ -136,7 +141,6 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
Ref<ConfigFile> config = lib->get_config_file();
- String entry_lib_path;
{
List<String> entry_keys;
@@ -161,14 +165,12 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
continue;
}
- entry_lib_path = config->get_value("entry", key);
- break;
+ String entry_lib_path = config->get_value("entry", key);
+ add_shared_object(entry_lib_path, tags);
}
}
- Vector<String> dependency_paths;
{
-
List<String> dependency_keys;
config->get_section_keys("dependencies", &dependency_keys);
@@ -191,47 +193,54 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
continue;
}
- dependency_paths = config->get_value("dependencies", key);
- break;
+ Vector<String> dependency_paths = config->get_value("dependencies", key);
+ for (int i = 0; i < dependency_paths.size(); i++) {
+ add_shared_object(dependency_paths[i], tags);
+ }
}
}
- bool is_statically_linked = false;
- {
-
- List<String> static_linking_keys;
- config->get_section_keys("static_linking", &static_linking_keys);
-
- for (List<String>::Element *E = static_linking_keys.front(); E; E = E->next()) {
- String key = E->get();
-
- Vector<String> tags = key.split(".");
-
- bool skip = false;
-
- for (int i = 0; i < tags.size(); i++) {
- bool has_feature = p_features.has(tags[i]);
-
- if (!has_feature) {
- skip = true;
- break;
+ if (p_features.has("iOS")) {
+ // Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS.
+ LibrarySymbol expected_symbols[] = {
+ { "gdnative_init", true },
+ { "gdnative_terminate", false },
+ { "nativescript_init", false },
+ { "nativescript_frame", false },
+ { "nativescript_thread_enter", false },
+ { "nativescript_thread_exit", false },
+ { "gdnative_singleton", false }
+ };
+ String declare_pattern = "extern \"C\" void $name(void)$weak;\n";
+ String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"
+ "extern void add_ios_init_callback(void (*cb)());\n";
+ String linker_flags = "";
+ for (int i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) {
+ String full_name = lib->get_symbol_prefix() + expected_symbols[i].name;
+ String code = declare_pattern.replace("$name", full_name);
+ code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))");
+ additional_code += code;
+
+ if (!expected_symbols[i].is_required) {
+ if (linker_flags.length() > 0) {
+ linker_flags += " ";
}
+ linker_flags += "-Wl,-U,_" + full_name;
}
-
- if (skip) {
- continue;
- }
-
- is_statically_linked = config->get_value("static_linking", key);
- break;
}
- }
- if (!is_statically_linked)
- add_shared_object(entry_lib_path);
+ additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix());
+ String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n";
+ for (int i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) {
+ String full_name = lib->get_symbol_prefix() + expected_symbols[i].name;
+ additional_code += register_pattern.replace("$name", full_name);
+ }
+ additional_code += "}\n";
+ additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix());
+ additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix());
- for (int i = 0; i < dependency_paths.size(); i++) {
- add_shared_object(dependency_paths[i]);
+ add_ios_cpp_code(additional_code);
+ add_ios_linker_flags(linker_flags);
}
}
@@ -271,9 +280,7 @@ void register_gdnative_types() {
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- EditorNode::add_init_callback(editor_init_callback);
- }
+ EditorNode::add_init_callback(editor_init_callback);
#endif
ClassDB::register_class<GDNativeLibrary>();
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 55ea8a5f24..41a810ff00 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -100,7 +100,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
#endif
instance->owner->set_script_instance(instance);
-/* STEP 2, INITIALIZE AND CONSRTUCT */
+ /* STEP 2, INITIALIZE AND CONSRTUCT */
#ifndef NO_THREADS
GDScriptLanguage::singleton->lock->lock();
@@ -615,6 +615,23 @@ ScriptLanguage *GDScript::get_language() const {
return GDScriptLanguage::get_singleton();
}
+void GDScript::get_constants(Map<StringName, Variant> *p_constants) {
+
+ if (p_constants) {
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ (*p_constants)[E->key()] = E->value();
+ }
+ }
+}
+
+void GDScript::get_members(Set<StringName> *p_members) {
+ if (p_members) {
+ for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
+ p_members->insert(E->get());
+ }
+ }
+}
+
Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
GDScript *top = this;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 3f6f431938..6e5d59ad0e 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -198,6 +198,9 @@ public:
return -1;
}
+ virtual void get_constants(Map<StringName, Variant> *p_constants);
+ virtual void get_members(Set<StringName> *p_members);
+
GDScript();
~GDScript();
};
@@ -219,7 +222,7 @@ class GDScriptInstance : public ScriptInstance {
void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount);
public:
- _FORCE_INLINE_ Object *get_owner() { return owner; }
+ virtual Object *get_owner() { return owner; }
virtual bool set(const StringName &p_name, const Variant &p_value);
virtual bool get(const StringName &p_name, Variant &r_ret) const;
@@ -407,7 +410,8 @@ public:
virtual String debug_get_stack_level_source(int p_level) const;
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level);
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1);
virtual void reload_all_scripts();
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 3121a61436..4cd6472b7f 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1686,21 +1686,44 @@ Error GDScriptCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, cons
base_class = p->subclasses[base];
break;
}
+
+ if (p->constants.has(base)) {
+
+ base_class = p->constants[base];
+ if (base_class.is_null()) {
+ _set_error("Constant is not a class: " + base, p_class);
+ return ERR_SCRIPT_FAILED;
+ }
+ break;
+ }
+
p = p->_owner;
}
if (base_class.is_valid()) {
+ String ident = base;
+
for (int i = 1; i < p_class->extends_class.size(); i++) {
String subclass = p_class->extends_class[i];
+ ident += ("." + subclass);
+
if (base_class->subclasses.has(subclass)) {
base_class = base_class->subclasses[subclass];
+ } else if (base_class->constants.has(subclass)) {
+
+ Ref<GDScript> new_base_class = base_class->constants[subclass];
+ if (new_base_class.is_null()) {
+ _set_error("Constant is not a class: " + ident, p_class);
+ return ERR_SCRIPT_FAILED;
+ }
+ base_class = new_base_class;
} else {
- _set_error("Could not find subclass: " + subclass, p_class);
+ _set_error("Could not find subclass: " + ident, p_class);
return ERR_FILE_NOT_FOUND;
}
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index a74b8a8483..5a76acea6e 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -33,7 +33,7 @@
#include "gdscript_compiler.h"
#include "global_constants.h"
#include "os/file_access.h"
-#include "project_settings.h"
+#include "core/engine.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_file_system.h"
@@ -280,10 +280,62 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *
p_values->push_back(instance->debug_get_member_by_index(E->get().index));
}
}
-void GDScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
- //no globals are really reachable in gdscript
+ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) {
+
+ ERR_FAIL_COND_V(_debug_parse_err_line >= 0, NULL);
+ ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, NULL);
+
+ int l = _debug_call_stack_pos - p_level - 1;
+ ScriptInstance *instance = _call_stack[l].instance;
+
+ return instance;
}
+
+void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
+
+ const Map<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map();
+ const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array();
+
+ List<Pair<String, Variant> > cinfo;
+ get_public_constants(&cinfo);
+
+ for (const Map<StringName, int>::Element *E = name_idx.front(); E; E = E->next()) {
+
+ if (ClassDB::class_exists(E->key()) || Engine::get_singleton()->has_singleton(E->key()))
+ continue;
+
+ bool is_script_constant = false;
+ for (List<Pair<String, Variant> >::Element *CE = cinfo.front(); CE; CE = CE->next()) {
+ if (CE->get().first == E->key()) {
+ is_script_constant = true;
+ break;
+ }
+ }
+ if (is_script_constant)
+ continue;
+
+ const Variant &var = globals[E->value()];
+ if (Object *obj = var) {
+ if (Object::cast_to<GDScriptNativeClass>(obj))
+ continue;
+ }
+
+ bool skip = false;
+ for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
+ if (E->key() == GlobalConstants::get_global_constant_name(i)) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ p_globals->push_back(E->key());
+ p_values->push_back(var);
+ }
+}
+
String GDScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
if (_debug_parse_err_line >= 0)
@@ -1743,7 +1795,7 @@ static void _find_type_arguments(GDScriptCompletionContext &context, const GDScr
}
} else {
-//regular method
+ //regular method
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
if (p_argidx < m->get_argument_count()) {
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index c6066ceefb..ca0a9582a7 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -84,6 +84,8 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"rad2deg",
"linear2db",
"db2linear",
+ "polar2cartesian",
+ "cartesian2polar",
"wrapi",
"wrapf",
"max",
@@ -408,6 +410,22 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(0);
r_ret = Math::db2linear((double)*p_args[0]);
} break;
+ case MATH_POLAR2CARTESIAN: {
+ VALIDATE_ARG_COUNT(2);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double r = *p_args[0];
+ double th = *p_args[1];
+ r_ret = Vector2(r * Math::cos(th), r * Math::sin(th));
+ } break;
+ case MATH_CARTESIAN2POLAR: {
+ VALIDATE_ARG_COUNT(2);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double x = *p_args[0];
+ double y = *p_args[1];
+ r_ret = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
+ } break;
case MATH_WRAP: {
VALIDATE_ARG_COUNT(3);
r_ret = Math::wrapi((int64_t)*p_args[0], (int64_t)*p_args[1], (int64_t)*p_args[2]);
@@ -1296,6 +1314,8 @@ bool GDScriptFunctions::is_deterministic(Function p_func) {
case MATH_RAD2DEG:
case MATH_LINEAR2DB:
case MATH_DB2LINEAR:
+ case MATH_POLAR2CARTESIAN:
+ case MATH_CARTESIAN2POLAR:
case MATH_WRAP:
case MATH_WRAPF:
case LOGIC_MAX:
@@ -1526,6 +1546,16 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::REAL;
return mi;
} break;
+ case MATH_POLAR2CARTESIAN: {
+ MethodInfo mi("polar2cartesian", PropertyInfo(Variant::REAL, "r"), PropertyInfo(Variant::REAL, "th"));
+ mi.return_val.type = Variant::VECTOR2;
+ return mi;
+ } break;
+ case MATH_CARTESIAN2POLAR: {
+ MethodInfo mi("cartesian2polar", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ mi.return_val.type = Variant::VECTOR2;
+ return mi;
+ } break;
case MATH_WRAP: {
MethodInfo mi("wrapi", PropertyInfo(Variant::INT, "value"), PropertyInfo(Variant::INT, "min"), PropertyInfo(Variant::INT, "max"));
mi.return_val.type = Variant::INT;
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index ecbede83a8..d1c5815cec 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -75,6 +75,8 @@ public:
MATH_RAD2DEG,
MATH_LINEAR2DB,
MATH_DB2LINEAR,
+ MATH_POLAR2CARTESIAN,
+ MATH_CARTESIAN2POLAR,
MATH_WRAP,
MATH_WRAPF,
LOGIC_MAX,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 1e677f11c4..bee9ef1998 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2971,18 +2971,37 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) {
}
while (true) {
- if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER) {
- _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class).");
- return;
- }
+ switch (tokenizer->get_token()) {
+
+ case GDScriptTokenizer::TK_IDENTIFIER: {
+
+ StringName identifier = tokenizer->get_token_identifier();
+ p_class->extends_class.push_back(identifier);
+ }
+ break;
+
+ case GDScriptTokenizer::TK_PERIOD:
+ break;
+
+ default: {
- StringName identifier = tokenizer->get_token_identifier();
- p_class->extends_class.push_back(identifier);
+ _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class).");
+ return;
+ }
+ }
tokenizer->advance(1);
- if (tokenizer->get_token() != GDScriptTokenizer::TK_PERIOD)
- return;
+
+ switch (tokenizer->get_token()) {
+
+ case GDScriptTokenizer::TK_IDENTIFIER:
+ case GDScriptTokenizer::TK_PERIOD:
+ continue;
+
+ default:
+ return;
+ }
}
}
diff --git a/modules/mono/glue/cs_files/Mathf.cs b/modules/mono/glue/cs_files/Mathf.cs
index cb0eb1acdd..37e6e5bbe3 100644
--- a/modules/mono/glue/cs_files/Mathf.cs
+++ b/modules/mono/glue/cs_files/Mathf.cs
@@ -35,6 +35,11 @@ namespace Godot
return (float)Math.Atan2(x, y);
}
+ public static Vector2 cartesian2polar(float x, float y)
+ {
+ return new Vector2(sqrt(x * x + y * y), atan2(y, x));
+ }
+
public static float ceil(float s)
{
return (float)Math.Ceiling(s);
@@ -176,6 +181,11 @@ namespace Godot
return val;
}
+ public static Vector2 polar2cartesian(float r, float th)
+ {
+ return new Vector2(r * cos(th), r * sin(th));
+ }
+
public static float pow(float x, float y)
{
return (float)Math.Pow(x, y);
diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index 27231574d7..c45c8d2b64 100644
--- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -151,68 +151,74 @@
<constant name="MATH_DB2LINEAR" value="39">
Convert the input from decibel volume to linear volume.
</constant>
- <constant name="MATH_WRAP" value="40">
+ <constant name="MATH_POLAR2CARTESIAN" value="40">
+ Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (x and y axis).
</constant>
- <constant name="MATH_WRAPF" value="41">
+ <constant name="MATH_CARTESIAN2POLAR" value="41">
+ Converts a 2D point expressed in the cartesian coordinate system (x and y axis) to the polar coordinate system (a distance from the origin and an angle).
</constant>
- <constant name="LOGIC_MAX" value="42">
+ <constant name="MATH_WRAP" value="42">
+ </constant>
+ <constant name="MATH_WRAPF" value="43">
+ </constant>
+ <constant name="LOGIC_MAX" value="44">
Return the greater of the two numbers, also known as their maximum.
</constant>
- <constant name="LOGIC_MIN" value="43">
+ <constant name="LOGIC_MIN" value="45">
Return the lesser of the two numbers, also known as their minimum.
</constant>
- <constant name="LOGIC_CLAMP" value="44">
+ <constant name="LOGIC_CLAMP" value="46">
Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to `min(max(input, range_low), range_high)`
</constant>
- <constant name="LOGIC_NEAREST_PO2" value="45">
+ <constant name="LOGIC_NEAREST_PO2" value="46">
Return the nearest power of 2 to the input.
</constant>
- <constant name="OBJ_WEAKREF" value="46">
+ <constant name="OBJ_WEAKREF" value="47">
Create a [WeakRef] from the input.
</constant>
- <constant name="FUNC_FUNCREF" value="47">
+ <constant name="FUNC_FUNCREF" value="48">
Create a [FuncRef] from the input.
</constant>
- <constant name="TYPE_CONVERT" value="48">
+ <constant name="TYPE_CONVERT" value="49">
Convert between types.
</constant>
- <constant name="TYPE_OF" value="49">
+ <constant name="TYPE_OF" value="50">
Return the type of the input as an integer. Check [enum Variant.Type] for the integers that might be returned.
</constant>
- <constant name="TYPE_EXISTS" value="50">
+ <constant name="TYPE_EXISTS" value="51">
Checks if a type is registered in the [ClassDB].
</constant>
- <constant name="TEXT_CHAR" value="51">
+ <constant name="TEXT_CHAR" value="52">
Return a character with the given ascii value.
</constant>
- <constant name="TEXT_STR" value="52">
+ <constant name="TEXT_STR" value="53">
Convert the input to a string.
</constant>
- <constant name="TEXT_PRINT" value="53">
+ <constant name="TEXT_PRINT" value="54">
Print the given string to the output window.
</constant>
- <constant name="TEXT_PRINTERR" value="54">
+ <constant name="TEXT_PRINTERR" value="55">
Print the given string to the standard error output.
</constant>
- <constant name="TEXT_PRINTRAW" value="55">
+ <constant name="TEXT_PRINTRAW" value="56">
Print the given string to the standard output, without adding a newline.
</constant>
- <constant name="VAR_TO_STR" value="56">
+ <constant name="VAR_TO_STR" value="57">
Serialize a [Variant] to a string.
</constant>
- <constant name="STR_TO_VAR" value="57">
+ <constant name="STR_TO_VAR" value="58">
Deserialize a [Variant] from a string serialized using [VAR_TO_STR].
</constant>
- <constant name="VAR_TO_BYTES" value="58">
+ <constant name="VAR_TO_BYTES" value="59">
Serialize a [Variant] to a [PoolByteArray].
</constant>
- <constant name="BYTES_TO_VAR" value="59">
+ <constant name="BYTES_TO_VAR" value="60">
Deserialize a [Variant] from a [PoolByteArray] serialized using [VAR_TO_BYTES].
</constant>
- <constant name="COLORN" value="60">
+ <constant name="COLORN" value="61">
Return the [Color] with the given name and alpha ranging from 0 to 1. Note: names are defined in color_names.inc.
</constant>
- <constant name="FUNC_MAX" value="61">
+ <constant name="FUNC_MAX" value="62">
The maximum value the [member function] property can have.
</constant>
</constants>
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 8f7fe58bee..32f7519125 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -78,6 +78,8 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"rad2deg",
"linear2db",
"db2linear",
+ "polar2cartesian",
+ "cartesian2polar",
"wrapi",
"wrapf",
"max",
@@ -191,6 +193,8 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case MATH_EASE:
case MATH_STEPIFY:
case MATH_RANDOM:
+ case MATH_POLAR2CARTESIAN:
+ case MATH_CARTESIAN2POLAR:
case LOGIC_MAX:
case LOGIC_MIN:
case FUNC_FUNCREF:
@@ -368,6 +372,18 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
case MATH_DB2LINEAR: {
return PropertyInfo(Variant::REAL, "db");
} break;
+ case MATH_POLAR2CARTESIAN: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "r");
+ else
+ return PropertyInfo(Variant::REAL, "th");
+ } break;
+ case MATH_CARTESIAN2POLAR: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "x");
+ else
+ return PropertyInfo(Variant::REAL, "y");
+ } break;
case MATH_WRAP: {
if (p_idx == 0)
return PropertyInfo(Variant::INT, "value");
@@ -573,6 +589,10 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_DB2LINEAR: {
t = Variant::REAL;
} break;
+ case MATH_POLAR2CARTESIAN:
+ case MATH_CARTESIAN2POLAR: {
+ t = Variant::VECTOR2;
+ } break;
case MATH_WRAP: {
t = Variant::INT;
} break;
@@ -922,6 +942,20 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
VALIDATE_ARG_NUM(0);
*r_return = Math::db2linear((double)*p_inputs[0]);
} break;
+ case VisualScriptBuiltinFunc::MATH_POLAR2CARTESIAN: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double r = *p_inputs[0];
+ double th = *p_inputs[1];
+ *r_return = Vector2(r * Math::cos(th), r * Math::sin(th));
+ } break;
+ case VisualScriptBuiltinFunc::MATH_CARTESIAN2POLAR: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ double x = *p_inputs[0];
+ double y = *p_inputs[1];
+ *r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
+ } break;
case VisualScriptBuiltinFunc::MATH_WRAP: {
VALIDATE_ARG_NUM(0);
VALIDATE_ARG_NUM(1);
@@ -1294,6 +1328,8 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_RAD2DEG);
BIND_ENUM_CONSTANT(MATH_LINEAR2DB);
BIND_ENUM_CONSTANT(MATH_DB2LINEAR);
+ BIND_ENUM_CONSTANT(MATH_POLAR2CARTESIAN);
+ BIND_ENUM_CONSTANT(MATH_CARTESIAN2POLAR);
BIND_ENUM_CONSTANT(MATH_WRAP);
BIND_ENUM_CONSTANT(MATH_WRAPF);
BIND_ENUM_CONSTANT(LOGIC_MAX);
@@ -1381,6 +1417,8 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/rad2deg", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAD2DEG>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/linear2db", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LINEAR2DB>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/db2linear", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/polar2cartesian", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_POLAR2CARTESIAN>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/cartesian2polar", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_CARTESIAN2POLAR>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAPF>);
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index 34a2825938..54dc997b38 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -77,6 +77,8 @@ public:
MATH_RAD2DEG,
MATH_LINEAR2DB,
MATH_DB2LINEAR,
+ MATH_POLAR2CARTESIAN,
+ MATH_CARTESIAN2POLAR,
MATH_WRAP,
MATH_WRAPF,
LOGIC_MAX,
diff --git a/modules/webm/config.py b/modules/webm/config.py
index 0374bb36f7..dcae4447d5 100644
--- a/modules/webm/config.py
+++ b/modules/webm/config.py
@@ -1,5 +1,5 @@
def can_build(platform):
- return True
+ return platform != 'iphone'
def configure(env):
pass
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index d5ccf76631..b2c8799540 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -705,7 +705,24 @@ String OS_Android::get_joy_guid(int p_device) const {
}
bool OS_Android::_check_internal_feature_support(const String &p_feature) {
- return p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2"; //TODO support etc2 only if GLES3 driver is selected
+ if (p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2") {
+ //TODO support etc2 only if GLES3 driver is selected
+ return true;
+ }
+#if defined(__aarch64__)
+ if (p_feature == "arm64-v8a") {
+ return true;
+ }
+#elif defined(__ARM_ARCH_7A__)
+ if (p_feature == "armeabi-v7a" || p_feature == "armeabi") {
+ return true;
+ }
+#elif defined(__arm__)
+ if (p_feature == "armeabi") {
+ return true;
+ }
+#endif
+ return false;
}
OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion) {
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 61798c5f87..550dfdd7d6 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -3,7 +3,7 @@
Import('env')
iphone_lib = [
-
+ 'godot_iphone.cpp',
'os_iphone.cpp',
'sem_iphone.cpp',
'gl_view.mm',
@@ -17,10 +17,10 @@ iphone_lib = [
]
env_ios = env.Clone()
+ios_lib = env_ios.Library('iphone', iphone_lib)
-obj = env_ios.Object('godot_iphone.cpp')
+def combine_libs(target=None, source=None, env=None):
+ lib_path = target[0].srcnode().abspath
+ env.Execute('$IPHONEPATH/usr/bin/libtool -static -o "' + lib_path + '" ' + ' '.join([('"' + lib.srcnode().abspath + '"') for lib in source]))
-prog = None
-prog = env_ios.Program('#bin/godot', [obj] + iphone_lib)
-action = "$IPHONEPATH/usr/bin/dsymutil " + File(prog)[0].path + " -o " + File(prog)[0].path + ".dSYM"
-env.AddPostAction(prog, action)
+combine_command = env_ios.Command('#bin/libgodot' + env_ios['LIBSUFFIX'], [ios_lib] + env_ios['LIBS'], combine_libs)
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 4ea358f871..25674c2b47 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -61,10 +61,13 @@ def configure(env):
env.Append(LINKFLAGS=['-flto'])
## Architecture
+ if env["ios_sim"] and not ("arch" in env):
+ env["arch"] = "x86"
- if env["ios_sim"] or env["arch"] == "x86": # i386, simulator
- env["arch"] = "x86"
+ if env["arch"] == "x86": # i386, simulator
env["bits"] = "32"
+ elif env["arch"] == "x86_64":
+ env["bits"] = "64"
elif (env["arch"] == "arm" or env["arch"] == "arm32" or env["arch"] == "armv7" or env["bits"] == "32"): # arm
env["arch"] = "arm"
env["bits"] = "32"
@@ -95,10 +98,11 @@ def configure(env):
## Compile flags
- if (env["arch"] == "x86"):
+ if (env["arch"] == "x86" or env["arch"] == "x86_64"):
env['IPHONEPLATFORM'] = 'iPhoneSimulator'
- env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
- env.Append(CCFLAGS='-arch i386 -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -D__IPHONE_OS_VERSION_MIN_REQUIRED=40100 -isysroot $IPHONESDK -mios-simulator-version-min=4.3 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"'.split())
+ env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
+ arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
+ env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=9.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
elif (env["arch"] == "arm"):
env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=9.0 -MMD -MT dependencies'.split())
elif (env["arch"] == "arm64"):
@@ -113,8 +117,9 @@ def configure(env):
## Link flags
- if (env["arch"] == "x86"):
- env.Append(LINKFLAGS=['-arch', 'i386', '-mios-simulator-version-min=4.3',
+ if (env["arch"] == "x86" or env["arch"] == "x86_64"):
+ arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
+ env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=9.0',
'-isysroot', '$IPHONESDK',
'-Xlinker',
'-objc_abi_version',
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 0507ef19d6..6aa1ed9f8d 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -56,11 +56,48 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata);
static Error _codesign(String p_file, void *p_userdata);
- void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug);
- static Error _export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
+ struct IOSConfigData {
+ String pkg_name;
+ String binary_name;
+ String plist_content;
+ String architectures;
+ String linker_flags;
+ String cpp_code;
+ };
+
+ struct ExportArchitecture {
+ String name;
+ bool is_default;
+
+ ExportArchitecture()
+ : name(""), is_default(false) {
+ }
+
+ ExportArchitecture(String p_name, bool p_is_default) {
+ name = p_name;
+ is_default = p_is_default;
+ }
+ };
+
+ struct IOSExportAsset {
+ String exported_path;
+ bool is_framework; // framework is anything linked to the binary, otherwise it's a resource
+ };
+
+ String _get_additional_plist_content();
+ String _get_linker_flags();
+ String _get_cpp_code();
+ void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug);
Error _export_loading_screens(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir);
Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir);
+ Vector<ExportArchitecture> _get_supported_architectures();
+ Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset);
+
+ void _add_assets_to_project(Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets);
+ Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &r_exported_assets);
+ Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
+
protected:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
virtual void get_export_options(List<ExportOption> *r_options);
@@ -96,6 +133,17 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset>
if (p_preset->get("texture_format/etc2")) {
r_features->push_back("etc2");
}
+ Vector<String> architectures = _get_preset_architectures(p_preset);
+ for (int i = 0; i < architectures.size(); ++i) {
+ r_features->push_back(architectures[i]);
+ }
+}
+
+Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() {
+ Vector<ExportArchitecture> archs;
+ archs.push_back(ExportArchitecture("armv7", true));
+ archs.push_back(ExportArchitecture("arm64", true));
+ return archs;
}
void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
@@ -120,7 +168,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPhone/iPod Touch with retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPad
@@ -145,10 +192,13 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true));
- /* probably need some more info */
+ Vector<ExportArchitecture> architectures = _get_supported_architectures();
+ for (int i = 0; i < architectures.size(); ++i) {
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + architectures[i].name), architectures[i].is_default));
+ }
}
-void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug) {
+void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug) {
static const String export_method_string[] = {
"app-store",
"development",
@@ -158,13 +208,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
String str;
String strnew;
str.parse_utf8((const char *)pfile.ptr(), pfile.size());
- print_line(str);
Vector<String> lines = str.split("\n");
for (int i = 0; i < lines.size(); i++) {
if (lines[i].find("$binary") != -1) {
- strnew += lines[i].replace("$binary", p_binary) + "\n";
+ strnew += lines[i].replace("$binary", p_config.binary_name) + "\n";
} else if (lines[i].find("$name") != -1) {
- strnew += lines[i].replace("$name", p_name) + "\n";
+ strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
} else if (lines[i].find("$info") != -1) {
strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
} else if (lines[i].find("$identifier") != -1) {
@@ -186,10 +235,21 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n";
} else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) {
strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n";
+ } else if (lines[i].find("$provisioning_profile_uuid") != -1) {
+ String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release");
+ strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n";
} else if (lines[i].find("$code_sign_identity_debug") != -1) {
strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n";
} else if (lines[i].find("$code_sign_identity_release") != -1) {
strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n";
+ } else if (lines[i].find("$additional_plist_content") != -1) {
+ strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n";
+ } else if (lines[i].find("$godot_archs") != -1) {
+ strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n";
+ } else if (lines[i].find("$linker_flags") != -1) {
+ strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n";
+ } else if (lines[i].find("$cpp_code") != -1) {
+ strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n";
} else {
strnew += lines[i] + "\n";
}
@@ -204,27 +264,37 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
}
}
-Error EditorExportPlatformIOS::_export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
- if (!p_path.ends_with(".dylib")) return OK;
- const String &dest_dir = *(String *)p_userdata;
- String rel_path = p_path.replace_first("res://", "dylibs/");
- DirAccess *dest_dir_access = DirAccess::open(dest_dir);
- ERR_FAIL_COND_V(!dest_dir_access, ERR_CANT_OPEN);
-
- String base_dir = rel_path.get_base_dir();
- Error make_dir_err = OK;
- if (!dest_dir_access->dir_exists(base_dir)) {
- make_dir_err = dest_dir_access->make_dir_recursive(base_dir);
- }
- if (make_dir_err != OK) {
- memdelete(dest_dir_access);
- return make_dir_err;
+String EditorExportPlatformIOS::_get_additional_plist_content() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ String result;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ result += export_plugins[i]->get_ios_plist_content();
}
+ return result;
+}
- Error copy_err = dest_dir_access->copy(p_path, dest_dir + rel_path);
- memdelete(dest_dir_access);
+String EditorExportPlatformIOS::_get_linker_flags() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ String result;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ String flags = export_plugins[i]->get_ios_linker_flags();
+ if (flags.length() == 0) continue;
+ if (result.length() > 0) {
+ result += ' ';
+ }
+ result += flags;
+ }
+ // the flags will be enclosed in quotes, so need to escape them
+ return result.replace("\"", "\\\"");
+}
- return copy_err;
+String EditorExportPlatformIOS::_get_cpp_code() {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ String result;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ result += export_plugins[i]->get_ios_cpp_code();
+ }
+ return result;
}
struct IconInfo {
@@ -402,7 +472,207 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) {
return OK;
}
+struct PbxId {
+private:
+ static char _hex_char(uint8_t four_bits) {
+ if (four_bits < 10) {
+ return ('0' + four_bits);
+ }
+ return 'A' + (four_bits - 10);
+ }
+
+ static String _hex_pad(uint32_t num) {
+ Vector<char> ret;
+ ret.resize(sizeof(num) * 2);
+ for (int i = 0; i < sizeof(num) * 2; ++i) {
+ uint8_t four_bits = (num >> (sizeof(num) * 8 - (i + 1) * 4)) & 0xF;
+ ret[i] = _hex_char(four_bits);
+ }
+ return String::utf8(ret.ptr(), ret.size());
+ }
+
+public:
+ uint32_t high_bits;
+ uint32_t mid_bits;
+ uint32_t low_bits;
+
+ String str() const {
+ return _hex_pad(high_bits) + _hex_pad(mid_bits) + _hex_pad(low_bits);
+ }
+
+ PbxId &operator++() {
+ low_bits++;
+ if (!low_bits) {
+ mid_bits++;
+ if (!mid_bits) {
+ high_bits++;
+ }
+ }
+
+ return *this;
+ }
+};
+
+struct ExportLibsData {
+ Vector<String> lib_paths;
+ String dest_dir;
+};
+
+void EditorExportPlatformIOS::_add_assets_to_project(Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets) {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ Vector<String> frameworks;
+ for (int i = 0; i < export_plugins.size(); ++i) {
+ Vector<String> plugin_frameworks = export_plugins[i]->get_ios_frameworks();
+ for (int j = 0; j < plugin_frameworks.size(); ++j) {
+ frameworks.push_back(plugin_frameworks[j]);
+ }
+ }
+
+ // that is just a random number, we just need Godot IDs not to clash with
+ // existing IDs in the project.
+ PbxId current_id = { 0x58938401, 0, 0 };
+ String pbx_files;
+ String pbx_frameworks_build;
+ String pbx_frameworks_refs;
+ String pbx_resources_build;
+ String pbx_resources_refs;
+
+ const String file_info_format = String("$build_id = {isa = PBXBuildFile; fileRef = $ref_id; };\n") +
+ "$ref_id = {isa = PBXFileReference; lastKnownFileType = $file_type; name = $name; path = \"$file_path\"; sourceTree = \"<group>\"; };\n";
+ for (int i = 0; i < p_additional_assets.size(); ++i) {
+ String build_id = (++current_id).str();
+ String ref_id = (++current_id).str();
+ const IOSExportAsset &asset = p_additional_assets[i];
+
+ String type;
+ if (asset.exported_path.ends_with(".framework")) {
+ type = "wrapper.framework";
+ } else if (asset.exported_path.ends_with(".dylib")) {
+ type = "compiled.mach-o.dylib";
+ } else if (asset.exported_path.ends_with(".a")) {
+ type = "archive.ar";
+ } else {
+ type = "file";
+ }
+
+ String &pbx_build = asset.is_framework ? pbx_frameworks_build : pbx_resources_build;
+ String &pbx_refs = asset.is_framework ? pbx_frameworks_refs : pbx_resources_refs;
+
+ if (pbx_build.length() > 0) {
+ pbx_build += ",\n";
+ pbx_refs += ",\n";
+ }
+ pbx_build += build_id;
+ pbx_refs += ref_id;
+
+ Dictionary format_dict;
+ format_dict["build_id"] = build_id;
+ format_dict["ref_id"] = ref_id;
+ format_dict["name"] = asset.exported_path.get_file();
+ format_dict["file_path"] = asset.exported_path;
+ format_dict["file_type"] = type;
+ pbx_files += file_info_format.format(format_dict, "$_");
+ }
+
+ String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size());
+ str = str.replace("$additional_pbx_files", pbx_files);
+ str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build);
+ str = str.replace("$additional_pbx_frameworks_refs", pbx_frameworks_refs);
+ str = str.replace("$additional_pbx_resources_build", pbx_resources_build);
+ str = str.replace("$additional_pbx_resources_refs", pbx_resources_refs);
+
+ CharString cs = str.utf8();
+ p_project_data.resize(cs.size() - 1);
+ for (int i = 0; i < cs.size() - 1; i++) {
+ p_project_data[i] = cs[i];
+ }
+}
+
+Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &r_exported_assets) {
+ DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(!filesystem_da, ERR_CANT_CREATE);
+ for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) {
+ String asset = p_assets[f_idx];
+ if (!asset.begins_with("res://")) {
+ // either SDK-builtin or already a part of the export template
+ IOSExportAsset exported_asset = { asset, p_is_framework };
+ r_exported_assets.push_back(exported_asset);
+ } else {
+ DirAccess *da = DirAccess::create_for_path(asset);
+ if (!da) {
+ memdelete(filesystem_da);
+ ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ }
+ bool file_exists = da->file_exists(asset);
+ bool dir_exists = da->dir_exists(asset);
+ if (!file_exists && !dir_exists) {
+ memdelete(da);
+ memdelete(filesystem_da);
+ return ERR_FILE_NOT_FOUND;
+ }
+ String additional_dir = p_is_framework && asset.ends_with(".dylib") ? "/dylibs/" : "/";
+ String destination_dir = p_out_dir + additional_dir + asset.get_base_dir().replace("res://", "");
+ if (!filesystem_da->dir_exists(destination_dir)) {
+ Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
+ if (make_dir_err) {
+ memdelete(da);
+ memdelete(filesystem_da);
+ return make_dir_err;
+ }
+ }
+
+ String destination = destination_dir + "/" + asset.get_file();
+ Error err = dir_exists ? da->copy_dir(asset, destination) : da->copy(asset, destination);
+ memdelete(da);
+ if (err) {
+ memdelete(filesystem_da);
+ return err;
+ }
+ IOSExportAsset exported_asset = { destination, p_is_framework };
+ r_exported_assets.push_back(exported_asset);
+ }
+ }
+ memdelete(filesystem_da);
+
+ return OK;
+}
+
+Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) {
+ Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+ for (int i = 0; i < export_plugins.size(); i++) {
+ Vector<String> frameworks = export_plugins[i]->get_ios_frameworks();
+ Error err = _export_additional_assets(p_out_dir, frameworks, true, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+ Vector<String> ios_bundle_files = export_plugins[i]->get_ios_bundle_files();
+ err = _export_additional_assets(p_out_dir, ios_bundle_files, false, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ Vector<String> library_paths;
+ for (int i = 0; i < p_libraries.size(); ++i) {
+ library_paths.push_back(p_libraries[i].path);
+ }
+ Error err = _export_additional_assets(p_out_dir, library_paths, true, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+
+ return OK;
+}
+
+Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) {
+ Vector<ExportArchitecture> all_archs = _get_supported_architectures();
+ Vector<String> enabled_archs;
+ for (int i = 0; i < all_archs.size(); ++i) {
+ bool is_enabled = p_preset->get("architectures/" + all_archs[i].name);
+ if (is_enabled) {
+ enabled_archs.push_back(all_archs[i].name);
+ }
+ }
+ return enabled_archs;
+}
+
Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
+
String src_pkg_name;
String dest_dir = p_path.get_base_dir() + "/";
String binary_name = p_path.get_file().get_basename();
@@ -427,26 +697,43 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
}
}
- FileAccess *src_f = NULL;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da) {
+ String current_dir = da->get_current_dir();
- ep.step("Creating app", 0);
+ // remove leftovers from last export so they don't interfere
+ // in case some files are no longer needed
+ if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
+ da->erase_contents_recursive();
+ }
+ if (da->change_dir(dest_dir + binary_name) == OK) {
+ da->erase_contents_recursive();
+ }
- unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
- if (!src_pkg_zip) {
+ da->change_dir(current_dir);
- EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);
- return ERR_FILE_NOT_FOUND;
+ if (!da->dir_exists(dest_dir + binary_name)) {
+ Error err = da->make_dir(dest_dir + binary_name);
+ if (err) {
+ memdelete(da);
+ return err;
+ }
+ }
+ memdelete(da);
}
- ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
- int ret = unzGoToFirstFile(src_pkg_zip);
+ ep.step("Making .pck", 0);
+ String pack_path = dest_dir + binary_name + ".pck";
+ Vector<SharedObject> libraries;
+ Error err = save_pack(p_preset, pack_path, &libraries);
+ if (err)
+ return err;
+
+ ep.step("Extracting and configuring Xcode project", 1);
- String binary_to_use = "godot.iphone." + String(p_debug ? "debug" : "release") + ".";
- int bits_mode = p_preset->get("application/bits_mode");
- binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "arm64" : "armv7");
+ String library_to_use = "libgodot.iphone." + String(p_debug ? "debug" : "release") + ".fat.a";
- print_line("binary: " + binary_to_use);
+ print_line("static library: " + library_to_use);
String pkg_name;
if (p_preset->get("application/name") != "")
pkg_name = p_preset->get("application/name"); // app_name
@@ -455,22 +742,41 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
else
pkg_name = "Unnamed";
- DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
- ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
-
- /* Now process our template */
- bool found_binary = false;
+ bool found_library = false;
int total_size = 0;
+ const String project_file = "godot_ios.xcodeproj/project.pbxproj";
Set<String> files_to_parse;
files_to_parse.insert("godot_ios/godot_ios-Info.plist");
- files_to_parse.insert("godot_ios.xcodeproj/project.pbxproj");
- files_to_parse.insert("export_options.plist");
+ files_to_parse.insert(project_file);
+ files_to_parse.insert("godot_ios/export_options.plist");
+ files_to_parse.insert("godot_ios/dummy.cpp");
files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata");
files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme");
- print_line("Unzipping...");
+ IOSConfigData config_data = {
+ pkg_name,
+ binary_name,
+ _get_additional_plist_content(),
+ String(" ").join(_get_preset_architectures(p_preset)),
+ _get_linker_flags(),
+ _get_cpp_code()
+ };
+
+ DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
+ ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
+ print_line("Unzipping...");
+ FileAccess *src_f = NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
+ if (!src_pkg_zip) {
+ EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name);
+ return ERR_CANT_OPEN;
+ }
+ ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
+ int ret = unzGoToFirstFile(src_pkg_zip);
+ Vector<uint8_t> project_file_data;
while (ret == UNZ_OK) {
bool is_execute = false;
@@ -496,15 +802,18 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (files_to_parse.has(file)) {
print_line(String("parse ") + file);
- _fix_config_file(p_preset, data, pkg_name, binary_name, p_debug);
- } else if (file.begins_with("godot.iphone")) {
- if (file != binary_to_use) {
+ _fix_config_file(p_preset, data, config_data, p_debug);
+ } else if (file.begins_with("libgodot.iphone")) {
+ if (file != library_to_use) {
ret = unzGoToNextFile(src_pkg_zip);
continue; //ignore!
}
- found_binary = true;
+ found_library = true;
is_execute = true;
- file = "godot_ios.iphone";
+ file = "godot_ios.a";
+ }
+ if (file == project_file) {
+ project_file_data = data;
}
///@TODO need to parse logo files
@@ -557,16 +866,16 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
/* we're done with our source zip */
unzClose(src_pkg_zip);
- if (!found_binary) {
- ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive.");
+ if (!found_library) {
+ ERR_PRINTS("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive.");
memdelete(tmp_app_path);
return ERR_FILE_NOT_FOUND;
}
String iconset_dir = dest_dir + binary_name + "/Images.xcassets/AppIcon.appiconset/";
- Error err = OK;
+ err = OK;
if (!tmp_app_path->dir_exists(iconset_dir)) {
- Error err = tmp_app_path->make_dir_recursive(iconset_dir);
+ err = tmp_app_path->make_dir_recursive(iconset_dir);
}
memdelete(tmp_app_path);
if (err)
@@ -580,20 +889,23 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (err)
return err;
- ep.step("Making .pck", 1);
-
- String pack_path = dest_dir + binary_name + ".pck";
- err = save_pack(p_preset, pack_path);
- if (err)
- return err;
-
- err = export_project_files(p_preset, _export_dylibs, &dest_dir);
- if (err)
- return err;
+ print_line("Exporting additional assets");
+ Vector<IOSExportAsset> assets;
+ _export_additional_assets(dest_dir + binary_name, libraries, assets);
+ _add_assets_to_project(project_file_data, assets);
+ String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
+ FileAccess *f = FileAccess::open(project_file_name, FileAccess::WRITE);
+ if (!f) {
+ ERR_PRINTS("Can't write '" + project_file_name + "'.");
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(project_file_data.ptr(), project_file_data.size());
+ f->close();
+ memdelete(f);
#ifdef OSX_ENABLED
ep.step("Code-signing dylibs", 2);
- DirAccess *dylibs_dir = DirAccess::open(dest_dir + "dylibs");
+ DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
CodesignData codesign_data(p_preset, p_debug);
err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
@@ -625,13 +937,14 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
export_args.push_back("-archivePath");
export_args.push_back(archive_path);
export_args.push_back("-exportOptionsPlist");
- export_args.push_back(dest_dir + "export_options.plist");
+ export_args.push_back(dest_dir + binary_name + "/export_options.plist");
+ export_args.push_back("-allowProvisioningUpdates");
export_args.push_back("-exportPath");
export_args.push_back(dest_dir);
err = OS::get_singleton()->execute("xcodebuild", export_args, true);
ERR_FAIL_COND_V(err, err);
#else
- print_line(".ipa can only be built on macOS. Leaving XCode project without building the package.");
+ print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package.");
#endif
return OK;
diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm
index 531b80eee3..d2104ae765 100644
--- a/platform/iphone/game_center.mm
+++ b/platform/iphone/game_center.mm
@@ -109,7 +109,7 @@ void GameCenter::connect() {
GameCenter::get_singleton()->authenticated = true;
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
ret["error_description"] = [error.localizedDescription UTF8String];
GameCenter::get_singleton()->authenticated = false;
};
@@ -145,7 +145,7 @@ Error GameCenter::post_score(Variant p_score) {
ret["result"] = "ok";
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
ret["error_description"] = [error.localizedDescription UTF8String];
};
@@ -183,7 +183,7 @@ Error GameCenter::award_achievement(Variant p_params) {
ret["result"] = "ok";
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -241,7 +241,7 @@ void GameCenter::request_achievement_descriptions() {
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -273,7 +273,7 @@ void GameCenter::request_achievements() {
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -289,7 +289,7 @@ void GameCenter::reset_achievements() {
ret["result"] = "ok";
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
};
pending_events.push_back(ret);
@@ -358,7 +358,7 @@ Error GameCenter::request_identity_verification_signature() {
ret["player_id"] = [player.playerID UTF8String];
} else {
ret["result"] = "error";
- ret["error_code"] = error.code;
+ ret["error_code"] = (int64_t)error.code;
ret["error_description"] = [error.localizedDescription UTF8String];
};
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 95d7710c76..90cb09b458 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -46,6 +46,7 @@
#include "sem_iphone.h"
#include "ios.h"
+#include <dlfcn.h>
int OSIPhone::get_video_driver_count() const {
@@ -99,9 +100,11 @@ void OSIPhone::initialize_core() {
void OSIPhone::initialize_logger() {
Vector<Logger *> loggers;
loggers.push_back(memnew(SyslogLogger));
- // FIXME: Reenable once we figure out how to get this properly in user://
- // instead of littering the user's working dirs (res:// + pwd) with log files (GH-12277)
- //loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+#ifdef DEBUG_ENABLED
+ // it seems iOS app's stdout/stderr is only obtainable if you launch it from Xcode
+ loggers.push_back(memnew(StdLogger));
+#endif
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
_set_logger(memnew(CompositeLogger(loggers)));
}
@@ -402,6 +405,37 @@ void OSIPhone::alert(const String &p_alert, const String &p_title) {
iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
}
+Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle) {
+ if (p_path.length() == 0) {
+ p_library_handle = RTLD_SELF;
+ return OK;
+ }
+ return OS_Unix::open_dynamic_library(p_path, p_library_handle);
+}
+
+Error OSIPhone::close_dynamic_library(void *p_library_handle) {
+ if (p_library_handle == RTLD_SELF) {
+ return OK;
+ }
+ return OS_Unix::close_dynamic_library(p_library_handle);
+}
+
+HashMap<String, void *> OSIPhone::dynamic_symbol_lookup_table;
+void register_dynamic_symbol(char *name, void *address) {
+ OSIPhone::dynamic_symbol_lookup_table[String(name)] = address;
+}
+
+Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
+ if (p_library_handle == RTLD_SELF) {
+ void **ptr = OSIPhone::dynamic_symbol_lookup_table.getptr(p_name);
+ if (ptr) {
+ p_symbol_handle = *ptr;
+ return OK;
+ }
+ }
+ return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional);
+}
+
void OSIPhone::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
video_mode = p_video_mode;
@@ -558,7 +592,36 @@ bool OSIPhone::_check_internal_feature_support(const String &p_feature) {
return p_feature == "mobile" || p_feature == "etc" || p_feature == "pvrtc" || p_feature == "etc2";
}
+// Initialization order between compilation units is not guaranteed,
+// so we use this as a hack to ensure certain code is called before
+// everything else, but after all units are initialized.
+typedef void (*init_callback)();
+static init_callback *ios_init_callbacks = NULL;
+static int ios_init_callbacks_count = 0;
+static int ios_init_callbacks_capacity = 0;
+
+void add_ios_init_callback(init_callback cb) {
+ if (ios_init_callbacks_count == ios_init_callbacks_capacity) {
+ void *new_ptr = realloc(ios_init_callbacks, sizeof(cb) * 32);
+ if (new_ptr) {
+ ios_init_callbacks = (init_callback *)(new_ptr);
+ ios_init_callbacks_capacity += 32;
+ }
+ }
+ if (ios_init_callbacks_capacity > ios_init_callbacks_count) {
+ ios_init_callbacks[ios_init_callbacks_count] = cb;
+ ++ios_init_callbacks_count;
+ }
+}
+
OSIPhone::OSIPhone(int width, int height, String p_data_dir) {
+ for (int i = 0; i < ios_init_callbacks_count; ++i) {
+ ios_init_callbacks[i]();
+ }
+ free(ios_init_callbacks);
+ ios_init_callbacks = NULL;
+ ios_init_callbacks_count = 0;
+ ios_init_callbacks_capacity = 0;
main_loop = NULL;
visual_server = NULL;
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index 433228b599..0790a2a9ea 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -60,6 +60,9 @@ private:
MAX_EVENTS = 64,
};
+ static HashMap<String, void *> dynamic_symbol_lookup_table;
+ friend void register_dynamic_symbol(char *name, void *address);
+
uint8_t supported_orientations;
VisualServer *visual_server;
@@ -153,6 +156,10 @@ public:
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+ virtual Error open_dynamic_library(const String p_path, void *&p_library_handle);
+ virtual Error close_dynamic_library(void *p_library_handle);
+ virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
+
virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
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;
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 943f6d8f35..05b0fb3fbc 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -155,6 +155,7 @@ String EditorExportPlatformJavaScript::get_binary_extension() const {
}
Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index f6922377e3..689b79b826 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -288,6 +288,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
}
Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
String src_pkg_name;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index e9e9dcc859..5e4dedcb48 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -525,6 +525,11 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
+ if (mb->get_button_index() == BUTTON_RIGHT) {
+ emit_signal("rmb_clicked", mb->get_position());
+
+ return;
+ }
}
if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
@@ -1397,6 +1402,7 @@ void ItemList::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position")));
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected")));
ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index")));
+ ADD_SIGNAL(MethodInfo("rmb_clicked", PropertyInfo(Variant::VECTOR2, "at_position")));
GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000);
}
diff --git a/version.py b/version.py
index 38847d68f5..cce155c9af 100644
--- a/version.py
+++ b/version.py
@@ -2,5 +2,5 @@ short_name = "godot"
name = "Godot Engine"
major = 3
minor = 0
-status = "alpha"
+status = "beta"
module_config = ""