summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/image.cpp16
-rw-r--r--core/image.h2
-rw-r--r--doc/base/classes.xml2
-rw-r--r--editor/SCsub149
-rw-r--r--editor/editor_node.cpp102
-rw-r--r--editor/editor_node.h5
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/curve_editor_plugin.cpp6
-rw-r--r--editor/plugins/editor_preview_plugins.cpp6
-rw-r--r--editor/plugins/shader_graph_editor_plugin.cpp2
-rw-r--r--platform/iphone/export/export.cpp345
-rw-r--r--platform/iphone/export/export.h30
-rw-r--r--platform/osx/export/export.cpp4
-rw-r--r--platform/x11/os_x11.cpp26
-rw-r--r--platform/x11/os_x11.h3
15 files changed, 667 insertions, 33 deletions
diff --git a/core/image.cpp b/core/image.cpp
index 023a058667..76f21a25de 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -423,7 +423,7 @@ void Image::convert(Format p_new_format) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
- new_img.put_pixel(i, j, get_pixel(i, j));
+ new_img.set_pixel(i, j, get_pixel(i, j));
}
}
@@ -1737,7 +1737,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
- put_pixel(dst_x, dst_y, dc);
+ set_pixel(dst_x, dst_y, dc);
}
}
@@ -1792,7 +1792,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
- put_pixel(dst_x, dst_y, dc);
+ set_pixel(dst_x, dst_y, dc);
}
}
}
@@ -1812,7 +1812,7 @@ void Image::fill(const Color &c) {
int pixel_size = get_format_pixel_size(format);
// put first pixel with the format-aware API
- put_pixel(0, 0, c);
+ set_pixel(0, 0, c);
for (int y = 0; y < height; y++) {
@@ -2041,12 +2041,12 @@ Color Image::get_pixel(int p_x, int p_y) const {
return Color();
}
-void Image::put_pixel(int p_x, int p_y, const Color &p_color) {
+void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
uint8_t *ptr = write_lock.ptr();
#ifdef DEBUG_ENABLED
if (!ptr) {
- ERR_EXPLAIN("Image must be locked with 'lock()' before using put_pixel()");
+ ERR_EXPLAIN("Image must be locked with 'lock()' before using set_pixel()");
ERR_FAIL_COND(!ptr);
}
@@ -2160,7 +2160,7 @@ void Image::put_pixel(int p_x, int p_y, const Color &p_color) {
} break;
default: {
- ERR_EXPLAIN("Can't put_pixel() on compressed image, sorry.");
+ ERR_EXPLAIN("Can't set_pixel() on compressed image, sorry.");
ERR_FAIL();
}
}
@@ -2270,7 +2270,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("lock"), &Image::lock);
ClassDB::bind_method(D_METHOD("unlock"), &Image::unlock);
- ClassDB::bind_method(D_METHOD("put_pixel", "x", "y", "color"), &Image::put_pixel);
+ ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel);
ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
diff --git a/core/image.h b/core/image.h
index e523f703fa..7acc4744e9 100644
--- a/core/image.h
+++ b/core/image.h
@@ -315,7 +315,7 @@ public:
DetectChannels get_detected_channels();
Color get_pixel(int p_x, int p_y) const;
- void put_pixel(int p_x, int p_y, const Color &p_color);
+ void set_pixel(int p_x, int p_y, const Color &p_color);
void copy_internals_from(const Ref<Image> &p_image) {
ERR_FAIL_COND(p_image.is_null());
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 39f5c94a94..6ff3e0fa29 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -19218,7 +19218,7 @@
<description>
</description>
</method>
- <method name="put_pixel">
+ <method name="set_pixel">
<argument index="0" name="x" type="int">
</argument>
<argument index="1" name="y" type="int">
diff --git a/editor/SCsub b/editor/SCsub
index 47bdec2e0d..f0d378c097 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -187,9 +187,11 @@ def make_authors_header(target, source, env):
def make_license_header(target, source, env):
- src = source[0].srcnode().abspath
+ src_copyright = source[0].srcnode().abspath
+ src_license = source[1].srcnode().abspath
dst = target[0].srcnode().abspath
- f = open(src, "rb")
+ f = open(src_license, "rb")
+ fc = open(src_copyright, "rb")
g = open(dst, "wb")
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
@@ -201,6 +203,145 @@ def make_license_header(target, source, env):
g.write("\n\t\"" + line.strip().replace("\"", "\\\"") + "\\n\"")
g.write(";\n")
+
+ tp_current = 0
+ tp_file = ""
+ tp_comment = ""
+ tp_copyright = ""
+ tp_license = ""
+
+ tp_licensename = ""
+ tp_licensebody = ""
+
+ tp = []
+ tp_licensetext = []
+ for line in fc:
+ if line.startswith("#"):
+ continue
+
+ if line.startswith("Files:"):
+ tp_file = line[6:].strip()
+ tp_current = 1
+ elif line.startswith("Comment:"):
+ tp_comment = line[8:].strip()
+ tp_current = 2
+ elif line.startswith("Copyright:"):
+ tp_copyright = line[10:].strip()
+ tp_current = 3
+ elif line.startswith("License:"):
+ if tp_current != 0:
+ tp_license = line[8:].strip()
+ tp_current = 4
+ else:
+ tp_licensename = line[8:].strip()
+ tp_current = 5
+ elif line.startswith(" "):
+ if tp_current == 1:
+ tp_file += "\n" + line.strip()
+ elif tp_current == 3:
+ tp_copyright += "\n" + line.strip()
+ elif tp_current == 5:
+ if line.strip() == ".":
+ tp_licensebody += "\n"
+ else:
+ tp_licensebody += line[1:]
+ else:
+ if tp_current != 0:
+ if tp_current == 5:
+ tp_licensetext.append([tp_licensename, tp_licensebody])
+
+ tp_licensename = ""
+ tp_licensebody = ""
+ else:
+ added = False
+ for i in tp:
+ if i[0] == tp_comment:
+ i[1].append([tp_file, tp_copyright, tp_license])
+ added = True
+ break
+ if not added:
+ tp.append([tp_comment,[[tp_file, tp_copyright, tp_license]]])
+
+ tp_file = []
+ tp_comment = ""
+ tp_copyright = []
+ tp_license = ""
+ tp_current = 0
+
+ about_thirdparty = ""
+ about_tp_copyright_count = ""
+ about_tp_license = ""
+ about_tp_copyright = ""
+ about_tp_file = ""
+
+ for i in tp:
+ about_thirdparty += "\t\"" + i[0] + "\",\n"
+ about_tp_copyright_count += str(len(i[1])) + ", "
+ for j in i[1]:
+ file_body = ""
+ copyright_body = ""
+ for k in j[0].split("\n"):
+ if file_body != "":
+ file_body += "\\n\"\n"
+ file_body += "\t\"" + k.strip().replace("\"", "\\\"")
+ for k in j[1].split("\n"):
+ if copyright_body != "":
+ copyright_body += "\\n\"\n"
+ copyright_body += "\t\"" + k.strip().replace("\"", "\\\"")
+
+ about_tp_file += "\t" + file_body + "\",\n"
+ about_tp_copyright += "\t" + copyright_body + "\",\n"
+ about_tp_license += "\t\"" + j[2] + "\",\n"
+
+ about_license_name = ""
+ about_license_body = ""
+
+ for i in tp_licensetext:
+ body = ""
+ for j in i[1].split("\n"):
+ if body != "":
+ body += "\\n\"\n"
+ body += "\t\"" + j.strip().replace("\"", "\\\"")
+
+ about_license_name += "\t\"" + i[0] + "\",\n"
+ about_license_body += "\t" + body + "\",\n"
+
+ g.write("static const char *about_thirdparty[] = {\n")
+ g.write(about_thirdparty)
+ g.write("\t0\n")
+ g.write("};\n")
+ g.write("#define THIRDPARTY_COUNT " + str(len(tp)) + "\n")
+
+ g.write("static const int about_tp_copyright_count[] = {\n\t")
+ g.write(about_tp_copyright_count)
+ g.write("0\n};\n")
+
+ g.write("static const char *about_tp_file[] = {\n")
+ g.write(about_tp_file)
+ g.write("\t0\n")
+ g.write("};\n")
+
+ g.write("static const char *about_tp_copyright[] = {\n")
+ g.write(about_tp_copyright)
+ g.write("\t0\n")
+ g.write("};\n")
+
+ g.write("static const char *about_tp_license[] = {\n")
+ g.write(about_tp_license)
+ g.write("\t0\n")
+ g.write("};\n")
+
+ g.write("static const char *about_license_name[] = {\n")
+ g.write(about_license_name)
+ g.write("\t0\n")
+ g.write("};\n")
+ g.write("#define LICENSE_COUNT " + str(len(tp_licensetext)) + "\n")
+
+ g.write("static const char *about_license_body[] = {\n")
+ g.write(about_license_body)
+ g.write("\t0\n")
+ g.write("};\n")
+
g.write("#endif\n")
if (env["tools"] == "yes"):
@@ -254,8 +395,8 @@ if (env["tools"] == "yes"):
env.Command('#editor/authors.gen.h', "../AUTHORS.md", make_authors_header)
# License
- env.Depends('#editor/license.gen.h', "../LICENSE.txt")
- env.Command('#editor/license.gen.h', "../LICENSE.txt", make_license_header)
+ env.Depends('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"])
+ env.Command('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], make_license_header)
env.add_source_files(env.editor_sources, "*.cpp")
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index c52a133e78..1df991ab24 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -4948,6 +4948,13 @@ void EditorNode::_check_gui_base_size() {
}
}
+void EditorNode::_license_tree_selected() {
+
+ TreeItem *selected = _tpl_tree->get_selected();
+ _tpl_text->select(0, 0, 0, 0);
+ _tpl_text->set_text(selected->get_metadata(0));
+}
+
void EditorNode::open_export_template_manager() {
export_template_manager->popup_manager();
@@ -5037,6 +5044,8 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout);
ClassDB::bind_method(D_METHOD("_check_gui_base_size"), &EditorNode::_check_gui_base_size);
+ ClassDB::bind_method(D_METHOD("_license_tree_selected"), &EditorNode::_license_tree_selected);
+
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
ADD_SIGNAL(MethodInfo("stop_pressed"));
@@ -6110,15 +6119,6 @@ EditorNode::EditorNode() {
dev_base->set_v_size_flags(Control::SIZE_EXPAND);
tc->add_child(dev_base);
- TextEdit *license = memnew(TextEdit);
- license->set_name(TTR("License"));
- license->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- license->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- license->set_wrap(true);
- license->set_readonly(true);
- license->set_text(String::utf8(about_license));
- tc->add_child(license);
-
VBoxContainer *dev_vbc = memnew(VBoxContainer);
dev_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
dev_base->add_child(dev_vbc);
@@ -6151,6 +6151,90 @@ EditorNode::EditorNode() {
hs->set_modulate(Color(0, 0, 0, 0));
dev_vbc->add_child(hs);
}
+
+ TextEdit *license = memnew(TextEdit);
+ license->set_name(TTR("License"));
+ license->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ license->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ license->set_wrap(true);
+ license->set_readonly(true);
+ license->set_text(String::utf8(about_license));
+ tc->add_child(license);
+
+ VBoxContainer *license_thirdparty = memnew(VBoxContainer);
+ license_thirdparty->set_name(TTR("Thirdparty License"));
+ license_thirdparty->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ tc->add_child(license_thirdparty);
+
+ Label *tpl_label = memnew(Label);
+ tpl_label->set_custom_minimum_size(Size2(0, 64 * EDSCALE));
+ tpl_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ tpl_label->set_autowrap(true);
+ tpl_label->set_text(TTR("Godot Engine relies on a number of thirdparty free and open source libraries, all compatible with the terms of its MIT license. The following is an exhaustive list of all such thirdparty components with their respective copyright statements and license terms."));
+ license_thirdparty->add_child(tpl_label);
+
+ HSplitContainer *tpl_hbc = memnew(HSplitContainer);
+ tpl_hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ tpl_hbc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ tpl_hbc->set_split_offset(240 * EDSCALE);
+ license_thirdparty->add_child(tpl_hbc);
+
+ _tpl_tree = memnew(Tree);
+ _tpl_tree->set_hide_root(true);
+ TreeItem *root = _tpl_tree->create_item();
+ TreeItem *tpl_ti_all = _tpl_tree->create_item(root);
+ tpl_ti_all->set_text(0, TTR("All Components"));
+ TreeItem *tpl_ti_tp = _tpl_tree->create_item(root);
+ tpl_ti_tp->set_text(0, TTR("Components"));
+ tpl_ti_tp->set_selectable(0, false);
+ TreeItem *tpl_ti_lc = _tpl_tree->create_item(root);
+ tpl_ti_lc->set_text(0, TTR("Licenses"));
+ tpl_ti_lc->set_selectable(0, false);
+ int read_idx = 0;
+ String long_text = "";
+ for (int i = 0; i < THIRDPARTY_COUNT; i++) {
+
+ TreeItem *ti = _tpl_tree->create_item(tpl_ti_tp);
+ String thirdparty = String(about_thirdparty[i]);
+ ti->set_text(0, thirdparty);
+ String text = thirdparty + "\n";
+ long_text += "- " + thirdparty + "\n\n";
+ for (int j = 0; j < about_tp_copyright_count[i]; j++) {
+
+ text += "\n Files:\n " + String(about_tp_file[read_idx]).replace("\n", "\n ") + "\n";
+ String copyright = String::utf8(" \u00A9 ") + String::utf8(about_tp_copyright[read_idx]).replace("\n", String::utf8("\n \u00A9 "));
+ text += copyright;
+ long_text += copyright;
+ String license = "\n License: " + String(about_tp_license[read_idx]) + "\n";
+ text += license;
+ long_text += license + "\n";
+ read_idx++;
+ }
+ ti->set_metadata(0, text);
+ }
+ for (int i = 0; i < LICENSE_COUNT; i++) {
+
+ TreeItem *ti = _tpl_tree->create_item(tpl_ti_lc);
+ String licensename = String(about_license_name[i]);
+ ti->set_text(0, licensename);
+ long_text += "- " + licensename + "\n\n";
+ String licensebody = String(about_license_body[i]);
+ ti->set_metadata(0, licensebody);
+ long_text += " " + licensebody.replace("\n", "\n ") + "\n\n";
+ }
+ tpl_ti_all->set_metadata(0, long_text);
+ tpl_hbc->add_child(_tpl_tree);
+
+ _tpl_text = memnew(TextEdit);
+ _tpl_text->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ _tpl_text->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ _tpl_text->set_wrap(true);
+ _tpl_text->set_readonly(true);
+ tpl_hbc->add_child(_tpl_text);
+
+ _tpl_tree->connect("item_selected", this, "_license_tree_selected");
+ tpl_ti_all->select(0);
+ _tpl_text->set_text(tpl_ti_all->get_metadata(0));
}
warning = memnew(AcceptDialog);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 24acedbf26..49ac04243c 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -431,6 +431,9 @@ private:
List<String> previous_scenes;
bool opening_prev;
+ Tree *_tpl_tree;
+ TextEdit *_tpl_text;
+
void _dialog_action(String p_file);
void _edit_current();
@@ -636,6 +639,8 @@ private:
void _dim_timeout();
void _check_gui_base_size();
+ void _license_tree_selected();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index e51254f84b..7ce884a455 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1170,7 +1170,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
canvas_item->edit_set_state(se->undo_state);
if (canvas_item->cast_to<Node2D>())
canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot);
- if (canvas_item->cast_to<Node2D>())
+ if (canvas_item->cast_to<Control>())
canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot);
}
}
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index c74eaf21a1..2d05c8eba1 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -874,7 +874,7 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) {
Color bg_color(0.1, 0.1, 0.1, 1.0);
for (int i = 0; i < thumbnail_size; i++) {
for (int j = 0; j < thumbnail_size; j++) {
- im.put_pixel(i, j, bg_color);
+ im.set_pixel(i, j, bg_color);
}
}
@@ -890,7 +890,7 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) {
// Plot point
if (y >= 0 && y < im.get_height()) {
- im.put_pixel(x, y, line_color);
+ im.set_pixel(x, y, line_color);
}
// Plot vertical line to fix discontinuity (not 100% correct but enough for a preview)
@@ -904,7 +904,7 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) {
y1 = y;
}
for (int ly = y0; ly < y1; ++ly) {
- im.put_pixel(x, ly, line_color);
+ im.set_pixel(x, ly, line_color);
}
}
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 11d804422a..7f8581535c 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -431,7 +431,7 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
for (int i = 0; i < thumbnail_size; i++) {
for (int j = 0; j < thumbnail_size; j++) {
- img->put_pixel(i, j, bg_color);
+ img->set_pixel(i, j, bg_color);
}
}
@@ -469,8 +469,8 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
Color ul = color;
ul.a *= 0.5;
- img->put_pixel(col, line * 2, bg_color.blend(ul));
- img->put_pixel(col, line * 2 + 1, color);
+ img->set_pixel(col, line * 2, bg_color.blend(ul));
+ img->set_pixel(col, line * 2 + 1, color);
prev_is_text = _is_text_char(c);
}
diff --git a/editor/plugins/shader_graph_editor_plugin.cpp b/editor/plugins/shader_graph_editor_plugin.cpp
index 9c65ef667a..5506c035ec 100644
--- a/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/editor/plugins/shader_graph_editor_plugin.cpp
@@ -1382,7 +1382,7 @@ ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int
Color c = graph->default_get_value(type,p_id,param);
for (int x=1;x<14;x++)
for (int y=1;y<14;y++)
- icon_color.put_pixel(x,y,c);
+ icon_color.set_pixel(x,y,c);
Ref<ImageTexture> t;
t.instance();
t->create_from_image(icon_color);
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
new file mode 100644
index 0000000000..ec8470518a
--- /dev/null
+++ b/platform/iphone/export/export.cpp
@@ -0,0 +1,345 @@
+/*************************************************************************/
+/* export.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 "export.h"
+#include "editor/editor_export.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "global_config.h"
+#include "io/marshalls.h"
+#include "io/resource_saver.h"
+#include "io/zip_io.h"
+#include "os/file_access.h"
+#include "os/os.h"
+#include "platform/osx/logo.gen.h"
+#include "string.h"
+#include "version.h"
+
+#include <sys/stat.h>
+
+class EditorExportPlatformIOS : public EditorExportPlatform {
+
+ GDCLASS(EditorExportPlatformIOS, EditorExportPlatform);
+
+ int version_code;
+
+ Ref<ImageTexture> logo;
+
+ void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary);
+
+protected:
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
+ virtual void get_export_options(List<ExportOption> *r_options);
+
+public:
+ virtual String get_name() const { return "iOS"; }
+ virtual Ref<Texture> get_logo() const { return logo; }
+
+ virtual String get_binary_extension() const { return "xcodeproj"; }
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
+
+ virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
+
+ EditorExportPlatformIOS();
+ ~EditorExportPlatformIOS();
+};
+
+void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+
+ // what does this need to do?
+}
+
+void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "zip"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "zip"), ""));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
+ // r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier"), "org.godotengine.iosgame"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "godotiosgame"));
+ 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));
+
+ /* probably need some more info */
+}
+
+void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary) {
+
+ String str;
+ String strnew;
+ str.parse_utf8((const char *)pfile.ptr(), pfile.size());
+ 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";
+ } else if (lines[i].find("$name") != -1) {
+ strnew += lines[i].replace("$name", p_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) {
+ strnew += lines[i].replace("$identifier", p_preset->get("application/identifier")) + "\n";
+ } else if (lines[i].find("$short_version") != -1) {
+ strnew += lines[i].replace("$short_version", p_preset->get("application/short_version")) + "\n";
+ } else if (lines[i].find("$version") != -1) {
+ strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
+ } else if (lines[i].find("$signature") != -1) {
+ strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
+ } else if (lines[i].find("$copyright") != -1) {
+ strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
+ } else {
+ strnew += lines[i] + "\n";
+ }
+ }
+
+ // !BAS! I'm assuming the 9 in the original code was a typo. I've added -1 or else it seems to also be adding our terminating zero...
+ // should apply the same fix in our OSX export.
+ CharString cs = strnew.utf8();
+ pfile.resize(cs.size() - 1);
+ for (int i = 0; i < cs.size() - 1; i++) {
+ pfile[i] = cs[i];
+ }
+}
+
+Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ String src_pkg_name;
+ String dest_dir = p_path.get_base_dir() + "/";
+ String binary_name = p_path.get_file().get_basename();
+
+ EditorProgress ep("export", "Exporting for iOS", 3);
+
+ if (p_debug)
+ src_pkg_name = p_preset->get("custom_package/debug");
+ else
+ src_pkg_name = p_preset->get("custom_package/release");
+
+ if (src_pkg_name == "") {
+ String err;
+ src_pkg_name = find_export_template("iphone.zip", &err);
+ if (src_pkg_name == "") {
+ EditorNode::add_io_error(err);
+ return ERR_FILE_NOT_FOUND;
+ }
+ }
+
+ FileAccess *src_f = NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+
+ ep.step("Creating app", 0);
+
+ unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
+ if (!src_pkg_zip) {
+
+ EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
+ int ret = unzGoToFirstFile(src_pkg_zip);
+
+ 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");
+
+ print_line("binary: " + binary_to_use);
+ String pkg_name;
+ if (p_preset->get("application/name") != "")
+ pkg_name = p_preset->get("application/name"); // app_name
+ else if (String(GlobalConfig::get_singleton()->get("application/name")) != "")
+ pkg_name = String(GlobalConfig::get_singleton()->get("application/name"));
+ 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;
+ int total_size = 0;
+
+ while (ret == UNZ_OK) {
+ bool is_execute = false;
+
+ //get filename
+ unz_file_info info;
+ char fname[16384];
+ ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, NULL, 0, NULL, 0);
+
+ String file = fname;
+
+ print_line("READ: " + file);
+ Vector<uint8_t> data;
+ data.resize(info.uncompressed_size);
+
+ //read
+ unzOpenCurrentFile(src_pkg_zip);
+ unzReadCurrentFile(src_pkg_zip, data.ptr(), data.size());
+ unzCloseCurrentFile(src_pkg_zip);
+
+ //write
+
+ file = file.replace_first("iphone/", "");
+
+ if (file == "godot_ios.xcodeproj/project.pbxproj") {
+ print_line("parse pbxproj");
+ _fix_config_file(p_preset, data, pkg_name, binary_name);
+ } else if (file == "godot_ios/godot_ios-Info.plist") {
+ print_line("parse plist");
+ _fix_config_file(p_preset, data, pkg_name, binary_name);
+ } else if (file.begins_with("godot.iphone")) {
+ if (file != binary_to_use) {
+ ret = unzGoToNextFile(src_pkg_zip);
+ continue; //ignore!
+ }
+ found_binary = true;
+ is_execute = true;
+ file = "godot_ios.iphone";
+ }
+
+ ///@TODO need to parse logo files
+
+ if (data.size() > 0) {
+ file = file.replace("godot_ios", binary_name);
+
+ print_line("ADDING: " + file + " size: " + itos(data.size()));
+ total_size += data.size();
+
+ /* write it into our folder structure */
+ file = dest_dir + file;
+
+ /* make sure this folder exists */
+ String dir_name = file.get_base_dir();
+ if (!tmp_app_path->dir_exists(dir_name)) {
+ print_line("Creating " + dir_name);
+ Error dir_err = tmp_app_path->make_dir_recursive(dir_name);
+ if (dir_err) {
+ ERR_PRINTS("Can't create '" + dir_name + "'.");
+ unzClose(src_pkg_zip);
+ return ERR_CANT_CREATE;
+ }
+ }
+
+ /* write the file */
+ FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
+ if (!f) {
+ ERR_PRINTS("Can't write '" + file + "'.");
+ unzClose(src_pkg_zip);
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(data.ptr(), data.size());
+ f->close();
+ memdelete(f);
+
+ if (is_execute) {
+ // we need execute rights on this file
+ chmod(file.utf8().get_data(), 0755);
+ }
+ }
+
+ ret = unzGoToNextFile(src_pkg_zip);
+ }
+
+ /* 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.");
+ unzClose(src_pkg_zip);
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ ep.step("Making PKG", 1);
+
+ String pack_path = dest_dir + binary_name + ".pck";
+ Error err = save_pack(p_preset, pack_path);
+
+ if (err) {
+ return err;
+ }
+
+#ifdef OSX_ENABLED
+ /* and open up xcode with our new project.... */
+ List<String> args;
+ args.push_back(p_path);
+ err = OS::get_singleton()->execute("/usr/bin/open", args, false);
+ ERR_FAIL_COND_V(err, err);
+
+#endif
+
+ return OK;
+}
+
+bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
+
+ bool valid = true;
+ String err;
+
+ if (!exists_export_template("iphone.zip", &err)) {
+ valid = false;
+ }
+
+ if (p_preset->get("custom_package/debug") != "" && !FileAccess::exists(p_preset->get("custom_package/debug"))) {
+ valid = false;
+ err += "Custom debug package not found.\n";
+ }
+
+ if (p_preset->get("custom_package/release") != "" && !FileAccess::exists(p_preset->get("custom_package/release"))) {
+ valid = false;
+ err += "Custom release package not found.\n";
+ }
+
+ if (!err.empty())
+ r_error = err;
+
+ return valid;
+}
+
+EditorExportPlatformIOS::EditorExportPlatformIOS() {
+
+ ///@TODO need to create the correct logo
+ // Ref<Image> img = memnew(Image(_iphone_logo));
+ Ref<Image> img = memnew(Image(_osx_logo));
+ logo.instance();
+ logo->create_from_image(img);
+}
+
+EditorExportPlatformIOS::~EditorExportPlatformIOS() {
+}
+
+void register_iphone_exporter() {
+
+ Ref<EditorExportPlatformIOS> platform;
+ platform.instance();
+
+ EditorExport::get_singleton()->add_export_platform(platform);
+}
diff --git a/platform/iphone/export/export.h b/platform/iphone/export/export.h
new file mode 100644
index 0000000000..6e9324aed7
--- /dev/null
+++ b/platform/iphone/export/export.h
@@ -0,0 +1,30 @@
+/*************************************************************************/
+/* export.h */
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+void register_iphone_exporter();
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 9d3493cb49..c81fb00b36 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -185,8 +185,8 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
}
CharString cs = strnew.utf8();
- plist.resize(cs.size());
- for (int i = 9; i < cs.size(); i++) {
+ plist.resize(cs.size() - 1);
+ for (int i = 0; i < cs.size() - 1; i++) {
plist[i] = cs[i];
}
}
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 383abffe46..f2754cc180 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -278,6 +278,13 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
xev.xclient.data.l[2] = 0;
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev);
+ } else if (current_videomode.borderless_window) {
+ Hints hints;
+ Atom property;
+ hints.flags = 2;
+ hints.decorations = 0;
+ property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
+ XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
}
// disable resizable window
@@ -1018,6 +1025,25 @@ bool OS_X11::is_window_maximized() const {
return false;
}
+void OS_X11::set_borderless_window(int p_borderless) {
+
+ if (current_videomode.borderless_window == p_borderless)
+ return;
+
+ current_videomode.borderless_window = p_borderless;
+
+ Hints hints;
+ Atom property;
+ hints.flags = 2;
+ hints.decorations = current_videomode.borderless_window ? 0 : 1;
+ property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
+ XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+}
+
+bool OS_X11::get_borderless_window() {
+ return current_videomode.borderless_window;
+}
+
void OS_X11::request_attention() {
// Using EWMH -- Extended Window Manager Hints
//
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index b253934a05..39c512b6bd 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -251,6 +251,9 @@ public:
virtual bool is_window_maximized() const;
virtual void request_attention();
+ virtual void set_borderless_window(int p_borderless);
+ virtual bool get_borderless_window();
+
virtual void move_window_to_foreground();
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");