summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/detect.py152
-rw-r--r--platform/android/export/export.cpp14
-rw-r--r--platform/android/run_icon.pngbin0 -> 636 bytes
-rw-r--r--platform/haiku/detect.py51
-rw-r--r--platform/iphone/SCsub9
-rw-r--r--platform/iphone/detect.py180
-rw-r--r--platform/iphone/export/export.cpp347
-rw-r--r--platform/iphone/export/export.h30
-rw-r--r--platform/javascript/detect.py62
-rw-r--r--platform/javascript/export/export.cpp43
-rw-r--r--platform/javascript/run_icon.pngbin0 -> 471 bytes
-rw-r--r--platform/osx/detect.py70
-rw-r--r--platform/osx/export/export.cpp804
-rw-r--r--platform/osx/os_osx.h6
-rw-r--r--platform/osx/os_osx.mm91
-rw-r--r--platform/server/detect.py78
-rw-r--r--platform/uwp/detect.py106
-rw-r--r--platform/windows/detect.py272
-rw-r--r--platform/windows/export/export.cpp2
-rw-r--r--platform/windows/godot.icobin370070 -> 110755 bytes
-rw-r--r--platform/windows/os_windows.cpp114
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--platform/x11/detect.py151
-rw-r--r--platform/x11/export/export.cpp2
-rw-r--r--platform/x11/godot_x11.cpp3
-rw-r--r--platform/x11/os_x11.cpp202
-rw-r--r--platform/x11/os_x11.h7
27 files changed, 1710 insertions, 1088 deletions
diff --git a/platform/android/detect.py b/platform/android/detect.py
index ce44ffbf74..7508c9ed0e 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -14,22 +14,17 @@ def get_name():
def can_build():
- import os
- if (not os.environ.has_key("ANDROID_NDK_ROOT")):
- return False
-
- return True
+ return (os.environ.has_key("ANDROID_NDK_ROOT"))
def get_opts():
return [
- ('ANDROID_NDK_ROOT', 'the path to Android NDK',
- os.environ.get("ANDROID_NDK_ROOT", 0)),
- ('ndk_platform', 'compile for platform: (android-<api> , example: android-18)', "android-18"),
- ('android_arch', 'select compiler architecture: (armv7/armv6/x86)', "armv7"),
- ('android_neon', 'enable neon (armv7 only)', "yes"),
- ('android_stl', 'enable STL support in android port (for modules)', "no")
+ ('ANDROID_NDK_ROOT', 'Path to the Android NDK', os.environ.get("ANDROID_NDK_ROOT", 0)),
+ ('ndk_platform', 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
+ ('android_arch', 'Target architecture (armv7/armv6/x86)', "armv7"),
+ ('android_neon', 'Enable NEON support (armv7 only)', "yes"),
+ ('android_stl', 'Enable Android STL support (for modules)', "no")
]
@@ -41,6 +36,7 @@ def get_flags():
def create(env):
+
tools = env['TOOLS']
if "mingw" in tools:
tools.remove('mingw')
@@ -54,7 +50,6 @@ def configure(env):
# Workaround for MinGW. See:
# http://www.scons.org/wiki/LongCmdLinesOnWin32
- import os
if (os.name == "nt"):
import subprocess
@@ -92,35 +87,43 @@ def configure(env):
env['SPAWN'] = mySpawn
- ndk_platform = env['ndk_platform']
+ ## Build type
- if env['android_arch'] not in ['armv7', 'armv6', 'x86']:
- env['android_arch'] = 'armv7'
+ if (env["target"].startswith("release")):
+ env.Append(LINKFLAGS=['-O2'])
+ env.Append(CPPFLAGS=['-O2', '-DNDEBUG', '-ffast-math', '-funsafe-math-optimizations', '-fomit-frame-pointer'])
+ if (can_vectorize):
+ env.Append(CPPFLAGS=['-ftree-vectorize'])
+ if (env["target"] == "release_debug"):
+ env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
+ elif (env["target"] == "debug"):
+ env.Append(LINKFLAGS=['-O0'])
+ env.Append(CPPFLAGS=['-O0', '-D_DEBUG', '-UNDEBUG', '-DDEBUG_ENABLED',
+ '-DDEBUG_MEMORY_ENABLED', '-g', '-fno-limit-debug-info'])
- if env['android_arch'] == 'x86':
- env["x86_libtheora_opt_gcc"] = True
+ ## Architecture
- if env['PLATFORM'] == 'win32':
- env.Tool('gcc')
- env['SHLIBSUFFIX'] = '.so'
+ if env['android_arch'] not in ['armv7', 'armv6', 'x86']:
+ env['android_arch'] = 'armv7'
neon_text = ""
if env["android_arch"] == "armv7" and env['android_neon'] == 'yes':
- neon_text = " (with neon)"
- print("Godot Android!!!!! (" + env['android_arch'] + ")" + neon_text)
-
- env.Append(CPPPATH=['#platform/android'])
+ neon_text = " (with NEON)"
+ print("Building for Android (" + env['android_arch'] + ")" + neon_text)
+ can_vectorize = True
if env['android_arch'] == 'x86':
env.extra_suffix = ".x86" + env.extra_suffix
target_subpath = "x86-4.9"
abi_subpath = "i686-linux-android"
arch_subpath = "x86"
+ env["x86_libtheora_opt_gcc"] = True
elif env['android_arch'] == 'armv6':
env.extra_suffix = ".armv6" + env.extra_suffix
target_subpath = "arm-linux-androideabi-4.9"
abi_subpath = "arm-linux-androideabi"
arch_subpath = "armeabi"
+ can_vectorize = False
elif env["android_arch"] == "armv7":
target_subpath = "arm-linux-androideabi-4.9"
abi_subpath = "arm-linux-androideabi"
@@ -130,6 +133,14 @@ def configure(env):
else:
env.extra_suffix = ".armv7" + env.extra_suffix
+ ## Compiler configuration
+
+ env['SHLIBSUFFIX'] = '.so'
+
+ if env['PLATFORM'] == 'win32':
+ env.Tool('gcc')
+ env.use_windows_spawn_fix()
+
mt_link = True
if (sys.platform.startswith("linux")):
host_subpath = "linux-x86_64"
@@ -142,10 +153,8 @@ def configure(env):
mt_link = False
host_subpath = "windows"
- compiler_path = env["ANDROID_NDK_ROOT"] + \
- "/toolchains/llvm/prebuilt/" + host_subpath + "/bin"
- gcc_toolchain_path = env["ANDROID_NDK_ROOT"] + \
- "/toolchains/" + target_subpath + "/prebuilt/" + host_subpath
+ compiler_path = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/" + host_subpath + "/bin"
+ gcc_toolchain_path = env["ANDROID_NDK_ROOT"] + "/toolchains/" + target_subpath + "/prebuilt/" + host_subpath
tools_path = gcc_toolchain_path + "/" + abi_subpath + "/bin"
# For Clang to find NDK tools in preference of those system-wide
@@ -162,31 +171,28 @@ def configure(env):
else:
env['ARCH'] = 'arch-arm'
- sysroot = env["ANDROID_NDK_ROOT"] + \
- "/platforms/" + ndk_platform + "/" + env['ARCH']
+ sysroot = env["ANDROID_NDK_ROOT"] + "/platforms/" + env['ndk_platform'] + "/" + env['ARCH']
common_opts = ['-fno-integrated-as', '-gcc-toolchain', gcc_toolchain_path]
+ ## Compile flags
+
env.Append(CPPFLAGS=["-isystem", sysroot + "/usr/include"])
- env.Append(CPPFLAGS=string.split(
- '-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'))
+ env.Append(CPPFLAGS=string.split('-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'))
env.Append(CPPFLAGS=string.split('-DANDROID -DNO_STATVFS -DGLES2_ENABLED'))
env['neon_enabled'] = False
if env['android_arch'] == 'x86':
- can_vectorize = True
target_opts = ['-target', 'i686-none-linux-android']
# The NDK adds this if targeting API < 21, so we can drop it when Godot targets it at least
env.Append(CPPFLAGS=['-mstackrealign'])
+
elif env["android_arch"] == "armv6":
- can_vectorize = False
target_opts = ['-target', 'armv6-none-linux-androideabi']
- env.Append(CPPFLAGS=string.split(
- '-D__ARM_ARCH_6__ -march=armv6 -mfpu=vfp -mfloat-abi=softfp'))
+ env.Append(CPPFLAGS=string.split('-D__ARM_ARCH_6__ -march=armv6 -mfpu=vfp -mfloat-abi=softfp'))
+
elif env["android_arch"] == "armv7":
- can_vectorize = True
target_opts = ['-target', 'armv7-none-linux-androideabi']
- env.Append(CPPFLAGS=string.split(
- '-D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -march=armv7-a -mfloat-abi=softfp'))
+ env.Append(CPPFLAGS=string.split('-D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -march=armv7-a -mfloat-abi=softfp'))
if env['android_neon'] == 'yes':
env['neon_enabled'] = True
env.Append(CPPFLAGS=['-mfpu=neon', '-D__ARM_NEON__'])
@@ -196,21 +202,20 @@ def configure(env):
env.Append(CPPFLAGS=target_opts)
env.Append(CPPFLAGS=common_opts)
- env.Append(LIBS=['OpenSLES'])
- env.Append(LIBS=['EGL', 'OpenSLES', 'android'])
- env.Append(LIBS=['log', 'GLESv1_CM', 'GLESv2', 'GLESv3','z'])
-
- if (sys.platform.startswith("darwin")):
- env['SHLIBSUFFIX'] = '.so'
-
- env['LINKFLAGS'] = ['-shared', '--sysroot=' +
- sysroot, '-Wl,--warn-shared-textrel']
- env.Append(LINKFLAGS=string.split(
- '-Wl,--fix-cortex-a8'))
- env.Append(LINKFLAGS=string.split(
- '-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now'))
- env.Append(LINKFLAGS=string.split(
- '-Wl,-soname,libgodot_android.so -Wl,--gc-sections'))
+ if (env['android_stl'] == 'yes'):
+ env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/gnu-libstdc++/4.9/include"])
+ env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + arch_subpath + "/include"])
+ env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + arch_subpath])
+ env.Append(LIBS=["gnustl_static"])
+ else:
+ env.Append(CXXFLAGS=['-fno-rtti', '-fno-exceptions', '-DNO_SAFE_CAST'])
+
+ ## Link flags
+
+ env['LINKFLAGS'] = ['-shared', '--sysroot=' + sysroot, '-Wl,--warn-shared-textrel']
+ env.Append(LINKFLAGS=string.split('-Wl,--fix-cortex-a8'))
+ env.Append(LINKFLAGS=string.split('-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now'))
+ env.Append(LINKFLAGS=string.split('-Wl,-soname,libgodot_android.so -Wl,--gc-sections'))
if mt_link:
env.Append(LINKFLAGS=['-Wl,--threads'])
env.Append(LINKFLAGS=target_opts)
@@ -221,45 +226,12 @@ def configure(env):
env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] +
'/toolchains/arm-linux-androideabi-4.9/prebuilt/' + host_subpath + '/' + abi_subpath + '/lib'])
- if (env["target"].startswith("release")):
- env.Append(LINKFLAGS=['-O2'])
- env.Append(CPPFLAGS=['-O2', '-DNDEBUG', '-ffast-math',
- '-funsafe-math-optimizations', '-fomit-frame-pointer'])
- if (can_vectorize):
- env.Append(CPPFLAGS=['-ftree-vectorize'])
- if (env["target"] == "release_debug"):
- env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
- elif (env["target"] == "debug"):
- env.Append(LINKFLAGS=['-O0'])
- env.Append(CPPFLAGS=['-O0', '-D_DEBUG', '-UNDEBUG', '-DDEBUG_ENABLED',
- '-DDEBUG_MEMORY_ENABLED', '-g', '-fno-limit-debug-info'])
-
- env.Append(CPPFLAGS=['-DANDROID_ENABLED',
- '-DUNIX_ENABLED', '-DNO_FCNTL', '-DMPC_FIXED_POINT'])
+ env.Append(CPPPATH=['#platform/android'])
+ env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL', '-DMPC_FIXED_POINT'])
+ env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z'])
# TODO: Move that to opus module's config
if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
if (env["android_arch"] == "armv6" or env["android_arch"] == "armv7"):
env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
env.opus_fixed_point = "yes"
-
- if (env['android_stl'] == 'yes'):
- env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"] +
- "/sources/cxx-stl/gnu-libstdc++/4.9/include"])
- env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"] +
- "/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + arch_subpath + "/include"])
- env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] +
- "/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + arch_subpath])
- env.Append(LIBS=["gnustl_static"])
- else:
- env.Append(CXXFLAGS=['-fno-rtti', '-fno-exceptions', '-DNO_SAFE_CAST'])
-
- import methods
- env.Append(BUILDERS={'GLSL120': env.Builder(
- action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL': env.Builder(
- action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL120GLES': env.Builder(
- action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
-
- env.use_windows_spawn_fix()
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 51597526ab..a72e8aa90e 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -36,7 +36,8 @@
#include "io/zip_io.h"
#include "os/file_access.h"
#include "os/os.h"
-#include "platform/android/logo.h"
+#include "platform/android/logo.gen.h"
+#include "platform/android/run_icon.gen.h"
#include "version.h"
#include <string.h>
#if 0
@@ -2042,6 +2043,7 @@ class EditorExportAndroid : public EditorExportPlatform {
GDCLASS(EditorExportAndroid, EditorExportPlatform)
Ref<ImageTexture> logo;
+ Ref<ImageTexture> run_icon;
struct Device {
@@ -3036,6 +3038,10 @@ public:
return OK;
}
+ virtual Ref<Texture> get_run_icon() const {
+ return run_icon;
+ }
+
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
r_missing_templates = find_export_template("android_debug.apk") == String() || find_export_template("android_release.apk") == String();
@@ -3524,9 +3530,13 @@ public:
EditorExportAndroid() {
Ref<Image> img = memnew(Image(_android_logo));
- logo = Ref<ImageTexture>(memnew(ImageTexture));
+ logo.instance();
logo->create_from_image(img);
+ img = Ref<Image>(memnew(Image(_android_run_icon)));
+ run_icon.instance();
+ run_icon->create_from_image(img);
+
device_lock = Mutex::create();
device_thread = Thread::create(_device_poll_thread, this);
devices_changed = true;
diff --git a/platform/android/run_icon.png b/platform/android/run_icon.png
new file mode 100644
index 0000000000..e53f8e9da5
--- /dev/null
+++ b/platform/android/run_icon.png
Binary files differ
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index 54e227cd19..c0e003a3d2 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -11,57 +11,58 @@ def get_name():
def can_build():
- if (os.name != "posix"):
- return False
- if (sys.platform == "darwin"):
+ if (os.name != "posix" or sys.platform == "darwin"):
return False
return True
def get_opts():
+
return [
('debug_release', 'Add debug symbols to release version', 'no')
]
def get_flags():
+
return [
]
def configure(env):
- is64 = sys.maxsize > 2**32
-
- if (env["bits"] == "default"):
- if (is64):
- env["bits"] = "64"
- else:
- env["bits"] = "32"
-
- env.Append(CPPPATH=['#platform/haiku'])
- env["CC"] = "gcc-x86"
- env["CXX"] = "g++-x86"
+ ## Build type
if (env["target"] == "release"):
if (env["debug_release"] == "yes"):
- env.Append(CCFLAGS=['-g2'])
+ env.Prepend(CCFLAGS=['-g2'])
else:
- env.Append(CCFLAGS=['-O3', '-ffast-math'])
+ env.Prepend(CCFLAGS=['-O3', '-ffast-math'])
+
elif (env["target"] == "release_debug"):
- env.Append(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
+
elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Prepend(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+
+ ## Architecture
+
+ is64 = sys.maxsize > 2**32
+ if (env["bits"] == "default"):
+ env["bits"] = "64" if is64 else "32"
+
+ ## Compiler configuration
+ env["CC"] = "gcc-x86"
+ env["CXX"] = "g++-x86"
+
+ ## Flags
+
+ env.Append(CPPPATH=['#platform/haiku'])
+ env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
+ env.Append(CPPFLAGS=['-DMEDIA_KIT_ENABLED'])
# env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
env.Append(CPPFLAGS=['-DPTHREAD_NO_RENAME']) # TODO: enable when we have pthread_setname_np
- env.Append(CPPFLAGS=['-DOPENGL_ENABLED', '-DMEDIA_KIT_ENABLED'])
- env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
env.Append(LIBS=['be', 'game', 'media', 'network', 'bnetapi', 'z', 'GL'])
-
- import methods
- env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 466b8241de..998d0a3f0d 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -17,17 +17,8 @@ iphone_lib = [
'ios.mm',
]
-# env.Depends('#core/math/vector3.h', 'vector3_psp.h')
-
-#iphone_lib = env.Library('iphone', iphone_lib)
-
env_ios = env.Clone()
-
-if env['ios_gles22_override'] == "yes":
- env_ios.Append(CPPFLAGS=['-DGLES2_OVERRIDE'])
-
-
obj = env_ios.Object('godot_iphone.cpp')
prog = None
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index c20d8e90f4..1d802ff288 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -1,4 +1,5 @@
import os
+import string
import sys
@@ -12,8 +13,6 @@ def get_name():
def can_build():
- import sys
- import os
if sys.platform == 'darwin' or os.environ.has_key("OSXCROSS_IOS"):
return True
@@ -23,13 +22,12 @@ def can_build():
def get_opts():
return [
- ('IPHONEPLATFORM', 'name of the iphone platform', 'iPhoneOS'),
- ('IPHONEPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
- ('IPHONESDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/${IPHONEPLATFORM}.platform/Developer/SDKs/${IPHONEPLATFORM}.sdk/'),
+ ('IPHONEPLATFORM', 'Name of the iPhone platform', 'iPhoneOS'),
+ ('IPHONEPATH', 'Path to iPhone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
+ ('IPHONESDK', 'Path to the iPhone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/${IPHONEPLATFORM}.platform/Developer/SDKs/${IPHONEPLATFORM}.sdk/'),
('game_center', 'Support for game center', 'yes'),
('store_kit', 'Support for in-app store', 'yes'),
('icloud', 'Support for iCloud', 'yes'),
- ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
('ios_exceptions', 'Enable exceptions', 'no'),
('ios_triple', 'Triple for ios toolchain', ''),
('ios_sim', 'Build simulator binary', 'no'),
@@ -45,95 +43,92 @@ def get_flags():
def configure(env):
- env.Append(CPPPATH=['#platform/iphone'])
+ ## Build type
- env['ENV']['PATH'] = env['IPHONEPATH'] + "/Developer/usr/bin/:" + env['ENV']['PATH']
+ if (env["target"].startswith("release")):
+ env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1'])
+ env.Append(CPPFLAGS=['-O2', '-flto', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations'])
+ env.Append(LINKFLAGS=['-O2', '-flto'])
- env['CC'] = '$IPHONEPATH/usr/bin/${ios_triple}clang'
- env['CXX'] = '$IPHONEPATH/usr/bin/${ios_triple}clang++'
- env['AR'] = '$IPHONEPATH/usr/bin/${ios_triple}ar'
- env['RANLIB'] = '$IPHONEPATH/usr/bin/${ios_triple}ranlib'
+ if env["target"] == "release_debug":
+ env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
+
+ elif (env["target"] == "debug"):
+ env.Append(CPPFLAGS=['-D_DEBUG', '-DDEBUG=1', '-gdwarf-2', '-O0', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+
+ ## Architecture
- import string
if (env["ios_sim"] == "yes" or env["arch"] == "x86"): # i386, simulator
env["arch"] = "x86"
env["bits"] = "32"
- env.Append(CCFLAGS=string.split('-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\\\"'))
elif (env["arch"] == "arm" or env["arch"] == "arm32" or env["arch"] == "armv7" or env["bits"] == "32"): # arm
env["arch"] = "arm"
env["bits"] = "32"
- env.Append(CCFLAGS=string.split('-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'))
else: # armv64
env["arch"] = "arm64"
env["bits"] = "64"
+
+ ## Compiler configuration
+
+ env['ENV']['PATH'] = env['IPHONEPATH'] + "/Developer/usr/bin/:" + env['ENV']['PATH']
+
+ env['CC'] = '$IPHONEPATH/usr/bin/${ios_triple}clang'
+ env['CXX'] = '$IPHONEPATH/usr/bin/${ios_triple}clang++'
+ env['AR'] = '$IPHONEPATH/usr/bin/${ios_triple}ar'
+ env['RANLIB'] = '$IPHONEPATH/usr/bin/${ios_triple}ranlib'
+ env['S_compiler'] = '$IPHONEPATH/Developer/usr/bin/gcc'
+
+ ## Compile flags
+
+ if (env["arch"] == "x86"):
+ env['IPHONEPLATFORM'] = 'iPhoneSimulator'
+ env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
+ env.Append(CCFLAGS=string.split('-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\\\"'))
+ elif (env["arch"] == "arm"):
+ env.Append(CCFLAGS=string.split('-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'))
+ elif (env["arch"] == "arm64"):
env.Append(CCFLAGS=string.split('-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=9.0 -isysroot $IPHONESDK'))
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
+ if env['ios_exceptions'] == 'yes':
+ env.Append(CPPFLAGS=['-fexceptions'])
+ else:
+ env.Append(CPPFLAGS=['-fno-exceptions'])
+
+ ## Link flags
+
if (env["arch"] == "x86"):
- env['IPHONEPLATFORM'] = 'iPhoneSimulator'
env.Append(LINKFLAGS=['-arch', 'i386', '-mios-simulator-version-min=4.3',
'-isysroot', '$IPHONESDK',
- #'-mmacosx-version-min=10.6',
'-Xlinker',
'-objc_abi_version',
'-Xlinker', '2',
- '-framework', 'AudioToolbox',
- '-framework', 'AVFoundation',
- '-framework', 'CoreAudio',
- '-framework', 'CoreGraphics',
- '-framework', 'CoreMedia',
- '-framework', 'CoreMotion',
- '-framework', 'Foundation',
- '-framework', 'Security',
- '-framework', 'UIKit',
- '-framework', 'MediaPlayer',
- '-framework', 'OpenGLES',
- '-framework', 'QuartzCore',
- '-framework', 'SystemConfiguration',
- '-framework', 'GameController',
'-F$IPHONESDK',
])
- elif (env["arch"] == "arm64"):
- env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=9.0',
- '-isysroot', '$IPHONESDK',
- #'-stdlib=libc++',
- '-framework', 'Foundation',
- '-framework', 'UIKit',
- '-framework', 'CoreGraphics',
- '-framework', 'OpenGLES',
- '-framework', 'QuartzCore',
- '-framework', 'CoreAudio',
- '-framework', 'AudioToolbox',
- '-framework', 'SystemConfiguration',
- '-framework', 'Security',
- #'-framework', 'AdSupport',
- '-framework', 'MediaPlayer',
- '-framework', 'AVFoundation',
- '-framework', 'CoreMedia',
- '-framework', 'CoreMotion',
- '-framework', 'GameController',
- ])
- else:
- env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=9.0',
- '-isysroot', '$IPHONESDK',
- '-framework', 'Foundation',
- '-framework', 'UIKit',
- '-framework', 'CoreGraphics',
- '-framework', 'OpenGLES',
- '-framework', 'QuartzCore',
- '-framework', 'CoreAudio',
- '-framework', 'AudioToolbox',
- '-framework', 'SystemConfiguration',
- '-framework', 'Security',
- #'-framework', 'AdSupport',
- '-framework', 'MediaPlayer',
- '-framework', 'AVFoundation',
- '-framework', 'CoreMedia',
- '-framework', 'CoreMotion',
- '-framework', 'GameController',
- ])
-
+ elif (env["arch"] == "arm"):
+ env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=9.0'])
+ if (env["arch"] == "arm64"):
+ env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=9.0'])
+
+ env.Append(LINKFLAGS=['-isysroot', '$IPHONESDK',
+ '-framework', 'AudioToolbox',
+ '-framework', 'AVFoundation',
+ '-framework', 'CoreAudio',
+ '-framework', 'CoreGraphics',
+ '-framework', 'CoreMedia',
+ '-framework', 'CoreMotion',
+ '-framework', 'Foundation',
+ '-framework', 'GameController',
+ '-framework', 'MediaPlayer',
+ '-framework', 'OpenGLES',
+ '-framework', 'QuartzCore',
+ '-framework', 'Security',
+ '-framework', 'SystemConfiguration',
+ '-framework', 'UIKit',
+ ])
+
+ # Feature options
if env['game_center'] == 'yes':
env.Append(CPPFLAGS=['-DGAME_CENTER_ENABLED'])
env.Append(LINKFLAGS=['-framework', 'GameKit'])
@@ -145,45 +140,20 @@ def configure(env):
if env['icloud'] == 'yes':
env.Append(CPPFLAGS=['-DICLOUD_ENABLED'])
- env.Append(CPPPATH=['$IPHONESDK/usr/include', '$IPHONESDK/System/Library/Frameworks/OpenGLES.framework/Headers', '$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers'])
+ env.Append(CPPPATH=['$IPHONESDK/usr/include',
+ '$IPHONESDK/System/Library/Frameworks/OpenGLES.framework/Headers',
+ '$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers',
+ ])
- if (env["target"].startswith("release")):
-
- env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1'])
- env.Append(CPPFLAGS=['-O2', '-flto', '-ftree-vectorize', '-fomit-frame-pointer', '-ffast-math', '-funsafe-math-optimizations'])
- env.Append(LINKFLAGS=['-O2', '-flto'])
-
- if env["target"] == "release_debug":
- env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
-
- elif (env["target"] == "debug"):
-
- env.Append(CPPFLAGS=['-D_DEBUG', '-DDEBUG=1', '-gdwarf-2', '-O0', '-DDEBUG_ENABLED'])
- env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ENABLED'])
-
- if (env["ios_sim"] == "yes"): # TODO: Check if needed?
- env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6'
env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
+
+ env.Append(CPPPATH=['#platform/iphone'])
env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DMPC_FIXED_POINT'])
# TODO: Move that to opus module's config
if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
env.opus_fixed_point = "yes"
- if env["arch"] == "x86":
- pass
- elif(env["arch"] == "arm64"):
- env.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
- else:
+ if (env["arch"] == "arm"):
env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
-
- if env['ios_exceptions'] == 'yes':
- env.Append(CPPFLAGS=['-fexceptions'])
- else:
- env.Append(CPPFLAGS=['-fno-exceptions'])
- # env['neon_enabled']=True
- env['S_compiler'] = '$IPHONEPATH/Developer/usr/bin/gcc'
-
- import methods
- env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
+ elif (env["arch"] == "arm64"):
+ env.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
new file mode 100644
index 0000000000..0960ec8791
--- /dev/null
+++ b/platform/iphone/export/export.cpp
@@ -0,0 +1,347 @@
+/*************************************************************************/
+/* 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);
+
+#ifdef OSX_ENABLED
+ if (is_execute) {
+ // we need execute rights on this file
+ chmod(file.utf8().get_data(), 0755);
+ }
+#endif
+ }
+
+ 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/javascript/detect.py b/platform/javascript/detect.py
index 41fe3fb027..68c8d1eea5 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -1,6 +1,6 @@
import os
-import sys
import string
+import sys
def is_active():
@@ -12,7 +12,8 @@ def get_name():
def can_build():
- return os.environ.has_key("EMSCRIPTEN_ROOT")
+
+ return (os.environ.has_key("EMSCRIPTEN_ROOT"))
def get_opts():
@@ -27,12 +28,12 @@ def get_flags():
return [
('tools', 'no'),
- ('module_etc1_enabled', 'no'),
('module_theora_enabled', 'no'),
]
def create(env):
+
# remove Windows' .exe suffix
return env.Clone(tools=['textfile', 'zip'], PROGSUFFIX='')
@@ -45,10 +46,26 @@ def escape_target_backslashes(target, source, env, for_signature):
def configure(env):
- env['ENV'] = os.environ
- env.Append(CPPPATH=['#platform/javascript'])
+ ## Build type
+
+ if (env["target"] == "release"):
+ env.Append(CCFLAGS=['-O3'])
+ env.Append(LINKFLAGS=['-O3'])
+ elif (env["target"] == "release_debug"):
+ env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Append(LINKFLAGS=['-O2', '-s', 'ASSERTIONS=1'])
+ # retain function names at the cost of file size, for backtraces and profiling
+ env.Append(LINKFLAGS=['--profiling-funcs'])
+
+ elif (env["target"] == "debug"):
+ env.Append(CCFLAGS=['-O1', '-D_DEBUG', '-g', '-DDEBUG_ENABLED'])
+ env.Append(LINKFLAGS=['-O1', '-g'])
+
+ ## Compiler configuration
+
+ env['ENV'] = os.environ
env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT'])
env['CC'] = 'emcc'
env['CXX'] = 'em++'
@@ -57,6 +74,7 @@ def configure(env):
# Emscripten's ar has issues with duplicate file names, so use cc
env['AR'] = 'emcc'
env['ARFLAGS'] = '-o'
+
if (os.name == 'nt'):
# use TempFileMunge on Windows since some commands get too long for
# cmd.exe even with spawn_fix
@@ -68,26 +86,20 @@ def configure(env):
env['OBJSUFFIX'] = '.bc'
env['LIBSUFFIX'] = '.bc'
- if (env["target"] == "release"):
- env.Append(CCFLAGS=['-O3'])
- env.Append(LINKFLAGS=['-O3'])
- elif (env["target"] == "release_debug"):
- env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
- env.Append(LINKFLAGS=['-O2', '-s', 'ASSERTIONS=1'])
- # retain function names at the cost of file size, for backtraces and profiling
- env.Append(LINKFLAGS=['--profiling-funcs'])
- elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['-O1', '-D_DEBUG', '-g', '-DDEBUG_ENABLED'])
- env.Append(LINKFLAGS=['-O1', '-g'])
+ ## Compile flags
- # TODO: Move that to opus module's config
- if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
- env.opus_fixed_point = "yes"
+ env.Append(CPPPATH=['#platform/javascript'])
+ env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DTYPED_METHOD_BIND', '-DNO_THREADS'])
+ env.Append(CPPFLAGS=['-DGLES3_ENABLED'])
# These flags help keep the file size down
env.Append(CPPFLAGS=["-fno-exceptions", '-DNO_SAFE_CAST', '-fno-rtti'])
- env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DTYPED_METHOD_BIND', '-DNO_THREADS'])
- env.Append(CPPFLAGS=['-DGLES3_ENABLED'])
+
+ if env['javascript_eval'] == 'yes':
+ env.Append(CPPFLAGS=['-DJAVASCRIPT_EVAL_ENABLED'])
+
+ ## Link flags
+
env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1'])
if (env['wasm'] == 'yes'):
@@ -101,8 +113,6 @@ def configure(env):
env.Append(LINKFLAGS=['-s', 'ASM_JS=1'])
env.Append(LINKFLAGS=['--separate-asm'])
- if env['javascript_eval'] == 'yes':
- env.Append(CPPFLAGS=['-DJAVASCRIPT_EVAL_ENABLED'])
-
-
- import methods
+ # TODO: Move that to opus module's config
+ if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
+ env.opus_fixed_point = "yes"
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index ea388072c5..4bdfdae39e 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -30,7 +30,8 @@
#include "editor/editor_node.h"
#include "editor_export.h"
#include "io/zip_io.h"
-#include "platform/javascript/logo.h"
+#include "platform/javascript/logo.gen.h"
+#include "platform/javascript/run_icon.gen.h"
#define EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE "webassembly_release.zip"
#define EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG "webassembly_debug.zip"
@@ -42,6 +43,8 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
GDCLASS(EditorExportPlatformJavaScript, EditorExportPlatform)
Ref<ImageTexture> logo;
+ Ref<ImageTexture> run_icon;
+ bool runnable_when_last_polled;
void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug);
void _fix_fsloader_js(Vector<uint8_t> &p_js, const String &p_pack_name, uint64_t p_pack_size);
@@ -64,10 +67,12 @@ public:
virtual String get_binary_extension() const;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
- virtual int get_device_count() const { return 1; }
+ virtual bool poll_devices();
+ virtual int get_device_count() const;
virtual String get_device_name(int p_device) const { return TTR("Run in Browser"); }
virtual String get_device_info(int p_device) const { return TTR("Run exported HTML in the system's default browser."); }
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags);
+ virtual Ref<Texture> get_run_icon() const;
EditorExportPlatformJavaScript();
};
@@ -303,6 +308,29 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
return OK;
}
+bool EditorExportPlatformJavaScript::poll_devices() {
+
+ Ref<EditorExportPreset> preset;
+
+ for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) {
+
+ Ref<EditorExportPreset> ep = EditorExport::get_singleton()->get_export_preset(i);
+ if (ep->is_runnable() && ep->get_platform() == this) {
+ preset = ep;
+ break;
+ }
+ }
+
+ bool prev = runnable_when_last_polled;
+ runnable_when_last_polled = preset.is_valid();
+ return runnable_when_last_polled != prev;
+}
+
+int EditorExportPlatformJavaScript::get_device_count() const {
+
+ return runnable_when_last_polled;
+}
+
Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
String path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmp_export.html";
@@ -314,11 +342,22 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese
return OK;
}
+Ref<Texture> EditorExportPlatformJavaScript::get_run_icon() const {
+
+ return run_icon;
+}
+
EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
Ref<Image> img = memnew(Image(_javascript_logo));
logo.instance();
logo->create_from_image(img);
+
+ img = Ref<Image>(memnew(Image(_javascript_run_icon)));
+ run_icon.instance();
+ run_icon->create_from_image(img);
+
+ runnable_when_last_polled = false;
}
void register_javascript_exporter() {
diff --git a/platform/javascript/run_icon.png b/platform/javascript/run_icon.png
new file mode 100644
index 0000000000..dedee6f479
--- /dev/null
+++ b/platform/javascript/run_icon.png
Binary files differ
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 39ee33ae82..dfefbbc1ba 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -1,4 +1,3 @@
-
import os
import sys
@@ -22,9 +21,7 @@ def can_build():
def get_opts():
return [
- ('force_64_bits', 'Force 64 bits binary', 'no'),
('osxcross_sdk', 'OSXCross SDK version', 'darwin14'),
-
]
@@ -36,36 +33,37 @@ def get_flags():
def configure(env):
- env.Append(CPPPATH=['#platform/osx'])
-
- if (env["bits"] == "default"):
- env["bits"] = "32"
+ ## Build type
if (env["target"] == "release"):
-
- env.Append(CCFLAGS=['-O2', '-ffast-math', '-fomit-frame-pointer', '-ftree-vectorize', '-msse2'])
+ env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-fomit-frame-pointer', '-ftree-vectorize', '-msse2'])
elif (env["target"] == "release_debug"):
-
- env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
elif (env["target"] == "debug"):
+ env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
- env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ ## Architecture
- if (not os.environ.has_key("OSXCROSS_ROOT")):
- # regular native build
- if (env["bits"] == "64"):
- env.Append(CCFLAGS=['-arch', 'x86_64'])
- env.Append(LINKFLAGS=['-arch', 'x86_64'])
+ is64 = sys.maxsize > 2**32
+ if (env["bits"] == "default"):
+ env["bits"] = "64" if is64 else "32"
+
+ ## Compiler configuration
+
+ if (not os.environ.has_key("OSXCROSS_ROOT")): # regular native build
+ if (env["bits"] == "fat"):
+ env.Append(CCFLAGS=['-arch', 'i386', '-arch', 'x86_64'])
+ env.Append(LINKFLAGS=['-arch', 'i386', '-arch', 'x86_64'])
elif (env["bits"] == "32"):
env.Append(CCFLAGS=['-arch', 'i386'])
env.Append(LINKFLAGS=['-arch', 'i386'])
- else:
- env.Append(CCFLAGS=['-arch', 'i386', '-arch', 'x86_64'])
- env.Append(LINKFLAGS=['-arch', 'i386', '-arch', 'x86_64'])
- else:
- # osxcross build
+ else: # 64-bit, default
+ env.Append(CCFLAGS=['-arch', 'x86_64'])
+ env.Append(LINKFLAGS=['-arch', 'x86_64'])
+
+ else: # osxcross build
root = os.environ.get("OSXCROSS_ROOT", 0)
if env["bits"] == "64":
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
@@ -78,26 +76,22 @@ def configure(env):
env['RANLIB'] = basecmd + "ranlib"
env['AS'] = basecmd + "as"
- env.Append(CPPFLAGS=["-DAPPLE_STYLE_KEYS"])
- env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DOSX_ENABLED'])
- env.Append(CPPFLAGS=["-mmacosx-version-min=10.9"])
- env.Append(LIBS=['pthread'])
- #env.Append(CPPFLAGS=['-F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-mmacosx-version-min=10.4'])
- #env.Append(LINKFLAGS=['-mmacosx-version-min=10.4', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk'])
- env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
- env.Append(LINKFLAGS=["-mmacosx-version-min=10.9"])
-
if (env["CXX"] == "clang++"):
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env["CC"] = "clang"
env["LD"] = "clang++"
- import methods
+ ## Dependencies
+
+ if (env['builtin_libtheora'] != 'no'):
+ env["x86_libtheora_opt_gcc"] = True
+
+ ## Flags
- env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
- #env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
+ env.Append(CPPPATH=['#platform/osx'])
+ env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DAPPLE_STYLE_KEYS'])
+ env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
+ env.Append(LIBS=['pthread'])
- env["x86_libtheora_opt_gcc"] = True
-
+ env.Append(CPPFLAGS=['-mmacosx-version-min=10.9'])
+ env.Append(LINKFLAGS=['-mmacosx-version-min=10.9'])
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 2033bc76a1..c81fb00b36 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -27,6 +27,7 @@
/* 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"
@@ -37,511 +38,652 @@
#include "io/zip_io.h"
#include "os/file_access.h"
#include "os/os.h"
-#include "platform/osx/logo.h"
+#include "platform/osx/logo.gen.h"
#include "string.h"
#include "version.h"
-#if 0
+#include <sys/stat.h>
class EditorExportPlatformOSX : public EditorExportPlatform {
- GDCLASS( EditorExportPlatformOSX,EditorExportPlatform );
-
- String custom_release_package;
- String custom_debug_package;
-
- enum BitsMode {
- BITS_FAT,
- BITS_64,
- BITS_32
- };
+ GDCLASS(EditorExportPlatformOSX, EditorExportPlatform);
int version_code;
- String app_name;
- String info;
- String icon;
- String identifier;
- String short_version;
- String version;
- String signature;
- String copyright;
- BitsMode bits_mode;
- bool high_resolution;
-
Ref<ImageTexture> logo;
- void _fix_plist(Vector<uint8_t>& plist, const String &p_binary);
- void _make_icon(const Image& p_icon,Vector<uint8_t>& data);
-
+ void _fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary);
+ void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
+#ifdef OSX_ENABLED
+ Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
+ Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
+#endif
protected:
-
- 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;
+ 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 "Mac OSX"; }
- virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_BC; }
virtual Ref<Texture> get_logo() const { return logo; }
-
- virtual bool poll_devices() { return false;}
- virtual int get_device_count() const { return 0; }
- virtual String get_device_name(int p_device) const { return String(); }
- virtual String get_device_info(int p_device) const { return String(); }
- virtual Error run(int p_device,int p_flags=0);
-
- virtual bool requires_password(bool p_debug) const { return false; }
+#ifdef OSX_ENABLED
+ virtual String get_binary_extension() const { return "dmg"; }
+#else
virtual String get_binary_extension() const { return "zip"; }
- virtual Error export_project(const String& p_path,bool p_debug,int p_flags=0);
+#endif
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
- virtual bool can_export(String *r_error=NULL) const;
+ virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
EditorExportPlatformOSX();
~EditorExportPlatformOSX();
};
-bool EditorExportPlatformOSX::_set(const StringName& p_name, const Variant& p_value) {
-
- String n=p_name;
-
- if (n=="custom_package/debug")
- custom_debug_package=p_value;
- else if (n=="custom_package/release")
- custom_release_package=p_value;
- else if (n=="application/name")
- app_name=p_value;
- else if (n=="application/info")
- info=p_value;
- else if (n=="application/icon")
- icon=p_value;
- else if (n=="application/identifier")
- identifier=p_value;
- else if (n=="application/signature")
- signature=p_value;
- else if (n=="application/short_version")
- short_version=p_value;
- else if (n=="application/version")
- version=p_value;
- else if (n=="application/copyright")
- copyright=p_value;
- else if (n=="application/bits_mode")
- bits_mode=BitsMode(int(p_value));
- else if (n=="display/high_res")
- high_resolution=p_value;
- else
- return false;
-
- return true;
-}
-
-bool EditorExportPlatformOSX::_get(const StringName& p_name,Variant &r_ret) const{
-
- String n=p_name;
-
- if (n=="custom_package/debug")
- r_ret=custom_debug_package;
- else if (n=="custom_package/release")
- r_ret=custom_release_package;
- else if (n=="application/name")
- r_ret=app_name;
- else if (n=="application/info")
- r_ret=info;
- else if (n=="application/icon")
- r_ret=icon;
- else if (n=="application/identifier")
- r_ret=identifier;
- else if (n=="application/signature")
- r_ret=signature;
- else if (n=="application/short_version")
- r_ret=short_version;
- else if (n=="application/version")
- r_ret=version;
- else if (n=="application/copyright")
- r_ret=copyright;
- else if (n=="application/bits_mode")
- r_ret=bits_mode;
- else if (n=="display/high_res")
- r_ret=high_resolution;
- else
- return false;
+void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
- return true;
+ // what does this need to do?
}
-void EditorExportPlatformOSX::_get_property_list( List<PropertyInfo> *p_list) const{
-
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"zip"));
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"zip"));
-
- p_list->push_back( PropertyInfo( Variant::STRING, "application/name") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/info") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/icon",PROPERTY_HINT_FILE,"png") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/identifier") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/signature") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/short_version") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/version") );
- p_list->push_back( PropertyInfo( Variant::STRING, "application/copyright") );
- p_list->push_back( PropertyInfo( Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "display/high_res") );
+void EditorExportPlatformOSX::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.macgame"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "godotmacgame"));
+ 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"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
+
+#ifdef OSX_ENABLED
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements"), ""));
+#endif
}
-void EditorExportPlatformOSX::_make_icon(const Image& p_icon,Vector<uint8_t>& icon) {
-
+void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
- Ref<ImageTexture> it = memnew( ImageTexture );
- int size=512;
+ Ref<ImageTexture> it = memnew(ImageTexture);
+ int size = 512;
Vector<uint8_t> data;
data.resize(8);
- data[0]='i';
- data[1]='c';
- data[2]='n';
- data[3]='s';
+ data[0] = 'i';
+ data[1] = 'c';
+ data[2] = 'n';
+ data[3] = 's';
- const char *name[]={"ic09","ic08","ic07","icp6","icp5","icp4"};
- int index=0;
+ const char *name[] = { "ic09", "ic08", "ic07", "icp6", "icp5", "icp4" };
+ int index = 0;
- while(size>=16) {
+ while (size >= 16) {
- Image copy = p_icon;
- copy.convert(Image::FORMAT_RGBA8);
- copy.resize(size,size);
+ Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy?
+ copy->convert(Image::FORMAT_RGBA8);
+ copy->resize(size, size);
it->create_from_image(copy);
- String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/icon.png";
- ResourceSaver::save(path,it);
+ String path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/icon.png";
+ ResourceSaver::save(path, it);
- FileAccess *f = FileAccess::open(path,FileAccess::READ);
+ FileAccess *f = FileAccess::open(path, FileAccess::READ);
ERR_FAIL_COND(!f);
int ofs = data.size();
uint32_t len = f->get_len();
- data.resize(data.size()+len+8);
- f->get_buffer(&data[ofs+8],len);
+ data.resize(data.size() + len + 8);
+ f->get_buffer(&data[ofs + 8], len);
memdelete(f);
- len+=8;
- len=BSWAP32(len);
- copymem(&data[ofs],name[index],4);
- encode_uint32(len,&data[ofs+4]);
+ len += 8;
+ len = BSWAP32(len);
+ copymem(&data[ofs], name[index], 4);
+ encode_uint32(len, &data[ofs + 4]);
index++;
- size/=2;
+ size /= 2;
}
uint32_t total_len = data.size();
total_len = BSWAP32(total_len);
- encode_uint32(total_len,&data[4]);
+ encode_uint32(total_len, &data[4]);
- icon=data;
+ p_data = data;
}
-
-void EditorExportPlatformOSX::_fix_plist(Vector<uint8_t>& plist,const String& p_binary) {
-
+void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary) {
String str;
String strnew;
- str.parse_utf8((const char*)plist.ptr(),plist.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_binary)+"\n";
- } else if (lines[i].find("$info")!=-1) {
- strnew+=lines[i].replace("$info",info)+"\n";
- } else if (lines[i].find("$identifier")!=-1) {
- strnew+=lines[i].replace("$identifier",identifier)+"\n";
- } else if (lines[i].find("$short_version")!=-1) {
- strnew+=lines[i].replace("$short_version",short_version)+"\n";
- } else if (lines[i].find("$version")!=-1) {
- strnew+=lines[i].replace("$version",version)+"\n";
- } else if (lines[i].find("$signature")!=-1) {
- strnew+=lines[i].replace("$signature",signature)+"\n";
- } else if (lines[i].find("$copyright")!=-1) {
- strnew+=lines[i].replace("$copyright",copyright)+"\n";
- } else if (lines[i].find("$highres")!=-1) {
- strnew+=lines[i].replace("$highres",high_resolution?"<true/>":"<false/>")+"\n";
+ str.parse_utf8((const char *)plist.ptr(), plist.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_binary) + "\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 if (lines[i].find("$highres") != -1) {
+ strnew += lines[i].replace("$highres", p_preset->get("display/high_res") ? "<true/>" : "<false/>") + "\n";
} else {
- strnew+=lines[i]+"\n";
+ strnew += lines[i] + "\n";
}
}
CharString cs = strnew.utf8();
- plist.resize(cs.size());
- for(int i=9;i<cs.size();i++) {
- plist[i]=cs[i];
+ plist.resize(cs.size() - 1);
+ for (int i = 0; i < cs.size() - 1; i++) {
+ plist[i] = cs[i];
}
}
-Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, int p_flags) {
+#ifdef OSX_ENABLED
+/**
+ If we're running the OSX version of the Godot editor we'll:
+ - export our application bundle to a temporary folder
+ - attempt to code sign it
+ - and then wrap it up in a DMG
+**/
+
+Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+ List<String> args;
+ if (p_preset->get("codesign/entitlements") != "") {
+ /* this should point to our entitlements.plist file that sandboxes our application, I don't know if this should also be placed in our app bundle */
+ args.push_back("-entitlements");
+ args.push_back(p_preset->get("codesign/entitlements"));
+ }
+ args.push_back("-s");
+ args.push_back(p_preset->get("codesign/identity"));
+ args.push_back("-v"); /* provide some more feedback */
+ args.push_back(p_path);
+ Error err = OS::get_singleton()->execute("/usr/bin/codesign", args, true);
+ ERR_FAIL_COND_V(err, err);
+
+ return OK;
+}
+
+Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) {
+ List<String> args;
+ args.push_back("create");
+ args.push_back(p_dmg_path);
+ args.push_back("-volname");
+ args.push_back(p_pkg_name);
+ args.push_back("-fs");
+ args.push_back("HFS+");
+ args.push_back("-srcfolder");
+ args.push_back(p_app_path_name);
+ Error err = OS::get_singleton()->execute("/usr/bin/hdiutil", args, true);
+ ERR_FAIL_COND_V(err, err);
- String src_pkg;
+ return OK;
+}
+
+Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- EditorProgress ep("export","Exporting for OSX",104);
+ String src_pkg_name;
+ EditorProgress ep("export", "Exporting for OSX", 3);
if (p_debug)
- src_pkg=custom_debug_package;
+ src_pkg_name = p_preset->get("custom_package/debug");
else
- src_pkg=custom_release_package;
+ src_pkg_name = p_preset->get("custom_package/release");
- if (src_pkg=="") {
+ if (src_pkg_name == "") {
String err;
- src_pkg=find_export_template("osx.zip", &err);
- if (src_pkg=="") {
+ src_pkg_name = find_export_template("osx.zip", &err);
+ if (src_pkg_name == "") {
EditorNode::add_io_error(err);
return ERR_FILE_NOT_FOUND;
}
}
-
- FileAccess *src_f=NULL;
+ FileAccess *src_f = NULL;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
- ep.step("Creating app",0);
+ ep.step("Creating app", 0);
- unzFile pkg = unzOpen2(src_pkg.utf8().get_data(), &io);
- if (!pkg) {
+ 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);
+ EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);
return ERR_FILE_NOT_FOUND;
}
- ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN);
- int ret = unzGoToFirstFile(pkg);
+ ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
+ int ret = unzGoToFirstFile(src_pkg_zip);
+
+ String binary_to_use = "godot_osx_" + 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 ? "64" : "32");
+
+ 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";
+
+ // We're on OSX so we can export to DMG, but first we create our application bundle
+ String tmp_app_path_name = p_path.get_base_dir() + "/" + pkg_name + ".app";
+ print_line("Exporting to " + tmp_app_path_name);
+ DirAccess *tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
+ ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE)
+
+ ///@TODO We should delete the existing application bundle especially if we attempt to code sign it, but what is a safe way to do this? Maybe call system function so it moves to trash?
+ // tmp_app_path->erase_contents_recursive();
+
+ // Create our folder structure or rely on unzip?
+ print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
+ Error dir_err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
+ ERR_FAIL_COND_V(dir_err, ERR_CANT_CREATE)
+ print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
+ dir_err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
+ ERR_FAIL_COND_V(dir_err, 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);
- zlib_filefunc_def io2=io;
- FileAccess *dst_f=NULL;
- io2.opaque=&dst_f;
- zipFile dpkg=zipOpen2(p_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io2);
+ 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("osx_template.app/", "");
+
+ if (file == "Contents/Info.plist") {
+ print_line("parse plist");
+ _fix_plist(p_preset, data, pkg_name);
+ }
+
+ if (file.begins_with("Contents/MacOS/godot_")) {
+ if (file != "Contents/MacOS/" + binary_to_use) {
+ ret = unzGoToNextFile(src_pkg_zip);
+ continue; //ignore!
+ }
+ found_binary = true;
+ is_execute = true;
+ file = "Contents/MacOS/" + pkg_name;
+ }
+
+ if (file == "Contents/Resources/icon.icns") {
+ //see if there is an icon
+ String iconpath;
+ if (p_preset->get("application/icon") != "")
+ iconpath = p_preset->get("application/icon");
+ else
+ iconpath = GlobalConfig::get_singleton()->get("application/icon");
+ print_line("icon? " + iconpath);
+ if (iconpath != "") {
+ Ref<Image> icon;
+ icon.instance();
+ icon->load(iconpath);
+ if (!icon->empty()) {
+ print_line("loaded?");
+ _make_icon(icon, data);
+ }
+ }
+ //bleh?
+ }
+
+ if (data.size() > 0) {
+ print_line("ADDING: " + file + " size: " + itos(data.size()));
+ total_size += data.size();
+
+ /* write it into our application bundle */
+ file = tmp_app_path_name + "/" + file;
+
+ /* write the file, need to add chmod */
+ FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
+ ERR_FAIL_COND_V(!f, 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);
+ } else {
+ // seems to already be set correctly
+ // chmod(file.utf8().get_data(), 0644);
+ }
+ }
+
+ 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 = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
+ Error err = save_pack(p_preset, pack_path);
+ // chmod(pack_path.utf8().get_data(), 0644);
+
+ if (err) {
+ return err;
+ }
+
+ /* see if we can code sign our new package */
+ if (p_preset->get("codesign/identity") != "") {
+ ep.step("Code signing bundle", 2);
+
+ /* the order in which we code sign is important, this is a bit of a shame or we could do this in our loop that extracts the files from our ZIP */
+
+ // start with our application
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
+ ERR_FAIL_COND_V(err, err);
+
+ ///@TODO we should check the contents of /Contents/Frameworks for frameworks to sign
+
+ // we should probably loop through all resources and sign them?
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Resources/icon.icns");
+ ERR_FAIL_COND_V(err, err);
+ err = _code_sign(p_preset, pack_path);
+ ERR_FAIL_COND_V(err, err);
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Info.plist");
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ /* and finally create a DMG */
+ ep.step("Making DMG", 3);
+ err = _create_dmg(p_path, pkg_name, tmp_app_path_name);
+ ERR_FAIL_COND_V(err, err);
+
+ return OK;
+}
+
+#else
+
+/**
+ When exporting for OSX from any other platform we don't have access to code signing or creating DMGs so we'll wrap the bundle into a zip file.
+
+ Should probably find a nicer way to have just one export method instead of duplicating the method like this but I would the code got very
+ messy with switches inside of it.
+**/
+Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+
+ String src_pkg_name;
+
+ EditorProgress ep("export", "Exporting for OSX", 104);
+
+ 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("osx.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_osx_" + String(p_debug ? "debug" : "release") + ".";
- binary_to_use += String(bits_mode==BITS_FAT ? "fat" : bits_mode==BITS_64 ? "64" : "32");
+ int bits_mode = p_preset->get("application/bits_mode");
+ binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "64" : "32");
- print_line("binary: "+binary_to_use);
+ print_line("binary: " + binary_to_use);
String pkg_name;
- if (app_name!="")
- pkg_name=app_name;
- else if (String(GlobalConfig::get_singleton()->get("application/name"))!="")
- pkg_name=String(GlobalConfig::get_singleton()->get("application/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";
+ pkg_name = "Unnamed";
+ /* Open our destination zip file */
+ zlib_filefunc_def io2 = io;
+ FileAccess *dst_f = NULL;
+ io2.opaque = &dst_f;
+ zipFile dst_pkg_zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2);
bool found_binary = false;
- while(ret==UNZ_OK) {
+ while (ret == UNZ_OK) {
//get filename
unz_file_info info;
char fname[16384];
- ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
+ ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, NULL, 0, NULL, 0);
- String file=fname;
+ String file = fname;
- print_line("READ: "+file);
+ print_line("READ: " + file);
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
//read
- unzOpenCurrentFile(pkg);
- unzReadCurrentFile(pkg,data.ptr(),data.size());
- unzCloseCurrentFile(pkg);
+ unzOpenCurrentFile(src_pkg_zip);
+ unzReadCurrentFile(src_pkg_zip, data.ptr(), data.size());
+ unzCloseCurrentFile(src_pkg_zip);
//write
- file = file.replace_first("osx_template.app/","");
+ file = file.replace_first("osx_template.app/", "");
-
- if (file=="Contents/Info.plist") {
+ if (file == "Contents/Info.plist") {
print_line("parse plist");
- _fix_plist(data,pkg_name);
+ _fix_plist(p_preset, data, pkg_name);
}
if (file.begins_with("Contents/MacOS/godot_")) {
- if (file!="Contents/MacOS/"+binary_to_use) {
- ret = unzGoToNextFile(pkg);
+ if (file != "Contents/MacOS/" + binary_to_use) {
+ ret = unzGoToNextFile(src_pkg_zip);
continue; //ignore!
}
found_binary = true;
- file="Contents/MacOS/"+pkg_name;
+ file = "Contents/MacOS/" + pkg_name;
}
- if (file=="Contents/Resources/icon.icns") {
+ if (file == "Contents/Resources/icon.icns") {
//see if there is an icon
- String iconpath = GlobalConfig::get_singleton()->get("application/icon");
- print_line("icon? "+iconpath);
- if (iconpath!="") {
- Image icon;
- icon.load(iconpath);
- if (!icon.empty()) {
+ String iconpath;
+ if (p_preset->get("application/icon") != "")
+ iconpath = p_preset->get("application/icon");
+ else
+ iconpath = GlobalConfig::get_singleton()->get("application/icon");
+ print_line("icon? " + iconpath);
+ if (iconpath != "") {
+ Ref<Image> icon;
+ icon.instance();
+ icon->load(iconpath);
+ if (!icon->empty()) {
print_line("loaded?");
- _make_icon(icon,data);
+ _make_icon(icon, data);
}
}
//bleh?
}
- file=pkg_name+".app/"+file;
+ if (data.size() > 0) {
+ print_line("ADDING: " + file + " size: " + itos(data.size()));
- if (data.size()>0) {
- print_line("ADDING: "+file+" size: "+itos(data.size()));
+ /* add it to our zip file */
+ file = pkg_name + ".app/" + file;
zip_fileinfo fi;
- fi.tmz_date.tm_hour=info.tmu_date.tm_hour;
- fi.tmz_date.tm_min=info.tmu_date.tm_min;
- fi.tmz_date.tm_sec=info.tmu_date.tm_sec;
- fi.tmz_date.tm_mon=info.tmu_date.tm_mon;
- fi.tmz_date.tm_mday=info.tmu_date.tm_mday;
- fi.tmz_date.tm_year=info.tmu_date.tm_year;
- fi.dosDate=info.dosDate;
- fi.internal_fa=info.internal_fa;
- fi.external_fa=info.external_fa;
-
- int err = zipOpenNewFileInZip(dpkg,
- file.utf8().get_data(),
- &fi,
- NULL,
- 0,
- NULL,
- 0,
- NULL,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- print_line("OPEN ERR: "+itos(err));
- err = zipWriteInFileInZip(dpkg,data.ptr(),data.size());
- print_line("WRITE ERR: "+itos(err));
- zipCloseFileInZip(dpkg);
+ fi.tmz_date.tm_hour = info.tmu_date.tm_hour;
+ fi.tmz_date.tm_min = info.tmu_date.tm_min;
+ fi.tmz_date.tm_sec = info.tmu_date.tm_sec;
+ fi.tmz_date.tm_mon = info.tmu_date.tm_mon;
+ fi.tmz_date.tm_mday = info.tmu_date.tm_mday;
+ fi.tmz_date.tm_year = info.tmu_date.tm_year;
+ fi.dosDate = info.dosDate;
+ fi.internal_fa = info.internal_fa;
+ fi.external_fa = info.external_fa;
+
+ int err = zipOpenNewFileInZip(dst_pkg_zip,
+ file.utf8().get_data(),
+ &fi,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
+
+ print_line("OPEN ERR: " + itos(err));
+ err = zipWriteInFileInZip(dst_pkg_zip, data.ptr(), data.size());
+ print_line("WRITE ERR: " + itos(err));
+ zipCloseFileInZip(dst_pkg_zip);
}
- ret = unzGoToNextFile(pkg);
+ ret = unzGoToNextFile(src_pkg_zip);
}
if (!found_binary) {
- ERR_PRINTS("Requested template binary '"+binary_to_use+"' not found. It might be missing from your template archive.");
- zipClose(dpkg,NULL);
- unzClose(pkg);
+ ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive.");
+ zipClose(dst_pkg_zip, NULL);
+ unzClose(src_pkg_zip);
return ERR_FILE_NOT_FOUND;
}
+ ep.step("Making PKG", 1);
- ep.step("Making PKG",1);
-
- String pack_path=EditorSettings::get_singleton()->get_settings_path()+"/tmp/data.pck";
- FileAccess *pfs = FileAccess::open(pack_path,FileAccess::WRITE);
- Error err = save_pack(pfs);
- memdelete(pfs);
+ String pack_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/" + pkg_name + ".pck";
+ Error err = save_pack(p_preset, pack_path);
if (err) {
- zipClose(dpkg,NULL);
- unzClose(pkg);
+ zipClose(dst_pkg_zip, NULL);
+ unzClose(src_pkg_zip);
return err;
-
}
{
//write datapack
- zipOpenNewFileInZip(dpkg,
- (pkg_name+".app/Contents/Resources/data.pck").utf8().get_data(),
- NULL,
- NULL,
- 0,
- NULL,
- 0,
- NULL,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
+ zipOpenNewFileInZip(dst_pkg_zip,
+ (pkg_name + ".app/Contents/Resources/" + pkg_name + ".pck").utf8().get_data(),
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
- FileAccess *pf = FileAccess::open(pack_path,FileAccess::READ);
- ERR_FAIL_COND_V(!pf,ERR_CANT_OPEN);
+ FileAccess *pf = FileAccess::open(pack_path, FileAccess::READ);
+ ERR_FAIL_COND_V(!pf, ERR_CANT_OPEN);
const int BSIZE = 16384;
uint8_t buf[BSIZE];
- while(true) {
+ while (true) {
- int r = pf->get_buffer(buf,BSIZE);
- if (r<=0)
+ int r = pf->get_buffer(buf, BSIZE);
+ if (r <= 0)
break;
- zipWriteInFileInZip(dpkg,buf,r);
-
+ zipWriteInFileInZip(dst_pkg_zip, buf, r);
}
- zipCloseFileInZip(dpkg);
+ zipCloseFileInZip(dst_pkg_zip);
memdelete(pf);
-
}
- zipClose(dpkg,NULL);
- unzClose(pkg);
+ zipClose(dst_pkg_zip, NULL);
+ unzClose(src_pkg_zip);
return OK;
}
+#endif
+bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
-Error EditorExportPlatformOSX::run(int p_device, int p_flags) {
-
- return OK;
-}
-
-
-EditorExportPlatformOSX::EditorExportPlatformOSX() {
-
- Image img( _osx_logo );
- logo = Ref<ImageTexture>( memnew( ImageTexture ));
- logo->create_from_image(img);
-
- info="Made with Godot Engine";
- identifier="org.godotengine.macgame";
- signature="godotmacgame";
- short_version="1.0";
- version="1.0";
- bits_mode=BITS_FAT;
- high_resolution=false;
-
-}
-
-bool EditorExportPlatformOSX::can_export(String *r_error) const {
-
-
- bool valid=true;
+ bool valid = true;
String err;
- if (!exists_export_template("osx.zip")) {
- valid=false;
- err+="No export templates found.\nDownload and install export templates.\n";
+ if (!exists_export_template("osx.zip", &err)) {
+ valid = false;
}
- if (custom_debug_package!="" && !FileAccess::exists(custom_debug_package)) {
- valid=false;
- err+="Custom debug package not found.\n";
+ 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 (custom_release_package!="" && !FileAccess::exists(custom_release_package)) {
- valid=false;
- err+="Custom release 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 (r_error)
- *r_error=err;
+ if (!err.empty())
+ r_error = err;
return valid;
}
+EditorExportPlatformOSX::EditorExportPlatformOSX() {
-EditorExportPlatformOSX::~EditorExportPlatformOSX() {
+ Ref<Image> img = memnew(Image(_osx_logo));
+ logo.instance();
+ logo->create_from_image(img);
+}
+EditorExportPlatformOSX::~EditorExportPlatformOSX() {
}
-#endif
void register_osx_exporter() {
-#if 0
- Ref<EditorExportPlatformOSX> exporter = Ref<EditorExportPlatformOSX>( memnew(EditorExportPlatformOSX) );
- EditorImportExport::get_singleton()->add_export_platform(exporter);
-#endif
+ Ref<EditorExportPlatformOSX> platform;
+ platform.instance();
+
+ EditorExport::get_singleton()->add_export_platform(platform);
}
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 123816b22d..a3036b1a8a 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -96,6 +96,7 @@ public:
CursorShape cursor_shape;
MouseMode mouse_mode;
+ String title;
bool minimized;
bool maximized;
bool zoomed;
@@ -116,6 +117,8 @@ public:
return 1.0;
}
+ void _update_window();
+
float display_scale;
protected:
@@ -200,6 +203,9 @@ public:
virtual void request_attention();
virtual String get_joy_guid(int p_device) const;
+ virtual void set_borderless_window(int p_borderless);
+ virtual bool get_borderless_window();
+
virtual PowerState get_power_state();
virtual int get_power_seconds_left();
virtual int get_power_percent_left();
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 1070de724b..87c25a5356 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -53,6 +53,10 @@
#include <sys/types.h>
#include <unistd.h>
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
+#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
+#endif
+
static NSRect convertRectToBacking(NSRect contentRect) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
@@ -813,7 +817,13 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
// Don't use accumulation buffer support; it's not accelerated
// Aux buffers probably aren't accelerated either
- unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | (p_desired.resizable ? NSResizableWindowMask : 0);
+ unsigned int styleMask;
+
+ if (p_desired.borderless_window) {
+ styleMask = NSWindowStyleMaskBorderless;
+ } else {
+ styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | (p_desired.resizable ? NSResizableWindowMask : 0);
+ }
window_object = [[GodotWindow alloc]
initWithContentRect:NSMakeRect(0, 0, p_desired.width, p_desired.height)
@@ -911,6 +921,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
[NSApp activateIgnoringOtherApps:YES];
+ _update_window();
+
[window_object makeKeyAndOrderFront:nil];
if (p_desired.fullscreen)
@@ -970,7 +982,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
displayScale = [[screenArray objectAtIndex:i] backingScaleFactor];
}
- NSRect nsrect = [[screenArray objectAtIndex:i] visibleFrame];
+ // Note: Use frame to get the whole screen size
+ NSRect nsrect = [[screenArray objectAtIndex:i] frame];
Rect2 rect = Rect2(nsrect.origin.x, nsrect.origin.y, nsrect.size.width, nsrect.size.height);
rect.position *= displayScale;
rect.size *= displayScale;
@@ -1125,6 +1138,7 @@ int OS_OSX::get_mouse_button_state() const {
}
void OS_OSX::set_window_title(const String &p_title) {
+ title = p_title;
[window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]];
}
@@ -1288,6 +1302,31 @@ Size2 OS_OSX::get_screen_size(int p_screen) const {
return screens[p_screen].size;
};
+void OS_OSX::_update_window() {
+ bool borderless_full = false;
+
+ if (get_borderless_window()) {
+ NSRect frameRect = [window_object frame];
+ NSRect screenRect = [[window_object screen] frame];
+
+ // Check if our window covers up the screen
+ if (frameRect.origin.x <= screenRect.origin.x && frameRect.origin.y <= frameRect.origin.y &&
+ frameRect.size.width >= screenRect.size.width && frameRect.size.height >= screenRect.size.height) {
+ borderless_full = true;
+ }
+ }
+
+ if (borderless_full) {
+ // If the window covers up the screen set the level to above the main menu and hide on deactivate
+ [window_object setLevel:NSMainMenuWindowLevel + 1];
+ [window_object setHidesOnDeactivate:YES];
+ } else {
+ // Reset these when our window is not a borderless window that covers up the screen
+ [window_object setLevel:NSNormalWindowLevel];
+ [window_object setHidesOnDeactivate:NO];
+ }
+}
+
Point2 OS_OSX::get_window_position() const {
Size2 wp([window_object frame].origin.x, [window_object frame].origin.y);
@@ -1300,6 +1339,8 @@ void OS_OSX::set_window_position(const Point2 &p_position) {
Point2 size = p_position;
size /= display_scale;
[window_object setFrame:NSMakeRect(size.x, size.y, [window_object frame].size.width, [window_object frame].size.height) display:YES];
+
+ _update_window();
};
Size2 OS_OSX::get_window_size() const {
@@ -1311,17 +1352,22 @@ void OS_OSX::set_window_size(const Size2 p_size) {
Size2 size = p_size;
- // NSRect used by setFrame includes the title bar, so add it to our size.y
- CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
- if (menuBarHeight != 0.f) {
- size.y += menuBarHeight;
+ if (get_borderless_window() == false) {
+ // NSRect used by setFrame includes the title bar, so add it to our size.y
+ CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
+ if (menuBarHeight != 0.f) {
+ size.y += menuBarHeight;
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101104
- } else {
- size.y += [[NSStatusBar systemStatusBar] thickness];
+ } else {
+ size.y += [[NSStatusBar systemStatusBar] thickness];
#endif
+ }
}
+
NSRect frame = [window_object frame];
[window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, size.x, size.y) display:YES];
+
+ _update_window();
};
void OS_OSX::set_window_fullscreen(bool p_enabled) {
@@ -1403,6 +1449,35 @@ void OS_OSX::request_attention() {
[NSApp requestUserAttention:NSCriticalRequest];
}
+void OS_OSX::set_borderless_window(int p_borderless) {
+
+ // OrderOut prevents a lose focus bug with the window
+ [window_object orderOut:nil];
+
+ if (p_borderless) {
+ [window_object setStyleMask:NSWindowStyleMaskBorderless];
+ } else {
+ [window_object setStyleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask];
+
+ // Force update of the window styles
+ NSRect frameRect = [window_object frame];
+ [window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
+ [window_object setFrame:frameRect display:NO];
+
+ // Restore the window title
+ [window_object setTitle:[NSString stringWithUTF8String:title.utf8().get_data()]];
+ }
+
+ _update_window();
+
+ [window_object makeKeyAndOrderFront:nil];
+}
+
+bool OS_OSX::get_borderless_window() {
+
+ return [window_object styleMask] == NSWindowStyleMaskBorderless;
+}
+
String OS_OSX::get_executable_path() const {
int ret;
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 32f3c55135..2bb4b59e94 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -1,4 +1,3 @@
-
import os
import sys
@@ -13,17 +12,16 @@ def get_name():
def can_build():
- if (os.name != "posix"):
+ if (os.name != "posix" or sys.platform == "darwin"):
return False
- return True # enabled
+ return True
def get_opts():
return [
- ('use_llvm', 'Use llvm compiler', 'no'),
- ('force_32_bits', 'Force 32 bits binary', 'no')
+ ('use_llvm', 'Use the LLVM compiler', 'no'),
]
@@ -35,46 +33,59 @@ def get_flags():
def configure(env):
- env.Append(CPPPATH=['#platform/server'])
- if (env["use_llvm"] == "yes"):
- env["CC"] = "clang"
- env["CXX"] = "clang++"
- env["LD"] = "clang++"
-
- is64 = sys.maxsize > 2**32
-
- if (env["bits"] == "default"):
- if (is64):
- env["bits"] = "64"
- else:
- env["bits"] = "32"
-
- # if (env["tools"]=="no"):
- # #no tools suffix
- # env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
- # env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
+ ## Build type
if (env["target"] == "release"):
-
env.Append(CCFLAGS=['-O2', '-ffast-math', '-fomit-frame-pointer'])
elif (env["target"] == "release_debug"):
-
env.Append(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
elif (env["target"] == "debug"):
-
env.Append(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ ## Architecture
+
+ is64 = sys.maxsize > 2**32
+ if (env["bits"] == "default"):
+ env["bits"] = "64" if is64 else "32"
+
+ ## Compiler configuration
+
+ if (env["use_llvm"] == "yes"):
+ if ('clang++' not in env['CXX']):
+ env["CC"] = "clang"
+ env["CXX"] = "clang++"
+ env["LD"] = "clang++"
+ env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
+ env.extra_suffix = ".llvm" + env.extra_suffix
+
+ ## Dependencies
- # Shared libraries, when requested
+ # FIXME: Check for existence of the libs before parsing their flags with pkg-config
if (env['builtin_openssl'] == 'no'):
+ # Currently not compatible with OpenSSL 1.1.0+
+ # https://github.com/godotengine/godot/issues/8624
+ import subprocess
+ openssl_version = subprocess.check_output(['pkg-config', 'openssl', '--modversion']).strip('\n')
+ if (openssl_version >= "1.1.0"):
+ print("Error: Found system-installed OpenSSL %s, currently only supporting version 1.0.x." % openssl_version)
+ print("Aborting.. You can compile with 'builtin_openssl=yes' to use the bundled version.\n")
+ sys.exit(255)
+
env.ParseConfig('pkg-config openssl --cflags --libs')
if (env['builtin_libwebp'] == 'no'):
env.ParseConfig('pkg-config libwebp --cflags --libs')
+ # freetype depends on libpng and zlib, so bundling one of them while keeping others
+ # as shared libraries leads to weird issues
+ if (env['builtin_freetype'] == 'yes' or env['builtin_libpng'] == 'yes' or env['builtin_zlib'] == 'yes'):
+ env['builtin_freetype'] = 'yes'
+ env['builtin_libpng'] = 'yes'
+ env['builtin_zlib'] = 'yes'
+
if (env['builtin_freetype'] == 'no'):
env.ParseConfig('pkg-config freetype2 --cflags --libs')
@@ -109,11 +120,12 @@ def configure(env):
if (env['builtin_libogg'] == 'no'):
env.ParseConfig('pkg-config ogg --cflags --libs')
+ ## Flags
- env.Append(CPPFLAGS=['-DSERVER_ENABLED', '-DUNIX_ENABLED'])
- env.Append(LIBS=['pthread', 'z']) # TODO detect linux/BSD!
+ # Linkflags below this line should typically stay the last ones
+ if (env['builtin_zlib'] == 'no'):
+ env.ParseConfig('pkg-config zlib --cflags --libs')
- if (env["CXX"] == "clang++"):
- env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
- env["CC"] = "clang"
- env["LD"] = "clang++"
+ env.Append(CPPPATH=['#platform/server'])
+ env.Append(CPPFLAGS=['-DSERVER_ENABLED', '-DUNIX_ENABLED'])
+ env.Append(LIBS=['pthread'])
diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py
index baff7f9788..ca469d0056 100644
--- a/platform/uwp/detect.py
+++ b/platform/uwp/detect.py
@@ -1,8 +1,7 @@
+import methods
import os
-
-import sys
import string
-import methods
+import sys
def is_active():
@@ -26,7 +25,9 @@ def can_build():
def get_opts():
- return []
+
+ return [
+ ]
def get_flags():
@@ -39,16 +40,36 @@ def get_flags():
def configure(env):
- if(env["bits"] != "default"):
- print "Error: bits argument is disabled for MSVC"
- print ("Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings)"
- + " that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits argument (example: scons p=uwp) and SCons will attempt to detect what MSVC compiler"
- + " will be executed and inform you.")
+ if (env["bits"] != "default"):
+ print("Error: bits argument is disabled for MSVC")
+ print("""
+ Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console
+ (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits
+ argument (example: scons p=uwp) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
+ """)
sys.exit()
- arch = ""
- env['ENV'] = os.environ
+ ## Build type
+
+ if (env["target"] == "release"):
+ env.Append(CPPFLAGS=['/O2', '/GL'])
+ env.Append(CPPFLAGS=['/MD'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS', '/LTCG'])
+
+ elif (env["target"] == "release_debug"):
+ env.Append(CCFLAGS=['/O2', '/Zi', '/DDEBUG_ENABLED'])
+ env.Append(CPPFLAGS=['/MD'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+
+ elif (env["target"] == "debug"):
+ env.Append(CCFLAGS=['/Zi', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED'])
+ env.Append(CPPFLAGS=['/MDd'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+ env.Append(LINKFLAGS=['/DEBUG'])
+
+ ## Compiler configuration
+ env['ENV'] = os.environ
vc_base_path = os.environ['VCTOOLSINSTALLDIR'] if "VCTOOLSINSTALLDIR" in os.environ else os.environ['VCINSTALLDIR']
# ANGLE
@@ -60,9 +81,12 @@ def configure(env):
if os.path.isfile(str(os.getenv("ANGLE_SRC_PATH")) + "/winrt/10/src/angle.sln"):
env["build_angle"] = True
+ ## Architecture
+
+ arch = ""
if os.getenv('Platform') == "ARM":
- print "Compiled program architecture will be an ARM executable. (forcing bits=32)."
+ print("Compiled program architecture will be an ARM executable. (forcing bits=32).")
arch = "arm"
env["bits"] = "32"
@@ -74,17 +98,16 @@ def configure(env):
env.Append(LIBPATH=[angle_root + '/winrt/10/src/Release_ARM/lib'])
else:
-
compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV'])
if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"):
env["bits"] = "64"
- print "Compiled program architecture will be a x64 executable (forcing bits=64)."
+ print("Compiled program architecture will be a x64 executable (forcing bits=64).")
elif (compiler_version_str == "x86" or compiler_version_str == "amd64_x86"):
env["bits"] = "32"
- print "Compiled program architecture will be a x86 executable. (forcing bits=32)."
+ print("Compiled program architecture will be a x86 executable. (forcing bits=32).")
else:
- print "Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup."
+ print("Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup.")
env["bits"] = "32"
if (env["bits"] == "32"):
@@ -106,48 +129,30 @@ def configure(env):
env.Append(LIBPATH=[os.environ['VCINSTALLDIR'] + 'lib/store/amd64'])
env.Append(LIBPATH=[angle_root + '/winrt/10/src/Release_x64/lib'])
- env.Append(CPPPATH=['#platform/uwp', '#drivers/windows'])
- env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', '/WINMD', '/APPCONTAINER', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1', '/NODEFAULTLIB:"kernel32.lib"', '/NODEFAULTLIB:"ole32.lib"'])
- env.Append(CPPFLAGS=['/D', '__WRL_NO_DEFAULT_LIB__', '/D', 'WIN32'])
-
- env.Append(CPPFLAGS=['/AI', vc_base_path + 'lib/store/references'])
- env.Append(CPPFLAGS=['/AI', vc_base_path + 'lib/x86/store/references'])
-
- if (env["target"] == "release"):
-
- env.Append(CPPFLAGS=['/O2', '/GL'])
- env.Append(CPPFLAGS=['/MD'])
- env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS', '/LTCG'])
+ env["PROGSUFFIX"] = "." + arch + env["PROGSUFFIX"]
+ env["OBJSUFFIX"] = "." + arch + env["OBJSUFFIX"]
+ env["LIBSUFFIX"] = "." + arch + env["LIBSUFFIX"]
- elif (env["target"] == "release_debug"):
+ ## Compile flags
- env.Append(CCFLAGS=['/O2', '/Zi', '/DDEBUG_ENABLED'])
- env.Append(CPPFLAGS=['/MD'])
- env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+ env.Append(CPPPATH=['#platform/uwp', '#drivers/windows'])
+ env.Append(CCFLAGS=['/DUWP_ENABLED', '/DWINDOWS_ENABLED', '/DTYPED_METHOD_BIND'])
+ env.Append(CCFLAGS=['/DGLES2_ENABLED', '/DGL_GLEXT_PROTOTYPES', '/DEGL_EGLEXT_PROTOTYPES', '/DANGLE_ENABLED'])
+ winver = "0x0602" # Windows 8 is the minimum target for UWP build
+ env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
- elif (env["target"] == "debug"):
+ env.Append(CPPFLAGS=['/D', '__WRL_NO_DEFAULT_LIB__', '/D', 'WIN32'])
- env.Append(CCFLAGS=['/Zi', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED'])
- env.Append(CPPFLAGS=['/MDd'])
- env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
- env.Append(LINKFLAGS=['/DEBUG'])
+ env.Append(CPPFLAGS=['/AI', vc_base_path + 'lib/store/references'])
+ env.Append(CPPFLAGS=['/AI', vc_base_path + 'lib/x86/store/references'])
env.Append(CCFLAGS=string.split('/FS /MP /GS /wd"4453" /wd"28204" /wd"4291" /Zc:wchar_t /Gm- /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo'))
env.Append(CXXFLAGS=string.split('/ZW /FS'))
env.Append(CCFLAGS=['/AI', vc_base_path + '\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR'] + '\\References\\CommonConfiguration\\Neutral'])
- env["PROGSUFFIX"] = "." + arch + env["PROGSUFFIX"]
- env["OBJSUFFIX"] = "." + arch + env["OBJSUFFIX"]
- env["LIBSUFFIX"] = "." + arch + env["LIBSUFFIX"]
-
- env.Append(CCFLAGS=['/DUWP_ENABLED'])
- env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
- env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
-
- env.Append(CCFLAGS=['/DGLES2_ENABLED', '/DGL_GLEXT_PROTOTYPES', '/DEGL_EGLEXT_PROTOTYPES', '/DANGLE_ENABLED'])
+ ## Link flags
- winver = "0x0602" # Windows 8 is the minimum target for UWP build
- env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
+ env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', '/WINMD', '/APPCONTAINER', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1', '/NODEFAULTLIB:"kernel32.lib"', '/NODEFAULTLIB:"ole32.lib"'])
LIBS = [
'WindowsApp',
@@ -164,8 +169,3 @@ def configure(env):
env['BUILDERS']['Program'] = methods.precious_program
env.Append(BUILDERS={'ANGLE': env.Builder(action=angle_build_cmd)})
-
- env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'HLSL9': env.Builder(action=methods.build_hlsl_dx9_headers, suffix='hlsl.h', src_suffix='.hlsl')})
- env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 5e56c1db49..a2bc5a11ab 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -1,104 +1,7 @@
-#
-# tested on | Windows native | Linux cross-compilation
-# ----------------------------+-------------------+---------------------------
-# Visual C++ Build Tools 2015 | WORKS | n/a
-# MSVS C++ 2010 Express | WORKS | n/a
-# Mingw-w64 | WORKS | WORKS
-# Mingw-w32 | WORKS | WORKS
-# MinGW | WORKS | untested
-#
-#####
-# Note about Visual C++ Build Tools :
-#
-# - Visual C++ Build Tools is the standalone MSVC compiler :
-# http://landinghub.visualstudio.com/visual-cpp-build-tools
-#
-#####
-# Notes about MSVS C++ :
-#
-# - MSVC2010-Express compiles to 32bits only.
-#
-#####
-# Notes about Mingw-w64 and Mingw-w32 under Windows :
-#
-# - both can be installed using the official installer :
-# http://mingw-w64.sourceforge.net/download.php#mingw-builds
-#
-# - if you want to compile both 32bits and 64bits, don't forget to
-# run the installer twice to install them both.
-#
-# - install them into a path that does not contain spaces
-# ( example : "C:/Mingw-w32", "C:/Mingw-w64" )
-#
-# - if you want to compile faster using the "-j" option, don't forget
-# to install the appropriate version of the Pywin32 python extension
-# available from : http://sourceforge.net/projects/pywin32/files/
-#
-# - before running scons, you must add into the environment path
-# the path to the "/bin" directory of the Mingw version you want
-# to use :
-#
-# set PATH=C:/Mingw-w32/bin;%PATH%
-#
-# - then, scons should be able to detect gcc.
-# - Mingw-w32 only compiles 32bits.
-# - Mingw-w64 only compiles 64bits.
-#
-# - it is possible to add them both at the same time into the PATH env,
-# if you also define the MINGW32_PREFIX and MINGW64_PREFIX environment
-# variables.
-# For instance, you could store that set of commands into a .bat script
-# that you would run just before scons :
-#
-# set PATH=C:\mingw-w32\bin;%PATH%
-# set PATH=C:\mingw-w64\bin;%PATH%
-# set MINGW32_PREFIX=C:\mingw-w32\bin\
-# set MINGW64_PREFIX=C:\mingw-w64\bin\
-#
-#####
-# Notes about Mingw, Mingw-w64 and Mingw-w32 under Linux :
-#
-# - default toolchain prefixes are :
-# "i586-mingw32msvc-" for MinGW
-# "i686-w64-mingw32-" for Mingw-w32
-# "x86_64-w64-mingw32-" for Mingw-w64
-#
-# - if both MinGW and Mingw-w32 are installed on your system
-# Mingw-w32 should take the priority over MinGW.
-#
-# - it is possible to manually override prefixes by defining
-# the MINGW32_PREFIX and MINGW64_PREFIX environment variables.
-#
-#####
-# Notes about Mingw under Windows :
-#
-# - this is the MinGW version from http://mingw.org/
-# - install it into a path that does not contain spaces
-# ( example : "C:/MinGW" )
-# - several DirectX headers might be missing. You can copy them into
-# the C:/MinGW/include" directory from this page :
-# https://code.google.com/p/mingw-lib/source/browse/trunk/working/avcodec_to_widget_5/directx_include/
-# - before running scons, add the path to the "/bin" directory :
-# set PATH=C:/MinGW/bin;%PATH%
-# - scons should be able to detect gcc.
-#
-
-#####
-# TODO :
-#
-# - finish to cleanup this script to remove all the remains of previous hacks and workarounds
-# - make it work with the Windows7 SDK that is supposed to enable 64bits compilation for MSVC2010-Express
-# - confirm it works well with other Visual Studio versions.
-# - update the wiki about the pywin32 extension required for the "-j" option under Windows.
-# - update the wiki to document MINGW32_PREFIX and MINGW64_PREFIX
-#
-
+import methods
import os
-
import sys
-import methods
-
def is_active():
return True
@@ -115,7 +18,7 @@ def can_build():
if (os.getenv("VCINSTALLDIR")):
return True
else:
- print("\nMSVC not detected, attempting Mingw.")
+ print("\nMSVC not detected, attempting MinGW.")
mingw32 = ""
mingw64 = ""
if (os.getenv("MINGW32_PREFIX")):
@@ -126,7 +29,7 @@ def can_build():
test = "gcc --version > NUL 2>&1"
if os.system(test) != 0 and os.system(mingw32 + test) != 0 and os.system(mingw64 + test) != 0:
print("- could not detect gcc.")
- print("Please, make sure a path to a Mingw /bin directory is accessible into the environment PATH.\n")
+ print("Please, make sure a path to a MinGW /bin directory is accessible into the environment PATH.\n")
return False
else:
print("- gcc detected.")
@@ -172,8 +75,8 @@ def get_opts():
mingw64 = os.getenv("MINGW64_PREFIX")
return [
- ('mingw_prefix', 'Mingw Prefix', mingw32),
- ('mingw_prefix_64', 'Mingw Prefix 64 bits', mingw64),
+ ('mingw_prefix', 'MinGW Prefix', mingw32),
+ ('mingw_prefix_64', 'MinGW Prefix 64 bits', mingw64),
]
@@ -211,55 +114,86 @@ def configure(env):
# Targeted Windows version: Vista (and later)
winver = "0x0600" # Windows Vista is the minimum target for windows builds
- env['is_mingw'] = False
- if (os.name == "nt" and os.getenv("VCINSTALLDIR")):
- # build using visual studio
+ if (os.name == "nt" and os.getenv("VCINSTALLDIR")): # MSVC
+
env['ENV']['TMP'] = os.environ['TMP']
- env.Append(CPPPATH=['#platform/windows/include'])
- env.Append(LIBPATH=['#platform/windows/lib'])
- env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
- if (env["target"] == "release"):
+ ## Build type
+ if (env["target"] == "release"):
env.Append(CCFLAGS=['/O2'])
env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
elif (env["target"] == "release_debug"):
-
env.Append(CCFLAGS=['/O2', '/DDEBUG_ENABLED'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
- elif (env["target"] == "debug_release"):
+ elif (env["target"] == "debug_release"):
env.Append(CCFLAGS=['/Z7', '/Od'])
env.Append(LINKFLAGS=['/DEBUG'])
env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
elif (env["target"] == "debug"):
-
env.Append(CCFLAGS=['/Z7', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED', '/DD3D_DEBUG_INFO', '/Od'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
env.Append(LINKFLAGS=['/DEBUG'])
- env.Append(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo'])
+ ## Architecture
+
+ # Note: this detection/override code from here onward should be here instead of in SConstruct because it's platform and compiler specific (MSVC/Windows)
+ if (env["bits"] != "default"):
+ print("Error: bits argument is disabled for MSVC")
+ print("""
+ Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console
+ (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits
+ argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
+ """)
+ sys.exit()
+
+ # Forcing bits argument because MSVC does not have a flag to set this through SCons... it's different compilers (cl.exe's) called from the proper command prompt
+ # that decide the architecture that is build for. Scons can only detect the os.getenviron (because vsvarsall.bat sets a lot of stuff for cl.exe to work with)
+ env["bits"] = "32"
+ env["x86_libtheora_opt_vc"] = True
+
+ ## Compiler configuration
+
+ env['ENV'] = os.environ
+ # This detection function needs the tools env (that is env['ENV'], not SCons's env), and that is why it's this far bellow in the code
+ compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV'])
+
+ print("Detected MSVC compiler: " + compiler_version_str)
+ # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writting)... vc compiler for 64bit can not compile _asm
+ if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"):
+ env["bits"] = "64"
+ env["x86_libtheora_opt_vc"] = False
+ print("Compiled program architecture will be a 64 bit executable (forcing bits=64).")
+ elif (compiler_version_str == "x86" or compiler_version_str == "amd64_x86"):
+ print("Compiled program architecture will be a 32 bit executable. (forcing bits=32).")
+ else:
+ print("Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup.")
+
+ ## Compile flags
+
+ env.Append(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo'])
env.Append(CXXFLAGS=['/TP'])
env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
env.Append(CCFLAGS=['/I' + os.getenv("WindowsSdkDir") + "/Include"])
+
env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
+ env.Append(CCFLAGS=['/DOPENGL_ENABLED'])
env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
- env.Append(CCFLAGS=['/DWIN32'])
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
+ env.Append(CCFLAGS=['/DWIN32'])
+ env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
+ if env["bits"] == "64":
+ env.Append(CCFLAGS=['/D_WIN64'])
- env.Append(CCFLAGS=['/DOPENGL_ENABLED'])
LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32', 'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32', 'shell32', 'advapi32', 'dinput8', 'dxguid']
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"])
- if (os.getenv("DXSDK_DIR")):
- DIRECTX_PATH = os.getenv("DXSDK_DIR")
- else:
- DIRECTX_PATH = "C:/Program Files/Microsoft DirectX SDK (March 2009)"
if (os.getenv("VCINSTALLDIR")):
VC_PATH = os.getenv("VCINSTALLDIR")
@@ -268,51 +202,37 @@ def configure(env):
env.Append(CCFLAGS=["/I" + p for p in os.getenv("INCLUDE").split(";")])
env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
- env.Append(CCFLAGS=["/I" + DIRECTX_PATH + "/Include"])
- env.Append(LIBPATH=[DIRECTX_PATH + "/Lib/x86"])
- env['ENV'] = os.environ
-
- # This detection function needs the tools env (that is env['ENV'], not SCons's env), and that is why it's this far bellow in the code
- compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV'])
-
- # Note: this detection/override code from here onward should be here instead of in SConstruct because it's platform and compiler specific (MSVC/Windows)
- if(env["bits"] != "default"):
- print "Error: bits argument is disabled for MSVC"
- print ("Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings)"
- + " that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler"
- + " will be executed and inform you.")
- sys.exit()
-
- # Forcing bits argument because MSVC does not have a flag to set this through SCons... it's different compilers (cl.exe's) called from the proper command prompt
- # that decide the architecture that is build for. Scons can only detect the os.getenviron (because vsvarsall.bat sets a lot of stuff for cl.exe to work with)
- env["bits"] = "32"
- env["x86_libtheora_opt_vc"] = True
-
- print "Detected MSVC compiler: " + compiler_version_str
- # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writting)... vc compiler for 64bit can not compile _asm
- if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"):
- env["bits"] = "64"
- env["x86_libtheora_opt_vc"] = False
- print "Compiled program architecture will be a 64 bit executable (forcing bits=64)."
- elif (compiler_version_str == "x86" or compiler_version_str == "amd64_x86"):
- print "Compiled program architecture will be a 32 bit executable. (forcing bits=32)."
- else:
- print "Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup."
- if env["bits"] == "64":
- env.Append(CCFLAGS=['/D_WIN64'])
# Incremental linking fix
env['BUILDERS']['ProgramOriginal'] = env['BUILDERS']['Program']
env['BUILDERS']['Program'] = methods.precious_program
- else:
+ else: # MinGW
# Workaround for MinGW. See:
# http://www.scons.org/wiki/LongCmdLinesOnWin32
env.use_windows_spawn_fix()
- # build using mingw
- env.Append(CCFLAGS=['-DWINVER=%s' % winver, '-D_WIN32_WINNT=%s' % winver])
+ ## Build type
+
+ if (env["target"] == "release"):
+ env.Append(CCFLAGS=['-msse2'])
+
+ if (env["bits"] == "64"):
+ env.Append(CCFLAGS=['-O3'])
+ else:
+ env.Append(CCFLAGS=['-O2'])
+
+ env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
+
+ elif (env["target"] == "release_debug"):
+ env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+
+ elif (env["target"] == "debug"):
+ env.Append(CCFLAGS=['-g', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+
+ ## Compiler configuration
+
if (os.name == "nt"):
env['ENV']['TMP'] = os.environ['TMP'] # way to go scons, you can be so stupid sometimes
else:
@@ -339,30 +259,6 @@ def configure(env):
else:
nulstr = ">nul"
- # if os.system(mingw_prefix+"gcc --version"+nulstr)!=0:
- # #not really super consistent but..
- # print("Can't find Windows compiler: "+mingw_prefix)
- # sys.exit(255)
-
- if (env["target"] == "release"):
-
- env.Append(CCFLAGS=['-msse2'])
-
- if (env["bits"] == "64"):
- env.Append(CCFLAGS=['-O3'])
- else:
- env.Append(CCFLAGS=['-O2'])
-
- env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
-
- elif (env["target"] == "release_debug"):
-
- env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
-
- elif (env["target"] == "debug"):
-
- env.Append(CCFLAGS=['-g', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
-
env["CC"] = mingw_prefix + "gcc"
env['AS'] = mingw_prefix + "as"
env['CXX'] = mingw_prefix + "g++"
@@ -371,29 +267,15 @@ def configure(env):
env['LD'] = mingw_prefix + "g++"
env["x86_libtheora_opt_gcc"] = True
- #env['CC'] = "winegcc"
- #env['CXX'] = "wineg++"
+ ## Compile flags
env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows'])
- env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
env.Append(CCFLAGS=['-DOPENGL_ENABLED'])
+ env.Append(CCFLAGS=['-DRTAUDIO_ENABLED'])
+ env.Append(CCFLAGS=['-DWINVER=%s' % winver, '-D_WIN32_WINNT=%s' % winver])
env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid'])
- # if (env["bits"]=="32"):
- # env.Append(LIBS=['gcc_s'])
- # #--with-arch=i686
- # env.Append(CPPFLAGS=['-march=i686'])
- # env.Append(LINKFLAGS=['-march=i686'])
-
- #'d3dx9d'
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
- # env.Append(LINKFLAGS=['-g'])
# resrc
- env['is_mingw'] = True
env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')})
-
- env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- env.Append(BUILDERS={'HLSL9': env.Builder(action=methods.build_hlsl_dx9_headers, suffix='hlsl.h', src_suffix='.hlsl')})
- env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 3802e7e784..c9271f6266 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "editor/editor_export.h"
-#include "platform/windows/logo.h"
+#include "platform/windows/logo.gen.h"
void register_windows_exporter() {
diff --git a/platform/windows/godot.ico b/platform/windows/godot.ico
index fd5c28944f..dd611e07da 100644
--- a/platform/windows/godot.ico
+++ b/platform/windows/godot.ico
Binary files differ
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index e94529dd94..2daf580c0d 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1410,28 +1410,21 @@ void OS_Windows::set_window_size(const Size2 p_size) {
return;
}
- RECT crect;
- GetClientRect(hWnd, &crect);
+ int w = p_size.width;
+ int h = p_size.height;
RECT rect;
GetWindowRect(hWnd, &rect);
- int dx = (rect.right - rect.left) - (crect.right - crect.left);
- int dy = (rect.bottom - rect.top) - (crect.bottom - crect.top);
- rect.right = rect.left + p_size.width + dx;
- rect.bottom = rect.top + p_size.height + dy;
+ if (video_mode.borderless_window == false) {
+ RECT crect;
+ GetClientRect(hWnd, &crect);
- //print_line("PRE: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top));
-
- /*if (video_mode.resizable) {
- AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
- } else {
- AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
- }*/
-
- //print_line("POST: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top));
+ w += (rect.right - rect.left) - (crect.right - crect.left);
+ h += (rect.bottom - rect.top) - (crect.bottom - crect.top);
+ }
- MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
+ MoveWindow(hWnd, rect.left, rect.top, w, h, TRUE);
}
void OS_Windows::set_window_fullscreen(bool p_enabled) {
@@ -1451,21 +1444,18 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
Point2 pos = get_screen_position(cs);
Size2 size = get_screen_size(cs);
- /* r.left = pos.x;
- r.top = pos.y;
- r.bottom = pos.y+size.y;
- r.right = pos.x+size.x;
-*/
- SetWindowLongPtr(hWnd, GWL_STYLE,
- WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
- MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
-
video_mode.fullscreen = true;
+ _update_window_style(false);
+
+ MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
+
} else {
RECT rect;
+ video_mode.fullscreen = false;
+
if (pre_fs_valid) {
rect = pre_fs_rect;
} else {
@@ -1475,35 +1465,12 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
rect.bottom = video_mode.height;
}
- if (video_mode.resizable) {
-
- SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
- //AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
- MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
- } else {
+ _update_window_style(false);
- SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
- //AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
- MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
- }
+ MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
- video_mode.fullscreen = false;
pre_fs_valid = true;
- /*
- DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- DWORD dwStyle=WS_OVERLAPPEDWINDOW;
- if (!video_mode.resizable) {
- dwStyle &= ~WS_THICKFRAME;
- dwStyle &= ~WS_MAXIMIZEBOX;
- }
- AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle);
- video_mode.fullscreen=false;
- video_mode.width=pre_fs_rect.right-pre_fs_rect.left;
- video_mode.height=pre_fs_rect.bottom-pre_fs_rect.top;
-*/
}
-
- //MoveWindow(hWnd,r.left,r.top,p_size.x,p_size.y,TRUE);
}
bool OS_Windows::is_window_fullscreen() const {
@@ -1513,30 +1480,10 @@ void OS_Windows::set_window_resizable(bool p_enabled) {
if (video_mode.resizable == p_enabled)
return;
- /*
- GetWindowRect(hWnd,&pre_fs_rect);
- DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- DWORD dwStyle=WS_OVERLAPPEDWINDOW;
- if (!p_enabled) {
- dwStyle &= ~WS_THICKFRAME;
- dwStyle &= ~WS_MAXIMIZEBOX;
- }
- AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle);
- */
-
- if (!video_mode.fullscreen) {
- if (p_enabled) {
- SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
- } else {
- SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE);
- }
-
- RECT rect;
- GetWindowRect(hWnd, &rect);
- MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
- }
video_mode.resizable = p_enabled;
+
+ _update_window_style();
}
bool OS_Windows::is_window_resizable() const {
@@ -1576,13 +1523,36 @@ bool OS_Windows::is_window_maximized() const {
}
void OS_Windows::set_borderless_window(int p_borderless) {
+ if (video_mode.borderless_window == p_borderless)
+ return;
+
video_mode.borderless_window = p_borderless;
+
+ _update_window_style();
}
bool OS_Windows::get_borderless_window() {
return video_mode.borderless_window;
}
+void OS_Windows::_update_window_style(bool repaint) {
+ if (video_mode.fullscreen || video_mode.borderless_window) {
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
+ } else {
+ if (video_mode.resizable) {
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
+ } else {
+ SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE);
+ }
+ }
+
+ if (repaint) {
+ RECT rect;
+ GetWindowRect(hWnd, &rect);
+ MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
+ }
+}
+
Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle) {
p_library_handle = (void *)LoadLibrary(p_path.utf8().get_data());
if (!p_library_handle) {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 6cbdd58830..835141145f 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -133,6 +133,8 @@ class OS_Windows : public OS {
void _drag_event(int p_x, int p_y, int idx);
void _touch_event(bool p_pressed, int p_x, int p_y, int idx);
+ void _update_window_style(bool repaint = true);
+
// functions used by main to initialize/deintialize the OS
protected:
virtual int get_video_driver_count() const;
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 0ba0f68393..79778136ad 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -1,7 +1,6 @@
-
import os
-import sys
import platform
+import sys
def is_active():
@@ -14,15 +13,12 @@ def get_name():
def can_build():
- if (os.name != "posix"):
+ if (os.name != "posix" or sys.platform == "darwin"):
return False
- if sys.platform == "darwin":
- return False # no x11 on mac for now
-
- errorval = os.system("pkg-config --version > /dev/null")
-
- if (errorval):
+ # Check the minimal dependencies
+ x11_error = os.system("pkg-config --version > /dev/null")
+ if (x11_error):
print("pkg-config not found.. x11 disabled.")
return False
@@ -31,11 +27,6 @@ def can_build():
print("X11 not found.. x11 disabled.")
return False
- ssl_error = os.system("pkg-config openssl --modversion > /dev/null ")
- if (ssl_error):
- print("OpenSSL not found.. x11 disabled.")
- return False
-
x11_error = os.system("pkg-config xcursor --modversion > /dev/null ")
if (x11_error):
print("xcursor not found.. x11 disabled.")
@@ -51,18 +42,18 @@ def can_build():
print("xrandr not found.. x11 disabled.")
return False
- return True # X11 enabled
+ return True
def get_opts():
return [
- ('use_llvm', 'Use llvm compiler', 'no'),
- ('use_static_cpp', 'link stdc++ statically', 'no'),
- ('use_sanitizer', 'Use llvm compiler sanitize address', 'no'),
- ('use_leak_sanitizer', 'Use llvm compiler sanitize memory leaks', 'no'),
+ ('use_llvm', 'Use the LLVM compiler', 'no'),
+ ('use_static_cpp', 'Link stdc++ statically', 'no'),
+ ('use_sanitizer', 'Use LLVM compiler address sanitizer', 'no'),
+ ('use_leak_sanitizer', 'Use LLVM compiler memory leaks sanitizer (implies use_sanitizer)', 'no'),
('use_lto', 'Use link time optimization', 'no'),
- ('pulseaudio', 'Detect & Use pulseaudio', 'yes'),
+ ('pulseaudio', 'Detect & use pulseaudio', 'yes'),
('udev', 'Use udev for gamepad connection callbacks', 'no'),
('debug_release', 'Add debug symbols to release version', 'no'),
]
@@ -80,66 +71,62 @@ def get_flags():
def configure(env):
- is64 = sys.maxsize > 2**32
+ ## Build type
+
+ if (env["target"] == "release"):
+ env.Prepend(CCFLAGS=['-Ofast'])
+ if (env["debug_release"] == "yes"):
+ env.Prepend(CCFLAGS=['-g2'])
+
+ elif (env["target"] == "release_debug"):
+ env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
+ if (env["debug_release"] == "yes"):
+ env.Prepend(CCFLAGS=['-g2'])
+
+ elif (env["target"] == "debug"):
+ env.Prepend(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+
+ ## Architecture
+ is64 = sys.maxsize > 2**32
if (env["bits"] == "default"):
- if (is64):
- env["bits"] = "64"
- else:
- env["bits"] = "32"
+ env["bits"] = "64" if is64 else "32"
+
+ ## Compiler configuration
- env.Append(CPPPATH=['#platform/x11'])
if (env["use_llvm"] == "yes"):
- if 'clang++' not in env['CXX']:
+ if ('clang++' not in env['CXX']):
env["CC"] = "clang"
env["CXX"] = "clang++"
env["LD"] = "clang++"
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
- env.extra_suffix = ".llvm"
-
- if (env["use_sanitizer"] == "yes"):
- env.Append(CCFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer'])
- env.Append(LINKFLAGS=['-fsanitize=address'])
- env.extra_suffix += "s"
+ env.extra_suffix = ".llvm" + env.extra_suffix
- if (env["use_leak_sanitizer"] == "yes"):
+ # leak sanitizer requires (address) sanitizer
+ if (env["use_sanitizer"] == "yes" or env["use_leak_sanitizer"] == "yes"):
env.Append(CCFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer'])
env.Append(LINKFLAGS=['-fsanitize=address'])
env.extra_suffix += "s"
-
- # if (env["tools"]=="no"):
- # #no tools suffix
- # env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
- # env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
+ if (env["use_leak_sanitizer"] == "yes"):
+ env.Append(CCFLAGS=['-fsanitize=leak'])
+ env.Append(LINKFLAGS=['-fsanitize=leak'])
if (env["use_lto"] == "yes"):
env.Append(CCFLAGS=['-flto'])
env.Append(LINKFLAGS=['-flto'])
-
env.Append(CCFLAGS=['-pipe'])
env.Append(LINKFLAGS=['-pipe'])
- if (env["target"] == "release"):
- env.Prepend(CCFLAGS=['-Ofast'])
- if (env["debug_release"] == "yes"):
- env.Prepend(CCFLAGS=['-g2'])
-
- elif (env["target"] == "release_debug"):
-
- env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
- if (env["debug_release"] == "yes"):
- env.Prepend(CCFLAGS=['-g2'])
-
- elif (env["target"] == "debug"):
-
- env.Prepend(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ ## Dependencies
env.ParseConfig('pkg-config x11 --cflags --libs')
- env.ParseConfig('pkg-config xinerama --cflags --libs')
env.ParseConfig('pkg-config xcursor --cflags --libs')
+ env.ParseConfig('pkg-config xinerama --cflags --libs')
env.ParseConfig('pkg-config xrandr --cflags --libs')
+ # FIXME: Check for existence of the libs before parsing their flags with pkg-config
+
if (env['builtin_openssl'] == 'no'):
# Currently not compatible with OpenSSL 1.1.0+
# https://github.com/godotengine/godot/issues/8624
@@ -196,47 +183,51 @@ def configure(env):
if (env['builtin_libogg'] == 'no'):
env.ParseConfig('pkg-config ogg --cflags --libs')
- env.Append(CPPFLAGS=['-DOPENGL_ENABLED'])
+ if (env['builtin_libtheora'] != 'no'):
+ list_of_x86 = ['x86_64', 'x86', 'i386', 'i586']
+ if any(platform.machine() in s for s in list_of_x86):
+ env["x86_libtheora_opt_gcc"] = True
+
+ ## Flags
- if os.system("pkg-config --exists alsa") == 0:
+ if (os.system("pkg-config --exists alsa") == 0): # 0 means found
print("Enabling ALSA")
env.Append(CPPFLAGS=["-DALSA_ENABLED"])
env.ParseConfig('pkg-config alsa --cflags --libs')
else:
print("ALSA libraries not found, disabling driver")
- if (platform.system() == "Linux"):
- env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
- if (env["udev"] == "yes"):
- # pkg-config returns 0 when the lib exists...
- found_udev = not os.system("pkg-config --exists libudev")
-
- if (found_udev):
- print("Enabling udev support")
- env.Append(CPPFLAGS=["-DUDEV_ENABLED"])
- env.ParseConfig('pkg-config libudev --cflags --libs')
- else:
- print("libudev development libraries not found, disabling udev support")
-
if (env["pulseaudio"] == "yes"):
- if not os.system("pkg-config --exists libpulse-simple"):
+ if (os.system("pkg-config --exists libpulse-simple") == 0): # 0 means found
print("Enabling PulseAudio")
env.Append(CPPFLAGS=["-DPULSEAUDIO_ENABLED"])
env.ParseConfig('pkg-config --cflags --libs libpulse-simple')
else:
print("PulseAudio development libraries not found, disabling driver")
+ if (platform.system() == "Linux"):
+ env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
+
+ if (env["udev"] == "yes"):
+ if (os.system("pkg-config --exists libudev") == 0): # 0 means found
+ print("Enabling udev support")
+ env.Append(CPPFLAGS=["-DUDEV_ENABLED"])
+ env.ParseConfig('pkg-config libudev --cflags --libs')
+ else:
+ print("libudev development libraries not found, disabling udev support")
+
+ # Linkflags below this line should typically stay the last ones
if (env['builtin_zlib'] == 'no'):
env.ParseConfig('pkg-config zlib --cflags --libs')
- env.Append(CPPFLAGS=['-DX11_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
+ env.Append(CPPPATH=['#platform/x11'])
+ env.Append(CPPFLAGS=['-DX11_ENABLED', '-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES2_ENABLED', '-DGLES_OVER_GL'])
env.Append(LIBS=['GL', 'pthread'])
if (platform.system() == "Linux"):
env.Append(LIBS=['dl'])
- # env.Append(CPPFLAGS=['-DMPC_FIXED_POINT'])
- # host compiler is default..
+ ## Cross-compilation
if (is64 and env["bits"] == "32"):
env.Append(CPPFLAGS=['-m32'])
@@ -245,17 +236,5 @@ def configure(env):
env.Append(CPPFLAGS=['-m64'])
env.Append(LINKFLAGS=['-m64', '-L/usr/lib/i686-linux-gnu'])
- import methods
-
- # FIXME: Commented out when moving to gles3
- #env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.h', src_suffix='.glsl')})
- #env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.h', src_suffix='.glsl')})
- #env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.h', src_suffix='.glsl')})
- #env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
-
if (env["use_static_cpp"] == "yes"):
env.Append(LINKFLAGS=['-static-libstdc++'])
-
- list_of_x86 = ['x86_64', 'x86', 'i386', 'i586']
- if any(platform.machine() in s for s in list_of_x86):
- env["x86_libtheora_opt_gcc"] = True
diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp
index d6bad95e5b..69784a473d 100644
--- a/platform/x11/export/export.cpp
+++ b/platform/x11/export/export.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "export.h"
#include "editor/editor_export.h"
-#include "platform/x11/logo.h"
+#include "platform/x11/logo.gen.h"
#include "scene/resources/texture.h"
void register_x11_exporter() {
diff --git a/platform/x11/godot_x11.cpp b/platform/x11/godot_x11.cpp
index b293b1bebb..6f418b213f 100644
--- a/platform/x11/godot_x11.cpp
+++ b/platform/x11/godot_x11.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include <limits.h>
+#include <locale.h>
#include <stdlib.h>
#include <unistd.h>
@@ -38,6 +39,8 @@ int main(int argc, char *argv[]) {
OS_X11 os;
+ setlocale(LC_CTYPE, "");
+
char *cwd = (char *)malloc(PATH_MAX);
getcwd(cwd, PATH_MAX);
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 2eebc96d2c..790182794e 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -68,6 +68,8 @@
#undef CursorShape
+#include <X11/XKBlib.h>
+
int OS_X11::get_video_driver_count() const {
return 1;
}
@@ -93,6 +95,7 @@ const char *OS_X11::get_audio_driver_name(int p_driver) const {
void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
+ long im_event_mask = 0;
last_button_state = 0;
xmbstring = NULL;
@@ -113,7 +116,32 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
/** XLIB INITIALIZATION **/
x11_display = XOpenDisplay(NULL);
- char *modifiers = XSetLocaleModifiers("@im=none");
+ Bool xkb_dar = False;
+ if (x11_display) {
+ XAutoRepeatOn(x11_display);
+ xkb_dar = XkbSetDetectableAutoRepeat(x11_display, True, NULL);
+ }
+
+ char *modifiers = NULL;
+
+ // Try to support IME if detectable auto-repeat is supported
+
+ if (xkb_dar == True) {
+
+// Xutf8LookupString will be used later instead of XmbLookupString before
+// the multibyte sequences can be converted to unicode string.
+
+#ifdef X_HAVE_UTF8_STRING
+ modifiers = XSetLocaleModifiers("");
+#endif
+ }
+
+ if (modifiers == NULL) {
+ if (is_stdout_verbose()) {
+ WARN_PRINT("IME is disabled");
+ }
+ modifiers = XSetLocaleModifiers("@im=none");
+ }
if (modifiers == NULL) {
WARN_PRINT("Error setting locale modifiers");
}
@@ -153,6 +181,14 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
WARN_PRINT("XOpenIM failed");
xim_style = 0L;
} else {
+ ::XIMCallback im_destroy_callback;
+ im_destroy_callback.client_data = (::XPointer)(this);
+ im_destroy_callback.callback = (::XIMProc)(xim_destroy_callback);
+ if (XSetIMValues(xim, XNDestroyCallback, &im_destroy_callback,
+ NULL) != NULL) {
+ WARN_PRINT("Error setting XIM destroy callback");
+ }
+
::XIMStyles *xim_styles = NULL;
xim_style = 0L;
char *imvalret = NULL;
@@ -242,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
@@ -303,7 +346,8 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
StructureNotifyMask |
SubstructureNotifyMask | SubstructureRedirectMask |
FocusChangeMask | PropertyChangeMask |
- ColormapChangeMask | OwnerGrabButtonMask;
+ ColormapChangeMask | OwnerGrabButtonMask |
+ im_event_mask;
XChangeWindowAttributes(x11_display, x11_window, CWEventMask, &new_attr);
@@ -327,6 +371,16 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
if (xim && xim_style) {
xic = XCreateIC(xim, XNInputStyle, xim_style, XNClientWindow, x11_window, XNFocusWindow, x11_window, (char *)NULL);
+ if (XGetICValues(xic, XNFilterEvents, &im_event_mask, NULL) != NULL) {
+ WARN_PRINT("XGetICValues couldn't obtain XNFilterEvents value");
+ XDestroyIC(xic);
+ xic = NULL;
+ }
+ if (xic) {
+ XSetICFocus(xic);
+ } else {
+ WARN_PRINT("XCreateIC couldn't create xic");
+ }
} else {
xic = NULL;
@@ -445,6 +499,33 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
_ensure_data_dir();
}
+void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data,
+ ::XPointer call_data) {
+
+ WARN_PRINT("Input method stopped");
+ OS_X11 *os = reinterpret_cast<OS_X11 *>(client_data);
+ os->xim = NULL;
+ os->xic = NULL;
+}
+
+void OS_X11::set_ime_position(short x, short y) {
+
+ if (!xic) {
+ return;
+ }
+ ::XPoint spot;
+ spot.x = x;
+ spot.y = y;
+ XVaNestedList preedit_attr = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ NULL);
+ XSetICValues(xic,
+ XNPreeditAttributes, preedit_attr,
+ NULL);
+ XFree(preedit_attr);
+ return;
+}
+
void OS_X11::finalize() {
if (main_loop)
@@ -492,8 +573,12 @@ void OS_X11::finalize() {
XcursorImageDestroy(img[i]);
};
- XDestroyIC(xic);
- XCloseIM(xim);
+ if (xic) {
+ XDestroyIC(xic);
+ }
+ if (xim) {
+ XCloseIM(xim);
+ }
XCloseDisplay(x11_display);
if (xmbstring)
@@ -940,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
//
@@ -1041,9 +1145,61 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
xmblen = 8;
}
+ keysym_unicode = keysym_keycode;
+
if (xkeyevent->type == KeyPress && xic) {
Status status;
+#ifdef X_HAVE_UTF8_STRING
+ int utf8len = 8;
+ char *utf8string = (char *)memalloc(sizeof(char) * utf8len);
+ int utf8bytes = Xutf8LookupString(xic, xkeyevent, utf8string,
+ utf8len - 1, &keysym_unicode, &status);
+ if (status == XBufferOverflow) {
+ utf8len = utf8bytes + 1;
+ utf8string = (char *)memrealloc(utf8string, utf8len);
+ utf8bytes = Xutf8LookupString(xic, xkeyevent, utf8string,
+ utf8len - 1, &keysym_unicode, &status);
+ }
+ utf8string[utf8bytes] = '\0';
+
+ if (status == XLookupChars) {
+ bool keypress = xkeyevent->type == KeyPress;
+ unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
+ if (keycode >= 'a' && keycode <= 'z')
+ keycode -= 'a' - 'A';
+
+ String tmp;
+ tmp.parse_utf8(utf8string, utf8bytes);
+ for (int i = 0; i < tmp.length(); i++) {
+ Ref<InputEventKey> k;
+ k.instance();
+ if (keycode == 0 && tmp[i] == 0) {
+ continue;
+ }
+
+ get_key_modifier_state(xkeyevent->state, k);
+
+ k->set_unicode(tmp[i]);
+
+ k->set_pressed(keypress);
+
+ k->set_scancode(keycode);
+
+ k->set_echo(false);
+
+ if (k->get_scancode() == KEY_BACKTAB) {
+ //make it consistent across platforms.
+ k->set_scancode(KEY_TAB);
+ k->set_shift(true);
+ }
+
+ input->parse_input_event(k);
+ }
+ return;
+ }
+ memfree(utf8string);
+#else
do {
int mnbytes = XmbLookupString(xic, xkeyevent, xmbstring, xmblen - 1, &keysym_unicode, &status);
@@ -1054,6 +1210,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
xmbstring = (char *)memrealloc(xmbstring, xmblen);
}
} while (status == XBufferOverflow);
+#endif
}
/* Phase 2, obtain a pigui keycode from the keysym */
@@ -1082,11 +1239,6 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
bool keypress = xkeyevent->type == KeyPress;
- if (xkeyevent->type == KeyPress && xic) {
- if (XFilterEvent((XEvent *)xkeyevent, x11_window))
- return;
- }
-
if (keycode == 0 && unicode == 0)
return;
@@ -1108,17 +1260,19 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
// Echo characters in X11 are a keyrelease and a keypress
// one after the other with the (almot) same timestamp.
// To detect them, i use XPeekEvent and check that their
- // difference in time is below a treshold.
+ // difference in time is below a threshold.
if (xkeyevent->type != KeyPress) {
+ p_echo = false;
+
// make sure there are events pending,
// so this call won't block.
if (XPending(x11_display) > 0) {
XEvent peek_event;
XPeekEvent(x11_display, &peek_event);
- // I'm using a treshold of 5 msecs,
+ // I'm using a threshold of 5 msecs,
// since sometimes there seems to be a little
// jitter. I'm still not convinced that all this approach
// is correct, but the xorg developers are
@@ -1172,6 +1326,18 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
k->set_metakey(false);
}
+ bool last_is_pressed = Input::get_singleton()->is_key_pressed(k->get_scancode());
+ if (k->is_pressed()) {
+ if (last_is_pressed) {
+ k->set_echo(true);
+ }
+ } else {
+ //ignore
+ if (last_is_pressed == false) {
+ return;
+ }
+ }
+
//printf("key: %x\n",k->get_scancode());
input->parse_input_event(k);
}
@@ -1253,6 +1419,10 @@ void OS_X11::process_xevents() {
XEvent event;
XNextEvent(x11_display, &event);
+ if (XFilterEvent(&event, None)) {
+ continue;
+ }
+
switch (event.type) {
case Expose:
Main::force_redraw();
@@ -1295,6 +1465,9 @@ void OS_X11::process_xevents() {
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime);
}
+ if (xic) {
+ XSetICFocus(xic);
+ }
break;
case FocusOut:
@@ -1308,9 +1481,16 @@ void OS_X11::process_xevents() {
}
XUngrabPointer(x11_display, CurrentTime);
}
+ if (xic) {
+ XUnsetICFocus(xic);
+ }
break;
case ConfigureNotify:
+ if (xic) {
+ // Not portable.
+ set_ime_position(0, 1);
+ }
/* call resizeGLScene only if our window-size changed */
if ((event.xconfigure.width == current_videomode.width) &&
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index d62186e5bd..39c512b6bd 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -113,6 +113,10 @@ class OS_X11 : public OS_Unix {
::XIC xic;
::XIM xim;
::XIMStyle xim_style;
+ static void xim_destroy_callback(::XIM im, ::XPointer client_data,
+ ::XPointer call_data);
+ void set_ime_position(short x, short y);
+
Point2i last_mouse_pos;
bool last_mouse_pos_valid;
Point2i last_click_pos;
@@ -247,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!");