summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--README.md2
-rw-r--r--core/bind/core_bind.cpp12
-rw-r--r--core/bind/core_bind.h11
-rw-r--r--core/image.cpp25
-rw-r--r--core/image.h1
-rw-r--r--core/io/file_access_encrypted.cpp5
-rw-r--r--core/io/file_access_pack.cpp5
-rw-r--r--core/io/file_access_pack.h1
-rw-r--r--core/io/ip.cpp13
-rw-r--r--core/io/ip.h3
-rw-r--r--core/io/packet_peer.cpp1
-rw-r--r--core/os/dir_access.h2
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/input.cpp2
-rw-r--r--core/os/main_loop.cpp2
-rw-r--r--core/script_language.h1
-rw-r--r--core/variant_call.cpp2
-rw-r--r--demos/2d/platformer/stage.xml12
-rw-r--r--demos/3d/fixed_materials/fixed_materials.scnbin5906 -> 6071 bytes
-rw-r--r--demos/3d/platformer/stage.xml15
-rw-r--r--demos/3d/platformer/tiles.resbin81540 -> 81468 bytes
-rw-r--r--[-rwxr-xr-x]doc/make_doc.sh0
-rw-r--r--drivers/gles1/rasterizer_gles1.cpp81
-rw-r--r--drivers/gles1/rasterizer_gles1.h28
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp370
-rw-r--r--drivers/gles2/rasterizer_gles2.h67
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp7
-rw-r--r--drivers/gles2/shader_compiler_gles2.h1
-rw-r--r--drivers/gles2/shader_gles2.cpp8
-rw-r--r--drivers/gles2/shaders/canvas.glsl3
-rw-r--r--drivers/gles2/shaders/copy.glsl56
-rw-r--r--drivers/gles2/shaders/material.glsl20
-rw-r--r--drivers/unix/dir_access_unix.cpp20
-rw-r--r--drivers/unix/dir_access_unix.h4
-rw-r--r--drivers/unix/ip_unix.cpp99
-rw-r--r--drivers/unix/ip_unix.h2
-rw-r--r--drivers/unix/tcp_server_posix.cpp3
-rw-r--r--drivers/windows/dir_access_windows.cpp33
-rw-r--r--drivers/windows/dir_access_windows.h1
-rw-r--r--modules/gdscript/gd_compiler.cpp20
-rw-r--r--modules/gdscript/gd_editor.cpp64
-rw-r--r--modules/gdscript/gd_parser.cpp23
-rw-r--r--modules/gdscript/gd_parser.h2
-rw-r--r--modules/gdscript/gd_script.cpp5
-rw-r--r--modules/gdscript/gd_script.h8
-rw-r--r--platform/android/SCsub1
-rw-r--r--platform/android/detect.py57
-rw-r--r--platform/android/dir_access_jandroid.cpp26
-rw-r--r--platform/android/dir_access_jandroid.h1
-rw-r--r--platform/android/export/export.cpp74
-rw-r--r--platform/android/ifaddrs_android.cpp221
-rw-r--r--platform/android/ifaddrs_android.h46
-rw-r--r--platform/android/java/src/com/android/godot/Godot.java178
-rw-r--r--platform/android/java/src/com/android/godot/GodotPaymentV3.java37
-rw-r--r--platform/android/java/src/com/android/godot/GodotView.java493
-rw-r--r--platform/android/java/src/com/android/godot/payments/ConsumeTask.java3
-rw-r--r--platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java10
-rw-r--r--platform/android/java/src/com/android/godot/payments/PaymentsCache.java3
-rw-r--r--platform/android/java/src/com/android/godot/payments/PaymentsManager.java12
-rw-r--r--platform/android/java/src/com/android/godot/payments/PurchaseTask.java6
-rw-r--r--platform/android/java_bind.cpp5
-rw-r--r--platform/android/java_bind.h10
-rw-r--r--platform/android/java_glue.cpp29
-rwxr-xr-xplatform/android/sign.sh2
-rw-r--r--platform/bb10/export/export.cpp8
-rw-r--r--platform/flash/dir_access_flash.cpp20
-rw-r--r--platform/flash/dir_access_flash.h1
-rw-r--r--platform/iphone/detect.py6
-rwxr-xr-xplatform/iphone/gl_view.mm13
-rw-r--r--platform/javascript/export/export.cpp8
-rw-r--r--platform/osx/export/export.cpp8
-rw-r--r--platform/windows/detect.py14
-rw-r--r--platform/windows/tcp_server_winsock.cpp3
-rw-r--r--platform/x11/os_x11.cpp36
-rw-r--r--platform/x11/os_x11.h2
-rw-r--r--scene/2d/canvas_item.cpp7
-rw-r--r--scene/2d/canvas_item.h3
-rw-r--r--scene/3d/immediate_geometry.cpp102
-rw-r--r--scene/3d/immediate_geometry.h41
-rw-r--r--scene/3d/sprite_3d.cpp772
-rw-r--r--scene/3d/sprite_3d.h191
-rw-r--r--scene/gui/label.cpp11
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/environment.cpp15
-rw-r--r--scene/resources/environment.h10
-rw-r--r--scene/resources/material.cpp13
-rw-r--r--scene/resources/material.h3
-rw-r--r--scene/resources/texture.cpp55
-rw-r--r--scene/resources/texture.h3
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h4
-rw-r--r--servers/visual/rasterizer.cpp6
-rw-r--r--servers/visual/rasterizer.h22
-rw-r--r--servers/visual/rasterizer_dummy.cpp80
-rw-r--r--servers/visual/rasterizer_dummy.h29
-rw-r--r--servers/visual/shader_language.cpp2
-rw-r--r--servers/visual/visual_server_raster.cpp77
-rw-r--r--servers/visual/visual_server_raster.h15
-rw-r--r--servers/visual/visual_server_wrap_mt.h16
-rw-r--r--servers/visual_server.cpp49
-rw-r--r--servers/visual_server.h46
-rw-r--r--tools/editor/editor_import_export.cpp2
-rw-r--r--tools/editor/editor_import_export.h6
-rw-r--r--tools/editor/editor_node.cpp7
-rw-r--r--tools/editor/editor_run_native.cpp14
-rw-r--r--tools/editor/editor_run_native.h4
-rw-r--r--tools/editor/fileserver/editor_file_server.cpp21
-rw-r--r--tools/editor/icons/SCsub36
-rw-r--r--tools/editor/icons/icon_animated_sprite_3d.pngbin0 -> 753 bytes
-rw-r--r--tools/editor/icons/icon_sprite_3d.pngbin0 -> 604 bytes
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp12
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.h3
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp193
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h12
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp15
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp21
-rw-r--r--tools/editor/plugins/script_editor_plugin.h1
-rw-r--r--tools/editor/project_export.cpp2
-rw-r--r--tools/editor/project_manager.cpp269
-rw-r--r--tools/editor/project_manager.h10
-rw-r--r--tools/editor/property_editor.cpp1
-rw-r--r--tools/editor/scenes_dock.cpp156
-rw-r--r--tools/editor/scenes_dock.h39
124 files changed, 4139 insertions, 641 deletions
diff --git a/.gitignore b/.gitignore
index be4dc91598..32c7fe51c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,7 +29,9 @@ platform/android/java/assets
# General c++ generated files
*.lib
*.o
+*.ox
*.a
+*.ax
*.d
*.so
*.os
diff --git a/README.md b/README.md
index d7cc6b3063..dba980bba9 100644
--- a/README.md
+++ b/README.md
@@ -28,4 +28,4 @@ http://www.godotengine.org
### Compiling from Source
Compilation instructions for every platform can be found in the Wiki:
-http://www.godotengine.org/wiki/doku.php?id=advanced
+https://github.com/okamstudio/godot/wiki/advanced
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index ec159da00f..73b8c01ee2 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -98,6 +98,13 @@ void _ResourceSaver::_bind_methods() {
ObjectTypeDB::bind_method(_MD("save","path","resource:Resource"),&_ResourceSaver::save, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_recognized_extensions","type"),&_ResourceSaver::get_recognized_extensions);
+
+ BIND_CONSTANT(FLAG_RELATIVE_PATHS);
+ BIND_CONSTANT(FLAG_BUNDLE_RESOURCES);
+ BIND_CONSTANT(FLAG_CHANGE_PATH);
+ BIND_CONSTANT(FLAG_OMIT_EDITOR_PROPERTIES);
+ BIND_CONSTANT(FLAG_SAVE_BIG_ENDIAN);
+ BIND_CONSTANT(FLAG_COMPRESS);
}
_ResourceSaver::_ResourceSaver() {
@@ -1340,6 +1347,10 @@ bool _Directory::file_exists(String p_file){
return d->file_exists(p_file);
}
+bool _Directory::dir_exists(String p_dir) {
+ ERR_FAIL_COND_V(!d,false);
+ return d->dir_exists(p_dir);
+}
int _Directory::get_space_left(){
@@ -1379,6 +1390,7 @@ void _Directory::_bind_methods() {
ObjectTypeDB::bind_method(_MD("make_dir:Error","name"),&_Directory::make_dir);
ObjectTypeDB::bind_method(_MD("make_dir_recursive:Error","name"),&_Directory::make_dir_recursive);
ObjectTypeDB::bind_method(_MD("file_exists","name"),&_Directory::file_exists);
+ ObjectTypeDB::bind_method(_MD("dir_exists","name"),&_Directory::dir_exists);
// ObjectTypeDB::bind_method(_MD("get_modified_time","file"),&_Directory::get_modified_time);
ObjectTypeDB::bind_method(_MD("get_space_left"),&_Directory::get_space_left);
ObjectTypeDB::bind_method(_MD("copy:Error","from","to"),&_Directory::copy);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 18eb594760..02fe3e8874 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -39,6 +39,16 @@ protected:
static _ResourceSaver *singleton;
public:
+ enum SaverFlags {
+
+ FLAG_RELATIVE_PATHS=1,
+ FLAG_BUNDLE_RESOURCES=2,
+ FLAG_CHANGE_PATH=4,
+ FLAG_OMIT_EDITOR_PROPERTIES=8,
+ FLAG_SAVE_BIG_ENDIAN=16,
+ FLAG_COMPRESS=32,
+ };
+
static _ResourceSaver *get_singleton() { return singleton; }
Error save(const String &p_path,const RES& p_resource, uint32_t p_flags);
@@ -340,6 +350,7 @@ public:
Error make_dir_recursive(String p_dir);
bool file_exists(String p_file);
+ bool dir_exists(String p_dir);
int get_space_left();
diff --git a/core/image.cpp b/core/image.cpp
index ccabd04d6f..db20862af5 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1660,6 +1660,31 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *)) {
}
+
+void Image::premultiply_alpha() {
+
+ if (data.size()==0)
+ return;
+
+ if (format!=FORMAT_RGBA)
+ return; //not needed
+
+ DVector<uint8_t>::Write wp = data.write();
+ unsigned char *data_ptr=wp.ptr();
+
+
+ for(int i=0;i<height;i++) {
+ for(int j=0;j<width;j++) {
+
+ BColor bc = _get_pixel(j,i,data_ptr,0);
+ bc.r=(int(bc.r)*int(bc.a))>>8;
+ bc.g=(int(bc.g)*int(bc.a))>>8;
+ bc.b=(int(bc.b)*int(bc.a))>>8;
+ _put_pixel(j,i,bc,data_ptr);
+ }
+ }
+}
+
void Image::fix_alpha_edges() {
if (data.size()==0)
diff --git a/core/image.h b/core/image.h
index 186aceb1bf..99300fc3af 100644
--- a/core/image.h
+++ b/core/image.h
@@ -320,6 +320,7 @@ public:
void decompress();
void fix_alpha_edges();
+ void premultiply_alpha();
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index bcd4197e11..29f27dcbda 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -25,6 +25,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_
} else if (p_mode==MODE_READ) {
+ writing=false;
key=p_key;
uint32_t magic = p_base->get_32();
print_line("MAGIC: "+itos(magic));
@@ -278,6 +279,10 @@ uint64_t FileAccessEncrypted::_get_modified_time(const String& p_file){
FileAccessEncrypted::FileAccessEncrypted() {
file=NULL;
+ pos=0;
+ eofed=false;
+ mode=MODE_MAX;
+ writing=false;
}
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 6a28fa9dae..e2cb300ebc 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -443,6 +443,11 @@ bool DirAccessPack::file_exists(String p_file){
return current->files.has(p_file);
}
+bool DirAccessPack::dir_exists(String p_dir) {
+
+ return current->subdirs.has(p_dir);
+}
+
Error DirAccessPack::make_dir(String p_dir){
return ERR_UNAVAILABLE;
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 07ce8cbaf8..a4c750bf3c 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -190,6 +190,7 @@ public:
virtual bool file_exists(String p_file);
+ virtual bool dir_exists(String p_dir);
virtual Error make_dir(String p_dir);
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 503a009444..d2a685f6b0 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -188,6 +188,18 @@ void IP::erase_resolve_item(ResolverID p_id) {
}
+Array IP::_get_local_addresses() const {
+
+ Array addresses;
+ List<IP_Address> ip_addresses;
+ get_local_addresses(&ip_addresses);
+ for(List<IP_Address>::Element *E=ip_addresses.front();E;E=E->next()) {
+ addresses.push_back(E->get());
+ }
+
+ return addresses;
+}
+
void IP::_bind_methods() {
ObjectTypeDB::bind_method(_MD("resolve_hostname","host"),&IP::resolve_hostname);
@@ -195,6 +207,7 @@ void IP::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_resolve_item_status","id"),&IP::get_resolve_item_status);
ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address);
ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item);
+ ObjectTypeDB::bind_method(_MD("get_local_addresses"),&IP::_get_local_addresses);
BIND_CONSTANT( RESOLVER_STATUS_NONE );
BIND_CONSTANT( RESOLVER_STATUS_WAITING );
diff --git a/core/io/ip.h b/core/io/ip.h
index f1ef5fe794..0181dc7d12 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -66,16 +66,19 @@ protected:
static void _bind_methods();
virtual IP_Address _resolve_hostname(const String& p_hostname)=0;
+ Array _get_local_addresses() const;
static IP* (*_create)();
public:
+
IP_Address resolve_hostname(const String& p_hostname);
// async resolver hostname
ResolverID resolve_hostname_queue_item(const String& p_hostname);
ResolverStatus get_resolve_item_status(ResolverID p_id) const;
IP_Address get_resolve_item_address(ResolverID p_id) const;
+ virtual void get_local_addresses(List<IP_Address> *r_addresses) const=0;
void erase_resolve_item(ResolverID p_id);
static IP* get_singleton();
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index f67a10df2e..37fc9c4a0a 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -112,6 +112,7 @@ void PacketPeer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var);
ObjectTypeDB::bind_method(_MD("put_var", "var:Variant"),&PacketPeer::put_var);
+ ObjectTypeDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count);
};
/***************/
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 58a925465a..d8672218bd 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -91,7 +91,7 @@ public:
virtual Error erase_contents_recursive(); //super dangerous, use with care!
virtual bool file_exists(String p_file)=0;
-
+ virtual bool dir_exists(String p_dir)=0;
virtual size_t get_space_left()=0;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 31e7d19bae..ffa0cad8e4 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -100,7 +100,7 @@ FileAccess *FileAccess::open(const String& p_path, int p_mode_flags, Error *r_er
FileAccess *ret=NULL;
if (!(p_mode_flags&WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
ret = PackedData::get_singleton()->try_open_path(p_path);
- if (ret) {
+ if (ret) {
if (r_error)
*r_error=OK;
return ret;
diff --git a/core/os/input.cpp b/core/os/input.cpp
index d7c0d86d64..70733aadec 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -211,6 +211,8 @@ void InputDefault::parse_input_event(const InputEvent& p_event) {
if (p_event.key.scancode==0)
break;
+ // print_line(p_event);
+
if (p_event.key.pressed)
keys_pressed.insert(p_event.key.scancode);
else
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index a8e02526b9..d01331a256 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -37,7 +37,7 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
-
+ BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
};
diff --git a/core/script_language.h b/core/script_language.h
index 9731273610..560de520ca 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -141,6 +141,7 @@ public:
virtual int find_function(const String& p_function,const String& p_code) const=0;
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0;
virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_keyword, List<String>* r_options) { return ERR_UNAVAILABLE; }
+ virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const=0;
/* DEBUGGER FUNCTIONS */
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 63d0fcec3a..c245e01ee0 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -567,6 +567,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_PTR0R( Matrix32, affine_inverse );
VCALL_PTR0R( Matrix32, get_rotation );
VCALL_PTR0R( Matrix32, get_origin );
+ VCALL_PTR0R( Matrix32, get_scale );
VCALL_PTR0R( Matrix32, orthonormalized );
VCALL_PTR1R( Matrix32, rotated );
VCALL_PTR1R( Matrix32, scaled );
@@ -1377,6 +1378,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(MATRIX32,MATRIX32,Matrix32,affine_inverse,varray());
ADDFUNC0(MATRIX32,REAL,Matrix32,get_rotation,varray());
ADDFUNC0(MATRIX32,VECTOR2,Matrix32,get_origin,varray());
+ ADDFUNC0(MATRIX32,VECTOR2,Matrix32,get_scale,varray());
ADDFUNC0(MATRIX32,MATRIX32,Matrix32,orthonormalized,varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,rotated,REAL,"phi",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,scaled,VECTOR2,"scale",varray());
diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml
index 952c21e936..6a112e02aa 100644
--- a/demos/2d/platformer/stage.xml
+++ b/demos/2d/platformer/stage.xml
@@ -3,10 +3,10 @@
<ext_resource path="res://music.ogg" type="AudioStream"></ext_resource>
<ext_resource path="res://tileset.xml" type="TileSet"></ext_resource>
<ext_resource path="res://coin.xml" type="PackedScene"></ext_resource>
+ <ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
+ <ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://enemy.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource>
- <ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource>
<main_resource>
<dictionary name="_bundled" shared="false">
@@ -160,9 +160,13 @@
<string> "pixel_snap" </string>
<bool> False </bool>
<string> "zoom" </string>
- <real> 0.735092 </real>
+ <real> 0.54036 </real>
+ <string> "use_snap" </string>
+ <bool> False </bool>
<string> "ofs" </string>
- <vector2> 55.9232, 767.661 </vector2>
+ <vector2> 418.81, 615.088 </vector2>
+ <string> "snap" </string>
+ <int> 10 </int>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
diff --git a/demos/3d/fixed_materials/fixed_materials.scn b/demos/3d/fixed_materials/fixed_materials.scn
index 210d4208ee..de14ccdb15 100644
--- a/demos/3d/fixed_materials/fixed_materials.scn
+++ b/demos/3d/fixed_materials/fixed_materials.scn
Binary files differ
diff --git a/demos/3d/platformer/stage.xml b/demos/3d/platformer/stage.xml
index 1dc7d1e7ab..fbb720c006 100644
--- a/demos/3d/platformer/stage.xml
+++ b/demos/3d/platformer/stage.xml
@@ -6,14 +6,19 @@
<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource>
<resource type="Environment" path="local://1">
+ <bool name="fxaa/enabled"> False </bool>
<int name="background/mode"> 4 </int>
<color name="background/color"> 0, 0, 0, 1 </color>
<nil name="background/texture"> </nil>
<resource name="background/cubemap" resource_type="CubeMap" path="res://sb.cube"> </resource>
<real name="background/energy"> 1 </real>
<real name="background/scale"> 1 </real>
+ <real name="background/glow"> 0.6 </real>
<bool name="glow/enabled"> True </bool>
<int name="glow/blur_passes"> 2 </int>
+ <real name="glow/blur_scale"> 1.3 </real>
+ <real name="glow/blur_strength"> 1.2 </real>
+ <int name="glow/blur_blend_mode"> 1 </int>
<real name="glow/bloom"> 0 </real>
<real name="glow/bloom_treshold"> 0.5 </real>
<bool name="dof_blur/enabled"> False </bool>
@@ -150,8 +155,12 @@
<bool> False </bool>
<string> "zoom" </string>
<real> 1 </real>
+ <string> "use_snap" </string>
+ <bool> False </bool>
<string> "ofs" </string>
<vector2> 1, 1 </vector2>
+ <string> "snap" </string>
+ <int> 10 </int>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
@@ -165,15 +174,15 @@
<string> "distance" </string>
<real> 6.622579 </real>
<string> "x_rot" </string>
- <real> 1.570796 </real>
+ <real> 0.358295 </real>
<string> "y_rot" </string>
- <real> 0 </real>
+ <real> 0.45 </real>
<string> "use_orthogonal" </string>
<bool> False </bool>
<string> "use_environment" </string>
<bool> False </bool>
<string> "pos" </string>
- <vector3> 8.30511, 0.427271, 15.7846 </vector3>
+ <vector3> 9.41795, 2.98588, 13.6496 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
diff --git a/demos/3d/platformer/tiles.res b/demos/3d/platformer/tiles.res
index 9270f4c491..0ab7c92ef6 100644
--- a/demos/3d/platformer/tiles.res
+++ b/demos/3d/platformer/tiles.res
Binary files differ
diff --git a/doc/make_doc.sh b/doc/make_doc.sh
index a76f568bfc..a76f568bfc 100755..100644
--- a/doc/make_doc.sh
+++ b/doc/make_doc.sh
diff --git a/drivers/gles1/rasterizer_gles1.cpp b/drivers/gles1/rasterizer_gles1.cpp
index 60c88af508..9e13f12abe 100644
--- a/drivers/gles1/rasterizer_gles1.cpp
+++ b/drivers/gles1/rasterizer_gles1.cpp
@@ -2165,6 +2165,74 @@ int RasterizerGLES1::multimesh_get_visible_instances(RID p_multimesh) const {
}
+/* IMMEDIATE API */
+
+
+RID RasterizerGLES1::immediate_create() {
+
+ Immediate *im = memnew( Immediate );
+ return immediate_owner.make_rid(im);
+
+}
+
+void RasterizerGLES1::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){
+
+
+}
+void RasterizerGLES1::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+
+}
+void RasterizerGLES1::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+
+}
+void RasterizerGLES1::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+
+}
+void RasterizerGLES1::immediate_color(RID p_immediate,const Color& p_color){
+
+
+}
+void RasterizerGLES1::immediate_uv(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+void RasterizerGLES1::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+
+void RasterizerGLES1::immediate_end(RID p_immediate){
+
+
+}
+void RasterizerGLES1::immediate_clear(RID p_immediate) {
+
+
+}
+
+AABB RasterizerGLES1::immediate_get_aabb(RID p_immediate) const {
+
+ return AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+}
+
+void RasterizerGLES1::immediate_set_material(RID p_immediate,RID p_material) {
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ im->material=p_material;
+}
+
+RID RasterizerGLES1::immediate_get_material(RID p_immediate) const {
+
+ const Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND_V(!im,RID());
+ return im->material;
+
+}
+
/* PARTICLES API */
@@ -5327,6 +5395,12 @@ bool RasterizerGLES1::is_mesh(const RID& p_rid) const {
return mesh_owner.owns(p_rid);
}
+
+bool RasterizerGLES1::is_immediate(const RID& p_rid) const {
+
+ return immediate_owner.owns(p_rid);
+}
+
bool RasterizerGLES1::is_multimesh(const RID& p_rid) const {
return multimesh_owner.owns(p_rid);
@@ -5447,6 +5521,13 @@ void RasterizerGLES1::free(const RID& p_rid) {
particles_owner.free(p_rid);
memdelete(particles);
+ } else if (immediate_owner.owns(p_rid)) {
+
+ Immediate *immediate = immediate_owner.get(p_rid);
+ ERR_FAIL_COND(!immediate);
+
+ immediate_owner.free(p_rid);
+ memdelete(immediate);
} else if (particles_instance_owner.owns(p_rid)) {
ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid);
diff --git a/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h
index dbb411c8a3..323d00a467 100644
--- a/drivers/gles1/rasterizer_gles1.h
+++ b/drivers/gles1/rasterizer_gles1.h
@@ -371,6 +371,15 @@ class RasterizerGLES1 : public Rasterizer {
mutable RID_Owner<MultiMesh> multimesh_owner;
+
+ struct Immediate {
+
+ RID material;
+ int empty;
+ };
+
+ mutable RID_Owner<Immediate> immediate_owner;
+
struct Particles : public Geometry {
ParticleSystemSW data; // software particle system
@@ -963,6 +972,23 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create();
+ virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+ virtual void immediate_color(RID p_immediate,const Color& p_color);
+ virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_end(RID p_immediate);
+ virtual void immediate_clear(RID p_immediate);
+ virtual AABB immediate_get_aabb(RID p_immediate) const;
+ virtual void immediate_set_material(RID p_immediate,RID p_material);
+ virtual RID immediate_get_material(RID p_immediate) const;
+
+
/* PARTICLES API */
virtual RID particles_create();
@@ -1120,6 +1146,7 @@ public:
virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
+ virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {}
virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
virtual void end_scene();
@@ -1176,6 +1203,7 @@ public:
virtual bool is_material(const RID& p_rid) const;
virtual bool is_mesh(const RID& p_rid) const;
virtual bool is_multimesh(const RID& p_rid) const;
+ virtual bool is_immediate(const RID& p_rid) const;
virtual bool is_particles(const RID &p_beam) const;
virtual bool is_light(const RID& p_rid) const;
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index f43b43bd77..74a82e1a5c 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -2489,6 +2489,156 @@ int RasterizerGLES2::multimesh_get_visible_instances(RID p_multimesh) const {
}
+/* IMMEDIATE API */
+
+
+RID RasterizerGLES2::immediate_create() {
+
+ Immediate *im = memnew( Immediate );
+ return immediate_owner.make_rid(im);
+
+}
+
+void RasterizerGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(im->building);
+
+ Immediate::Chunk ic;
+ ic.texture=p_texture;
+ ic.primitive=p_rimitive;
+ im->chunks.push_back(ic);
+ im->mask=0;
+ im->building=true;
+
+
+}
+void RasterizerGLES2::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ Immediate::Chunk *c = &im->chunks.back()->get();
+
+
+ if (c->vertices.empty() && im->chunks.size()==1) {
+
+ im->aabb.pos=p_vertex;
+ im->aabb.size=Vector3();
+ } else {
+ im->aabb.expand_to(p_vertex);
+ }
+
+ if (im->mask&VS::ARRAY_FORMAT_NORMAL)
+ c->normals.push_back(chunk_normal);
+ if (im->mask&VS::ARRAY_FORMAT_TANGENT)
+ c->tangents.push_back(chunk_tangent);
+ if (im->mask&VS::ARRAY_FORMAT_COLOR)
+ c->colors.push_back(chunk_color);
+ if (im->mask&VS::ARRAY_FORMAT_TEX_UV)
+ c->uvs.push_back(chunk_uv);
+ if (im->mask&VS::ARRAY_FORMAT_TEX_UV2)
+ c->uvs2.push_back(chunk_uv2);
+ im->mask|=VS::ARRAY_FORMAT_VERTEX;
+ c->vertices.push_back(p_vertex);
+
+}
+
+
+void RasterizerGLES2::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ im->mask|=VS::ARRAY_FORMAT_NORMAL;
+ chunk_normal=p_normal;
+
+}
+void RasterizerGLES2::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ im->mask|=VS::ARRAY_FORMAT_TANGENT;
+ chunk_tangent=p_tangent;
+
+}
+void RasterizerGLES2::immediate_color(RID p_immediate,const Color& p_color){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ im->mask|=VS::ARRAY_FORMAT_COLOR;
+ chunk_color=p_color;
+
+}
+void RasterizerGLES2::immediate_uv(RID p_immediate,const Vector2& tex_uv){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ im->mask|=VS::ARRAY_FORMAT_TEX_UV;
+ chunk_uv=tex_uv;
+
+}
+void RasterizerGLES2::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ im->mask|=VS::ARRAY_FORMAT_TEX_UV2;
+ chunk_uv2=tex_uv;
+
+}
+
+void RasterizerGLES2::immediate_end(RID p_immediate){
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(!im->building);
+
+ im->building=false;
+
+}
+void RasterizerGLES2::immediate_clear(RID p_immediate) {
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ ERR_FAIL_COND(im->building);
+
+ im->chunks.clear();
+}
+
+AABB RasterizerGLES2::immediate_get_aabb(RID p_immediate) const {
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND_V(!im,AABB());
+ return im->aabb;
+}
+
+void RasterizerGLES2::immediate_set_material(RID p_immediate,RID p_material) {
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ im->material=p_material;
+
+}
+
+RID RasterizerGLES2::immediate_get_material(RID p_immediate) const {
+
+ const Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND_V(!im,RID());
+ return im->material;
+
+}
+
/* PARTICLES API */
@@ -3793,9 +3943,16 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
//print_line("UCF: "+itos(p_shader->uniforms.size()));
+ int first_tex_index=0xFFFFF;
+ p_shader->first_texture=StringName();
+
for(Map<StringName,ShaderLanguage::Uniform>::Element *E=p_shader->uniforms.front();E;E=E->next()) {
uniform_names.push_back("_"+String(E->key()));
+ if (E->get().type==ShaderLanguage::TYPE_TEXTURE && E->get().order<first_tex_index) {
+ p_shader->first_texture=E->key();
+ first_tex_index=E->get().order;
+ }
}
if (p_shader->mode==VS::SHADER_MATERIAL) {
@@ -3819,6 +3976,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
if (flags.uses_screen_uv) {
enablers.push_back("#define ENABLE_SCREEN_UV\n");
}
+ if (flags.uses_discard) {
+ enablers.push_back("#define ENABLE_DISCARD\n");
+ }
material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names,enablers);
} else {
@@ -3827,6 +3987,8 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
p_shader->valid=true;
p_shader->has_alpha=flags.uses_alpha || flags.uses_texscreen;
+ p_shader->writes_vertex=flags.vertex_code_writes_vertex;
+ p_shader->uses_discard=flags.uses_discard;
p_shader->has_texscreen=flags.uses_texscreen;
p_shader->has_screen_uv=flags.uses_screen_uv;
p_shader->can_zpass=!flags.uses_discard && !flags.vertex_code_writes_vertex;
@@ -3887,16 +4049,19 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
RenderList *render_list=NULL;
- bool has_alpha = m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || (m->shader_cache && m->shader_cache->has_alpha) || m->flags[VS::MATERIAL_FLAG_ONTOP];
+ bool has_base_alpha=(m->shader_cache && m->shader_cache->has_alpha);
+ bool has_blend_alpha=m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP];
+ bool has_alpha = has_base_alpha || has_blend_alpha;
if (shadow) {
- if (has_alpha)
+ if (has_blend_alpha || (has_base_alpha && !m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]))
return; //bye
- if (true) {
- m = shadow_mat_ptr; //for now do this always
+ if (m->shader_cache && !m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && !m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]) {
+ //shader does not use discard and does not write a vertex position, use generic material
+ m = shadow_mat_ptr;
if (m->last_pass!=frame) {
if (m->shader.is_valid()) {
@@ -3939,6 +4104,9 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
RenderList::Element *e = render_list->add_element();
+ if (!e)
+ return;
+
e->geometry=p_geometry;
e->geometry_cmp=p_geometry_cmp;
e->material=m;
@@ -3974,6 +4142,18 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
e->light_type=0xFF; // no lights!
e->light=0xFFFF;
+ if (!shadow && !has_blend_alpha && has_alpha && m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]) {
+
+ //if nothing exists, add this element as opaque too
+ RenderList::Element *oe = opaque_render_list.add_element();
+
+ if (!oe)
+ return;
+
+ memcpy(oe,e,sizeof(RenderList::Element));
+ oe->additive_ptr=&oe->additive;
+ }
+
if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED]) {
e->light_type=0x7F; //unshaded is zero
@@ -4098,6 +4278,17 @@ void RasterizerGLES2::add_multimesh( const RID& p_multimesh, const InstanceData
}
+void RasterizerGLES2::add_immediate( const RID& p_immediate, const InstanceData *p_data) {
+
+
+ Immediate *immediate = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!immediate);
+
+ _add_geometry(immediate,p_data,immediate,NULL);
+
+}
+
+
void RasterizerGLES2::add_particles( const RID& p_particle_instance, const InstanceData *p_data){
//print_line("adding particles");
@@ -4169,7 +4360,7 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
}
-bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light) {
+bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light,bool p_opaque_pass) {
if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) {
glDisable(GL_CULL_FACE);
@@ -4196,11 +4387,19 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter>SHADOW_FILTER_PCF5);
//material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,true);
+ if (p_opaque_pass && p_material->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS] && p_material->shader_cache && p_material->shader_cache->has_alpha) {
+
+ material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,true);
+ } else {
+ material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,false);
+
+ }
+
if (!shadow) {
bool depth_test=!p_material->flags[VS::MATERIAL_FLAG_ONTOP];
- bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW];
+ bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW] && (p_opaque_pass || !p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]);
if (current_depth_mask!=depth_write) {
current_depth_mask=depth_write;
@@ -4276,6 +4475,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
if (t) {
if (t->render_target)
t->render_target->last_pass=frame;
+ if (E->key()==p_material->shader_cache->first_texture) {
+ tc0_idx=texcoord;
+ tc0_id_cache=t->tex_id;
+ }
glBindTexture(t->target,t->tex_id);
} else
glBindTexture(GL_TEXTURE_2D,white_tex); //no texture
@@ -5019,6 +5222,109 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater
};
}
} break;
+ case Geometry::GEOMETRY_IMMEDIATE: {
+
+ bool restore_tex=false;
+ const Immediate *im = static_cast<const Immediate*>( p_geometry );
+ if (im->building) {
+ return;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ for(const List<Immediate::Chunk>::Element *E=im->chunks.front();E;E=E->next()) {
+
+ const Immediate::Chunk &c=E->get();
+ if (c.vertices.empty()) {
+ continue;
+ }
+ for(int i=0;i<c.vertices.size();i++)
+
+ if (c.texture.is_valid() && texture_owner.owns(c.texture)) {
+
+ const Texture *t = texture_owner.get(c.texture);
+ glActiveTexture(GL_TEXTURE0+tc0_idx);
+ glBindTexture(t->target,t->tex_id);
+ restore_tex=true;
+
+
+ } else if (restore_tex) {
+
+ glActiveTexture(GL_TEXTURE0+tc0_idx);
+ glBindTexture(GL_TEXTURE_2D,tc0_id_cache);
+ restore_tex=false;
+ }
+
+ if (!c.normals.empty()) {
+
+ glEnableVertexAttribArray(VS::ARRAY_NORMAL);
+ glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false,sizeof(Vector3),c.normals.ptr());
+
+ } else {
+
+ glDisableVertexAttribArray(VS::ARRAY_NORMAL);
+ }
+
+ if (!c.tangents.empty()) {
+
+ glEnableVertexAttribArray(VS::ARRAY_TANGENT);
+ glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false,sizeof(Plane),c.tangents.ptr());
+
+ } else {
+
+ glDisableVertexAttribArray(VS::ARRAY_TANGENT);
+ }
+
+ if (!c.colors.empty()) {
+
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false,sizeof(Color),c.colors.ptr());
+
+ } else {
+
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ _set_color_attrib(Color(1, 1, 1,1));
+ }
+
+
+ if (!c.uvs.empty()) {
+
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs.ptr());
+
+ } else {
+
+ glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
+ }
+
+ if (!c.uvs2.empty()) {
+
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV2);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs2.ptr());
+
+ } else {
+
+ glDisableVertexAttribArray(VS::ARRAY_TEX_UV2);
+ }
+
+
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false,sizeof(Vector3),c.vertices.ptr());
+ glDrawArrays(gl_primitive[c.primitive],0,c.vertices.size());
+
+
+ }
+
+
+ if (restore_tex) {
+
+ glActiveTexture(GL_TEXTURE0+tc0_idx);
+ glBindTexture(GL_TEXTURE_2D,tc0_id_cache);
+ restore_tex=false;
+ }
+
+
+ } break;
case Geometry::GEOMETRY_PARTICLES: {
@@ -5275,8 +5581,10 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
if (desired_blend) {
glEnable(GL_BLEND);
+ glColorMask(1,1,1,0);
} else {
glDisable(GL_BLEND);
+ glColorMask(1,1,1,1);
}
prev_blend=desired_blend;
@@ -5337,7 +5645,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
if (material!=prev_material || rebind) {
- rebind = _setup_material(e->geometry,material,additive);
+ rebind = _setup_material(e->geometry,material,additive,!p_alpha_pass);
DEBUG_TEST_ERROR("Setup material");
_rinfo.mat_change_count++;
@@ -5530,9 +5838,12 @@ void RasterizerGLES2::_process_glow_bloom() {
_copy_screen_quad();
copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY,false);
- copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES];
Vector2 psize(1.0/framebuffer.blur_size,1.0/framebuffer.blur_size);
+ float pscale = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE];
+ float pmag = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH];
+
for(int i=0;i<passes;i++) {
@@ -5555,6 +5866,8 @@ void RasterizerGLES2::_process_glow_bloom() {
copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS,false);
copy_shader.bind();
copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize);
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale);
+ copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,pmag);
_draw_gui_primitive(4,dst_pos,NULL,src_uv);
@@ -5565,6 +5878,8 @@ void RasterizerGLES2::_process_glow_bloom() {
copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS,true);
copy_shader.bind();
copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize);
+ copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale);
+ copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,pmag);
_draw_gui_primitive(4,dst_pos,NULL,src_uv);
@@ -5693,6 +6008,8 @@ void RasterizerGLES2::_draw_tex_bg() {
copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false);
}
+ copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true);
+
copy_shader.bind();
if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
@@ -5705,6 +6022,7 @@ void RasterizerGLES2::_draw_tex_bg() {
if (current_env->fx_enabled[VS::ENV_FX_HDR])
nrg*=0.25; //go down a quarter for hdr
copy_shader.set_uniform(CopyShaderGLES2::ENERGY,nrg);
+ copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA,float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]));
Vector3 vertices[4]={
Vector3(-1,-1,1),
@@ -5774,6 +6092,7 @@ void RasterizerGLES2::_draw_tex_bg() {
copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,false);
copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false);
copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,false);
}
void RasterizerGLES2::end_scene() {
@@ -5854,7 +6173,7 @@ void RasterizerGLES2::end_scene() {
bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
else
bgcolor = Globals::get_singleton()->get("render/default_clear_color");
- float a = use_fb ? 0.0 : 1.0;
+ float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
_glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -5923,7 +6242,7 @@ void RasterizerGLES2::end_scene() {
}
alpha_render_list.sort_z();
- _render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,false,true);
+ _render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
glColorMask(1,1,1,1);
// material_shader.set_conditional( MaterialShaderGLES2::USE_FOG,false);
@@ -5953,7 +6272,12 @@ void RasterizerGLES2::end_scene() {
_process_hdr();
}
if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
- _process_glow_bloom();
+ _process_glow_bloom();
+ int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE];
+ if (glow_transfer_mode==1)
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true);
+ if (glow_transfer_mode==2)
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,true);
}
glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
@@ -6024,6 +6348,8 @@ void RasterizerGLES2::end_scene() {
copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false);
copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false);
+ copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false);
material_shader.set_conditional(MaterialShaderGLES2::USE_HDR,false);
@@ -6216,8 +6542,8 @@ void RasterizerGLES2::end_shadow_map() {
//glDisable(GL_POLYGON_OFFSET_FILL);
- if (!use_rgba_shadowmaps)
- glColorMask(1, 1, 1, 1);
+ //if (!use_rgba_shadowmaps)
+ glColorMask(1, 1, 1, 1);
DEBUG_TEST_ERROR("Drawing Shadow");
shadow=NULL;
@@ -6436,7 +6762,10 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
case VS::MATERIAL_BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-
+ } break;
+ case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: {
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
} break;
}
@@ -6947,6 +7276,10 @@ bool RasterizerGLES2::is_mesh(const RID& p_rid) const {
return mesh_owner.owns(p_rid);
}
+bool RasterizerGLES2::is_immediate(const RID& p_rid) const {
+
+ return immediate_owner.owns(p_rid);
+}
bool RasterizerGLES2::is_multimesh(const RID& p_rid) const {
return multimesh_owner.owns(p_rid);
@@ -7071,6 +7404,13 @@ void RasterizerGLES2::free(const RID& p_rid) {
multimesh_owner.free(p_rid);
memdelete(multimesh);
+ } else if (immediate_owner.owns(p_rid)) {
+
+ Immediate *immediate = immediate_owner.get(p_rid);
+ ERR_FAIL_COND(!immediate);
+
+ immediate_owner.free(p_rid);
+ memdelete(immediate);
} else if (particles_owner.owns(p_rid)) {
Particles *particles = particles_owner.get(p_rid);
@@ -8118,6 +8458,8 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
draw_next_frame=false;
use_framebuffers=true;
framebuffer.active=false;
+ tc0_id_cache=0;
+ tc0_idx=0;
};
RasterizerGLES2::~RasterizerGLES2() {
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index 673297dd51..0fee8bf918 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -173,8 +173,11 @@ class RasterizerGLES2 : public Rasterizer {
bool can_zpass;
bool has_texscreen;
bool has_screen_uv;
+ bool writes_vertex;
+ bool uses_discard;
Map<StringName,ShaderLanguage::Uniform> uniforms;
+ StringName first_texture;
SelfList<Shader> dirty_list;
@@ -190,6 +193,8 @@ class RasterizerGLES2 : public Rasterizer {
can_zpass=true;
has_texscreen=false;
has_screen_uv=false;
+ writes_vertex=false;
+ uses_discard=false;
}
@@ -235,6 +240,7 @@ class RasterizerGLES2 : public Rasterizer {
flags[VS::MATERIAL_FLAG_VISIBLE]=true;
for(int i=0;i<VS::MATERIAL_HINT_MAX;i++)
hints[i]=false;
+ hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]=true;
line_width=1;
has_alpha=false;
@@ -256,7 +262,7 @@ class RasterizerGLES2 : public Rasterizer {
enum Type {
GEOMETRY_INVALID,
GEOMETRY_SURFACE,
- GEOMETRY_POLY,
+ GEOMETRY_IMMEDIATE,
GEOMETRY_PARTICLES,
GEOMETRY_MULTISURFACE,
};
@@ -457,6 +463,31 @@ class RasterizerGLES2 : public Rasterizer {
mutable RID_Owner<MultiMesh> multimesh_owner;
mutable SelfList<MultiMesh>::List _multimesh_dirty_list;
+ struct Immediate : public Geometry {
+
+ struct Chunk {
+
+ RID texture;
+ VS::PrimitiveType primitive;
+ Vector<Vector3> vertices;
+ Vector<Vector3> normals;
+ Vector<Plane> tangents;
+ Vector<Color> colors;
+ Vector<Vector2> uvs;
+ Vector<Vector2> uvs2;
+ };
+
+ List<Chunk> chunks;
+ bool building;
+ int mask;
+ AABB aabb;
+
+ Immediate() { type=GEOMETRY_IMMEDIATE; building=false;}
+
+ };
+
+ mutable RID_Owner<Immediate> immediate_owner;
+
struct Particles : public Geometry {
ParticleSystemSW data; // software particle system
@@ -585,11 +616,15 @@ class RasterizerGLES2 : public Rasterizer {
bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID();
bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0;
bg_param[VS::ENV_BG_PARAM_SCALE]=1.0;
+ bg_param[VS::ENV_BG_PARAM_GLOW]=0.0;
for(int i=0;i<VS::ENV_FX_MAX;i++)
fx_enabled[i]=false;
fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1;
+ fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE]=1.0;
+ fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH]=1.0;
+ fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]=0;
fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0;
fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5;
fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1;
@@ -932,7 +967,7 @@ class RasterizerGLES2 : public Rasterizer {
void _setup_light(uint16_t p_light);
_FORCE_INLINE_ void _setup_shader_params(const Material *p_material);
- bool _setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light);
+ bool _setup_material(const Geometry *p_geometry, const Material *p_material, bool p_no_const_light, bool p_opaque_pass);
void _setup_skeleton(const Skeleton *p_skeleton);
@@ -1096,6 +1131,16 @@ class RasterizerGLES2 : public Rasterizer {
void _copy_screen_quad();
void _copy_to_texscreen();
+
+ Vector3 chunk_vertex;
+ Vector3 chunk_normal;
+ Plane chunk_tangent;
+ Color chunk_color;
+ Vector2 chunk_uv;
+ Vector2 chunk_uv2;
+ GLuint tc0_id_cache;
+ GLuint tc0_idx;
+
public:
/* TEXTURE API */
@@ -1205,6 +1250,22 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create();
+ virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+ virtual void immediate_color(RID p_immediate,const Color& p_color);
+ virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_end(RID p_immediate);
+ virtual void immediate_clear(RID p_immediate);
+ virtual AABB immediate_get_aabb(RID p_immediate) const;
+ virtual void immediate_set_material(RID p_immediate,RID p_material);
+ virtual RID immediate_get_material(RID p_immediate) const;
+
/* PARTICLES API */
virtual RID particles_create();
@@ -1364,6 +1425,7 @@ public:
virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
+ virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data);
virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
virtual void end_scene();
@@ -1411,6 +1473,7 @@ public:
virtual bool is_texture(const RID& p_rid) const;
virtual bool is_material(const RID& p_rid) const;
virtual bool is_mesh(const RID& p_rid) const;
+ virtual bool is_immediate(const RID& p_rid) const;
virtual bool is_multimesh(const RID& p_rid) const;
virtual bool is_particles(const RID &p_beam) const;
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 6dc6259fef..db63c3aeba 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -145,6 +145,12 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
} break;
case SL::Node::TYPE_VARIABLE: {
SL::VariableNode *vnode=(SL::VariableNode*)p_node;
+ if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) {
+
+ if (vnode->name==vname_vertex && p_assign_left) {
+ vertex_code_writes_vertex=true;
+ }
+ }
if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) {
if (vnode->name==vname_discard) {
@@ -644,5 +650,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
vname_binormal_interp="BINORMAL";
vname_var1_interp="VAR1";
vname_var2_interp="VAR2";
+ vname_vertex="VERTEX";
}
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 2f4aa7647e..d683f5b4f3 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -61,6 +61,7 @@ private:
StringName vname_binormal_interp;
StringName vname_var1_interp;
StringName vname_var2_interp;
+ StringName vname_vertex;
Map<StringName,ShaderLanguage::Uniform> *uniforms;
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index d665fddd2c..bcd3e6ad4b 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -315,6 +315,7 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() {
for(int i=0;i<cc->custom_defines.size();i++) {
strings.push_back(cc->custom_defines[i]);
+ DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i]));
}
}
@@ -349,9 +350,11 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() {
strings.push_back(vertex_code2.get_data());
#ifdef DEBUG_SHADER
+
+ DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data()));
for(int i=0;i<strings.size();i++) {
- print_line("vert strings "+itos(i)+":"+String(strings[i]));
+ //print_line("vert strings "+itos(i)+":"+String(strings[i]));
}
#endif
@@ -435,9 +438,10 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() {
strings.push_back(fragment_code2.get_data());
#ifdef DEBUG_SHADER
+ DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data()));
for(int i=0;i<strings.size();i++) {
- print_line("frag strings "+itos(i)+":"+String(strings[i]));
+ //print_line("frag strings "+itos(i)+":"+String(strings[i]));
}
#endif
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 66bdf15db4..f36741d586 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -64,6 +64,9 @@ void main() {
highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) );
color = vec4(vec3(enc32),1.0);
#endif
+
+// color.rgb*=color.a;
gl_FragColor = color;
+
}
diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl
index bea651bceb..2f1b349618 100644
--- a/drivers/gles2/shaders/copy.glsl
+++ b/drivers/gles2/shaders/copy.glsl
@@ -99,6 +99,8 @@ uniform float bloom_treshold;
#if defined(BLUR_V_PASS) || defined(BLUR_H_PASS) || defined(USE_HDR_REDUCE)
uniform vec2 pixel_size;
+uniform float pixel_scale;
+uniform float blur_magnitude;
#ifdef USE_HDR_STORE
@@ -123,6 +125,10 @@ uniform highp float energy;
#endif
+#ifdef USE_CUSTOM_ALPHA
+uniform float custom_alpha;
+#endif
+
void main() {
@@ -195,28 +201,28 @@ void main() {
#ifdef BLUR_V_PASS
- color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0));
- color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0));
- color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0));
- color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0));
- color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0));
- color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0));
+ color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale);
- color*=(1.0/7.0);
+ color*=(1.0/7.0)*blur_magnitude;
#endif
#ifdef BLUR_H_PASS
- color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0));
- color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0));
- color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0));
- color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0));
- color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0));
- color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0));
+ color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale);
+ color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale);
- color*=(1.0/7.0);
+ color*=(1.0/7.0)*blur_magnitude;
#endif
@@ -249,12 +255,25 @@ void main() {
vec4 glow = texture2D( glow_source, uv2_interp );
-#if 1
-//ifdef USE_GLOW_SCREEN
+#ifdef USE_GLOW_SCREEN
color.rgb = clamp((color.rgb + glow.rgb) - (color.rgb * glow.rgb), 0.0, 1.0);
-#else
+#endif
+
+#ifdef USE_GLOW_SOFTLIGHT
+
+ {
+
+ glow.rgb = (glow.rgb * 0.5) + 0.5;
+ color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r)));
+ color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g)));
+ color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b)));
+ }
+
+#endif
+
+#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT)
color.rgb+=glow.rgb;
#endif
@@ -316,6 +335,9 @@ void main() {
color.a=1.0;
#endif
+#ifdef USE_CUSTOM_ALPHA
+ color.a=custom_alpha;
+#endif
gl_FragColor = color;
}
diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl
index 1794f18801..a919e3b1e2 100644
--- a/drivers/gles2/shaders/material.glsl
+++ b/drivers/gles2/shaders/material.glsl
@@ -386,6 +386,7 @@ VERTEX_SHADER_CODE
specular_interp=vec3(0.0);
}
}
+
#else
#ifdef SHADELESS
@@ -722,21 +723,28 @@ void main() {
-#ifdef FRAGMENT_SHADER_CODE_USE_DISCARD
- float discard_=0.0;
+#if defined(ENABLE_DISCARD)
+ bool discard_=false;
#endif
FRAGMENT_SHADER_CODE
-#ifdef FRAGMENT_SHADER_CODE_USE_DISCARD
- if (discard_>0.0) {
+#if defined(ENABLE_DISCARD)
+ if (discard_) {
//easy to eliminate dead code
discard;
}
#endif
+#ifdef ENABLE_CLIP_ALPHA
+ if (diffuse.a<0.99) {
+ //used for doublepass and shadowmapping
+ discard;
+ }
+#endif
+
float shadow_attenuation = 1.0;
@@ -902,7 +910,10 @@ FRAGMENT_SHADER_CODE
# if !defined(LIGHT_TYPE_DIRECTIONAL) && !defined(LIGHT_TYPE_OMNI) && !defined (LIGHT_TYPE_SPOT)
//none
+#ifndef SHADELESS
diffuse.rgb=vec3(0.0,0.0,0.0);
+#endif
+
# endif
diffuse.rgb+=const_light_mult*emission;
@@ -959,6 +970,7 @@ FRAGMENT_SHADER_CODE
#ifdef USE_HDR
diffuse.rgb*=0.25;
#endif
+
gl_FragColor = diffuse;
#endif
}
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index fff86c5a7e..452d791d96 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -81,6 +81,26 @@ bool DirAccessUnix::file_exists(String p_file) {
}
+bool DirAccessUnix::dir_exists(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+
+
+ if (p_dir.is_rel_path())
+ p_dir=current_dir+"/"+p_dir;
+ else
+ p_dir=fix_path(p_dir);
+
+ struct stat flags;
+ bool success = (stat(p_dir.utf8().get_data(),&flags)==0);
+
+ if (success && S_ISDIR(flags.st_mode))
+ return true;
+
+ return false;
+
+}
+
uint64_t DirAccessUnix::get_modified_time(String p_file) {
if (p_file.is_rel_path())
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 7ede4fc31c..119cb5c3f4 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -66,7 +66,9 @@ public:
virtual String get_current_dir(); ///< return current dir location
virtual Error make_dir(String p_dir);
- virtual bool file_exists(String p_file);
+ virtual bool file_exists(String p_file);
+ virtual bool dir_exists(String p_dir);
+
virtual uint64_t get_modified_time(String p_file);
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index c11426d356..18b19ca095 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -30,12 +30,24 @@
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
+
#ifdef WINDOWS_ENABLED
+#define WINVER 0x0600
#include <ws2tcpip.h>
#include <winsock2.h>
#include <windows.h>
+#include <stdio.h>
+#include <iphlpapi.h>
#else
#include <netdb.h>
+#ifdef ANDROID_ENABLED
+#include "platform/android/ifaddrs_android.h"
+#else
+#include <ifaddrs.h>
+#endif
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
#endif
IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
@@ -52,6 +64,93 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
}
+#if defined(WINDOWS_ENABLED)
+
+void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
+
+ ULONG buf_size = 1024;
+ IP_ADAPTER_ADDRESSES* addrs;
+
+ while (true) {
+
+ addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size);
+ int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST |
+ GAA_FLAG_SKIP_MULTICAST |
+ GAA_FLAG_SKIP_DNS_SERVER |
+ GAA_FLAG_SKIP_FRIENDLY_NAME,
+ NULL, addrs, &buf_size);
+ if (err == NO_ERROR) {
+ break;
+ };
+ memfree(addrs);
+ if (err == ERROR_BUFFER_OVERFLOW) {
+ continue; // will go back and alloc the right size
+ };
+
+ ERR_EXPLAIN("Call to GetAdaptersAddresses failed with error " + itos(err));
+ ERR_FAIL();
+ return;
+ };
+
+
+ IP_ADAPTER_ADDRESSES* adapter = addrs;
+
+ while (adapter != NULL) {
+
+ IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
+ while (address != NULL) {
+
+ char addr_chr[INET_ADDRSTRLEN];
+ SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
+
+ IP_Address ip;
+ ip.host= *((unsigned long*)&ipv4->sin_addr);
+
+
+ //inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN);
+
+ r_addresses->push_back(ip);
+
+ address = address->Next;
+ };
+ adapter = adapter->Next;
+ };
+
+ memfree(addrs);
+};
+
+
+#else
+
+void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
+
+ struct ifaddrs * ifAddrStruct=NULL;
+ struct ifaddrs * ifa=NULL;
+
+ getifaddrs(&ifAddrStruct);
+
+ for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
+ // is a valid IP4 Address
+
+ IP_Address ip;
+ ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr);
+
+ r_addresses->push_back(ip);
+ }/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6
+ // is a valid IP6 Address
+ tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ char addressBuffer[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
+ printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
+ } */
+ }
+
+ if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
+
+}
+#endif
+
void IP_Unix::make_default() {
_create=_create_unix;
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index ec2d42c837..2fd5cf964b 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -41,6 +41,8 @@ class IP_Unix : public IP {
static IP* _create_unix();
public:
+ virtual void get_local_addresses(List<IP_Address> *r_addresses) const;
+
static void make_default();
IP_Unix();
};
diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp
index f91ad36ef9..dfcf479fc0 100644
--- a/drivers/unix/tcp_server_posix.cpp
+++ b/drivers/unix/tcp_server_posix.cpp
@@ -93,6 +93,9 @@ Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_host
close(sockfd);
ERR_FAIL_V(FAILED);
};
+ }
+ else {
+ return ERR_ALREADY_IN_USE;
};
if (listen_sockfd != -1) {
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 30f6ff6d8c..aacd02ca24 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -303,6 +303,39 @@ bool DirAccessWindows::file_exists(String p_file) {
return false;
}
+bool DirAccessWindows::dir_exists(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+
+ if (!p_dir.is_abs_path())
+ p_dir=get_current_dir()+"/"+p_dir;
+ p_dir=fix_path(p_dir);
+
+ p_dir.replace("/","\\");
+
+ if (unicode) {
+
+ DWORD fileAttr;
+
+ fileAttr = GetFileAttributesW(p_dir.c_str());
+ if (0xFFFFFFFF == fileAttr)
+ return false;
+
+ return (fileAttr&FILE_ATTRIBUTE_DIRECTORY);
+
+ } else {
+ DWORD fileAttr;
+
+ fileAttr = GetFileAttributesA(p_dir.ascii().get_data());
+ if (0xFFFFFFFF == fileAttr)
+ return false;
+ return (fileAttr&FILE_ATTRIBUTE_DIRECTORY);
+
+ }
+
+ return false;
+}
+
Error DirAccessWindows::rename(String p_path,String p_new_path) {
p_path=fix_path(p_path);
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 926497c583..36530ba9b3 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -74,6 +74,7 @@ public:
virtual bool file_exists(String p_file);
+ virtual bool dir_exists(String p_dir);
virtual Error make_dir(String p_dir);
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp
index 48f0092827..f1b7ad0096 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -1263,6 +1263,16 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
gdfunc->name=func_name;
gdfunc->_script=p_script;
gdfunc->source=source;
+
+#ifdef DEBUG_ENABLED
+
+ {
+ gdfunc->func_cname=(String(source)+" - "+String(func_name)).utf8();
+ gdfunc->_func_cname=gdfunc->func_cname.get_data();
+
+ }
+
+#endif
if (p_func) {
gdfunc->_initial_line=p_func->line;
} else {
@@ -1311,6 +1321,16 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
if (path!="") {
//path (and optionally subclasses)
+ if (path.is_rel_path()) {
+
+ String base = p_script->get_path();
+ if (base=="" || base.is_rel_path()) {
+ _set_error("Could not resolve relative path for parent class: "+path,p_class);
+ return ERR_FILE_NOT_FOUND;
+ }
+ path=base.get_base_dir().plus_file(path);
+ }
+
script = ResourceLoader::load(path);
if (script.is_null()) {
_set_error("Could not load base class: "+path,p_class);
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index f8717c292f..5f5de8b5db 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -787,3 +787,67 @@ Error GDScriptLanguage::complete_keyword(const String& p_code, int p_line, const
return OK;
}
+void GDScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_line) const {
+
+
+ Vector<String> lines = p_code.split("\n");
+ List<int> indent_stack;
+
+ for(int i=0;i<lines.size();i++) {
+
+ String l = lines[i];
+ int tc=0;
+ for(int j=0;j<l.length();j++) {
+ if (l[j]==' ' || l[j]=='\t') {
+
+ tc++;
+ } else {
+ break;
+ }
+ }
+
+
+ String st = l.substr(tc,l.length()).strip_edges();
+ if (st=="" || st.begins_with("#"))
+ continue; //ignore!
+
+ int ilevel=0;
+ if (indent_stack.size()) {
+ ilevel=indent_stack.back()->get();
+ }
+
+ if (tc>ilevel) {
+ indent_stack.push_back(tc);
+ } else if (tc<ilevel) {
+ while(indent_stack.size() && indent_stack.back()->get()>tc) {
+ indent_stack.pop_back();
+ }
+
+ if (indent_stack.size() && indent_stack.back()->get()!=tc)
+ indent_stack.push_back(tc); //this is not right but gets the job done
+ }
+
+ if (i>=p_from_line) {
+
+ l="";
+ for(int j=0;j<indent_stack.size();j++)
+ l+="\t";
+ l+=st;
+
+
+ } else if (i>p_to_line) {
+ break;
+ }
+
+ //print_line(itos(indent_stack.size())+","+itos(tc)+": "+l);
+ lines[i]=l;
+ }
+
+ p_code="";
+ for(int i=0;i<lines.size();i++) {
+ if (i>0)
+ p_code+="\n";
+ p_code+=lines[i];
+ }
+
+}
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index f540660cd3..2829132d99 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -1221,6 +1221,15 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
return; //go back a level
}
+ if (pending_newline!=-1) {
+
+ NewLineNode *nl = alloc_node<NewLineNode>();
+ nl->line=pending_newline;
+ p_block->statements.push_back(nl);
+ pending_newline=-1;
+
+ }
+
switch(token) {
@@ -1234,16 +1243,19 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
} break;
case GDTokenizer::TK_NEWLINE: {
- NewLineNode *nl = alloc_node<NewLineNode>();
- nl->line=tokenizer->get_token_line();
- p_block->statements.push_back(nl);
-
if (!_parse_newline()) {
if (!error_set) {
p_block->end_line=tokenizer->get_token_line();
+ pending_newline=p_block->end_line;
+
}
return;
}
+
+ NewLineNode *nl = alloc_node<NewLineNode>();
+ nl->line=tokenizer->get_token_line();
+ p_block->statements.push_back(nl);
+
} break;
case GDTokenizer::TK_CF_PASS: {
if (tokenizer->get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE ) {
@@ -1782,6 +1794,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
case GDTokenizer::TK_PR_FUNCTION: {
bool _static=false;
+ pending_newline=-1;
if (tokenizer->get_token(-1)==GDTokenizer::TK_PR_STATIC) {
@@ -2490,6 +2503,7 @@ void GDParser::clear() {
tab_level.push_back(0);
error_line=0;
error_column=0;
+ pending_newline=-1;
parenthesis=0;
current_export.type=Variant::NIL;
error="";
@@ -2501,6 +2515,7 @@ GDParser::GDParser() {
head=NULL;
list=NULL;
tokenizer=NULL;
+ pending_newline=-1;
clear();
}
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 278e5f543d..825bd954d1 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -362,6 +362,8 @@ private:
int error_line;
int error_column;
+ int pending_newline;
+
List<int> tab_level;
String base_path;
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index c6183aadc4..d183782864 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -389,6 +389,8 @@ Variant GDFunction::call(GDInstance *p_instance,const Variant **p_args, int p_ar
}
}
+
+
} else {
GDNativeClass *nc= obj_B->cast_to<GDNativeClass>();
@@ -1159,6 +1161,9 @@ GDFunction::GDFunction() {
_stack_size=0;
_call_size=0;
name="<anonymous>";
+#ifdef DEBUG_ENABLED
+ _func_cname=NULL;
+#endif
}
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 983899240a..56da0bb2e3 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -118,10 +118,13 @@ friend class GDCompiler;
Vector<Variant> constants;
Vector<StringName> global_names;
Vector<int> default_arguments;
-
Vector<int> code;
+#ifdef DEBUG_ENABLED
+ CharString func_cname;
+ const char*_func_cname;
+#endif
- List<StackDebug> stack_debug;
+ List<StackDebug> stack_debug;
_FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const;
_FORCE_INLINE_ String _get_call_error(const Variant::CallError& p_err, const String& p_where,const Variant**argptrs) const;
@@ -427,6 +430,7 @@ public:
virtual int find_function(const String& p_function,const String& p_code) const;
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const;
virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path,const String& p_keyword, List<String>* r_options);
+ virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const;
/* DEBUGGER FUNCTIONS */
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 5464376c31..8e61b7d8e0 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -13,6 +13,7 @@ android_files = [
'dir_access_jandroid.cpp',
'thread_jandroid.cpp',
'audio_driver_jandroid.cpp',
+ 'ifaddrs_android.cpp',
'android_native_app_glue.c',
'java_glue.cpp'
]
diff --git a/platform/android/detect.py b/platform/android/detect.py
index cd7f0d8de5..c9b21626c3 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -25,8 +25,9 @@ def get_opts():
#android 2.3
('ndk_platform', 'compile for platform: (2.2,2.3)',"2.2"),
('NDK_TARGET', 'toolchain to use for the NDK',"arm-linux-androideabi-4.8"),
- ('android_stl','enable STL support in android port (for modules)','no'),
- ('armv6','compile for older phones running arm v6 (instead of v7+neon+smp)','no')
+ ('android_stl','enable STL support in android port (for modules)','no'),
+ ('armv6','compile for older phones running arm v6 (instead of v7+neon+smp)','no'),
+ ('x86','compile for x86','no')
]
@@ -52,6 +53,9 @@ def create(env):
def configure(env):
+ if env['x86']=='yes':
+ env['NDK_TARGET']='x86-4.8'
+
if env['PLATFORM'] == 'win32':
import methods
env.Tool('gcc')
@@ -67,8 +71,12 @@ def configure(env):
env.Append(CPPPATH=['#platform/android'])
- env['OBJSUFFIX'] = ".android.o"
- env['LIBSUFFIX'] = ".android.a"
+ if env['x86']=='yes':
+ env['OBJSUFFIX'] = ".android.ox"
+ env['LIBSUFFIX'] = ".android.ax"
+ else:
+ env['OBJSUFFIX'] = ".android.o"
+ env['LIBSUFFIX'] = ".android.a"
env['PROGSUFFIX'] = ".android"
env['SHLIBSUFFIX'] = ".so"
@@ -89,23 +97,36 @@ def configure(env):
env['ENV']['PATH'] = gcc_path+":"+env['ENV']['PATH']
-
- env['CC'] = gcc_path+'/arm-linux-androideabi-gcc'
- env['CXX'] = gcc_path+'/arm-linux-androideabi-g++'
- env['AR'] = gcc_path+"/arm-linux-androideabi-ar"
- env['RANLIB'] = gcc_path+"/arm-linux-androideabi-ranlib"
- env['AS'] = gcc_path+"/arm-linux-androideabi-as"
+ if env['x86']=='yes':
+ env['CC'] = gcc_path+'/i686-linux-android-gcc'
+ env['CXX'] = gcc_path+'/i686-linux-android-g++'
+ env['AR'] = gcc_path+"/i686-linux-android-ar"
+ env['RANLIB'] = gcc_path+"/i686-linux-android-ranlib"
+ env['AS'] = gcc_path+"/i686-linux-android-as"
+ else:
+ env['CC'] = gcc_path+'/arm-linux-androideabi-gcc'
+ env['CXX'] = gcc_path+'/arm-linux-androideabi-g++'
+ env['AR'] = gcc_path+"/arm-linux-androideabi-ar"
+ env['RANLIB'] = gcc_path+"/arm-linux-androideabi-ranlib"
+ env['AS'] = gcc_path+"/arm-linux-androideabi-as"
+
+ if env['x86']=='yes':
+ env['ARCH'] = 'arch-x86'
+ else:
+ env['ARCH'] = 'arch-arm'
import string
#include path
- gcc_include=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/arch-arm/usr/include"
- ld_sysroot=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/arch-arm"
+ gcc_include=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/"+env['ARCH'] +"/usr/include"
+ ld_sysroot=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/"+env['ARCH']
#glue_include=env["ANDROID_NDK_ROOT"]+"/sources/android/native_app_glue"
- ld_path=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/arch-arm/usr/lib"
+ ld_path=env["ANDROID_NDK_ROOT"]+"/platforms/"+ndk_platform+"/"+env['ARCH']+"/usr/lib"
env.Append(CPPPATH=[gcc_include])
# env['CCFLAGS'] = string.split('-DNO_THREADS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -mthumb -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED ')
print("********* armv6", env['armv6'])
- if env["armv6"]!="no":
+ if env['x86']=='yes':
+ env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED')
+ elif env["armv6"]!="no":
env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED')
else:
env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_7__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED')
@@ -146,7 +167,7 @@ def configure(env):
env.Append(CCFLAGS=['-D_DEBUG', '-g1', '-Wall', '-O0', '-DDEBUG_ENABLED'])
env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
- if env["armv6"] == "no":
+ if env["armv6"] == "no" and env['x86'] != 'yes':
env['neon_enabled']=True
env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL','-DMPC_FIXED_POINT'])
# env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED','-DMPC_FIXED_POINT'])
@@ -165,7 +186,10 @@ def configure(env):
env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"]+"/sources/cxx-stl/gabi++/include"])
env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"]+"/sources/cpufeatures"])
- env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"]+"/sources/cxx-stl/gabi++/libs/armeabi"])
+ if env['x86']=='yes':
+ env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"]+"/sources/cxx-stl/gabi++/libs/x86"])
+ else:
+ env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"]+"/sources/cxx-stl/gabi++/libs/armeabi"])
env.Append(LIBS=['gabi++_static'])
env.Append(CCFLAGS=["-fno-exceptions",'-DNO_SAFE_CAST'])
@@ -173,4 +197,3 @@ def configure(env):
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/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 0c8a5785f8..f32e16e7d8 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -179,6 +179,32 @@ bool DirAccessJAndroid::file_exists(String p_file){
return exists;
}
+bool DirAccessJAndroid::dir_exists(String p_dir) {
+
+ JNIEnv *env = ThreadAndroid::get_env();
+
+ String sd;
+ if (current_dir=="")
+ sd=p_dir;
+ else
+ sd=current_dir+"/"+p_dir;
+
+ String path=fix_path(sd).simplify_path();
+ if (path.begins_with("/"))
+ path=path.substr(1,path.length());
+ else if (path.begins_with("res://"))
+ path=path.substr(6,path.length());
+
+ jstring js = env->NewStringUTF(path.utf8().get_data());
+ int res = env->CallIntMethod(io,_dir_open,js);
+ if (res<=0)
+ return false;
+
+ env->CallVoidMethod(io,_dir_close,res);
+ env->DeleteLocalRef(js);
+
+ return true;
+}
Error DirAccessJAndroid::make_dir(String p_dir){
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index b6e3fe393f..958ea34891 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -70,6 +70,7 @@ public:
virtual bool file_exists(String p_file);
+ virtual bool dir_exists(String p_dir);
virtual Error make_dir(String p_dir);
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 3b6a62898e..d1ee7087e7 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -189,6 +189,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int orientation;
String release_keystore;
+ String release_password;
String release_username;
struct APKExportData {
@@ -241,11 +242,11 @@ public:
virtual int get_device_count() const;
virtual String get_device_name(int p_device) const;
virtual String get_device_info(int p_device) const;
- virtual Error run(int p_device);
+ virtual Error run(int p_device,bool p_dumb=false);
virtual bool requieres_password(bool p_debug) const { return !p_debug; }
virtual String get_binary_extension() const { return "apk"; }
- virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+ virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual bool can_export(String *r_error=NULL) const;
@@ -285,6 +286,8 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
release_keystore=p_value;
else if (n=="keystore/release_user")
release_username=p_value;
+ else if (n=="keystore/release_password")
+ release_password=p_value;
else if (n=="apk_expansion/enable")
apk_expansion=p_value;
else if (n=="apk_expansion/SALT")
@@ -343,6 +346,8 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
r_ret=release_keystore;
else if (n=="keystore/release_user")
r_ret=release_username;
+ else if (n=="keystore/release_password")
+ r_ret=release_password;
else if (n=="apk_expansion/enable")
r_ret=apk_expansion;
else if (n=="apk_expansion/SALT")
@@ -968,7 +973,7 @@ Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String&
-Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, bool p_dumb) {
String src_apk;
@@ -1088,34 +1093,51 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_de
ep.step("Adding Files..",1);
-
Error err=OK;
Vector<String> cl = cmdline.strip_edges().split(" ");
- if (apk_expansion) {
- String apkfname="main."+itos(version_code)+"."+package+".obb";
- String fullpath=p_path.get_base_dir().plus_file(apkfname);
- FileAccess *pf = FileAccess::open(fullpath,FileAccess::WRITE);
- if (!pf) {
- EditorNode::add_io_error("Could not write expansion package file: "+apkfname);
- return OK;
+ if (p_dumb) {
+
+ String host = EditorSettings::get_singleton()->get("file_server/host");
+ int port = EditorSettings::get_singleton()->get("file_server/post");
+ String passwd = EditorSettings::get_singleton()->get("file_server/password");
+ cl.push_back("-rfs");
+ cl.push_back(host+":"+itos(port));
+ if (passwd!="") {
+ cl.push_back("-rfs_pass");
+ cl.push_back(passwd);
}
- err = save_pack(pf);
- memdelete(pf);
- cl.push_back("-main_pack");
- cl.push_back(apkfname);
- cl.push_back("-main_pack_md5");
- cl.push_back(FileAccess::get_md5(fullpath));
- cl.push_back("-main_pack_cfg");
- cl.push_back(apk_expansion_salt+","+apk_expansion_pkey);
+
} else {
+ //all files
- APKExportData ed;
- ed.ep=&ep;
- ed.apk=apk;
+ if (apk_expansion) {
- err = export_project_files(save_apk_file,&ed,false);
+ String apkfname="main."+itos(version_code)+"."+package+".obb";
+ String fullpath=p_path.get_base_dir().plus_file(apkfname);
+ FileAccess *pf = FileAccess::open(fullpath,FileAccess::WRITE);
+ if (!pf) {
+ EditorNode::add_io_error("Could not write expansion package file: "+apkfname);
+ return OK;
+ }
+ err = save_pack(pf);
+ memdelete(pf);
+ cl.push_back("-main_pack");
+ cl.push_back(apkfname);
+ cl.push_back("-main_pack_md5");
+ cl.push_back(FileAccess::get_md5(fullpath));
+ cl.push_back("-main_pack_cfg");
+ cl.push_back(apk_expansion_salt+","+apk_expansion_pkey);
+
+ } else {
+
+ APKExportData ed;
+ ed.ep=&ep;
+ ed.apk=apk;
+
+ err = export_project_files(save_apk_file,&ed,false);
+ }
}
if (cl.size()) {
@@ -1179,7 +1201,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_de
} else {
keystore=release_keystore;
- password=p_password;
+ password=release_password;
user=release_username;
ep.step("Signing Release APK..",103);
@@ -1388,7 +1410,7 @@ void EditorExportPlatformAndroid::_device_poll_thread(void *ud) {
}
-Error EditorExportPlatformAndroid::run(int p_device) {
+Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) {
ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
device_lock->lock();
@@ -1407,7 +1429,7 @@ Error EditorExportPlatformAndroid::run(int p_device) {
ep.step("Exporting APK",0);
String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
- Error err = export_project(export_to,true);
+ Error err = export_project(export_to,true,p_dumb);
if (err) {
device_lock->unlock();
return err;
diff --git a/platform/android/ifaddrs_android.cpp b/platform/android/ifaddrs_android.cpp
new file mode 100644
index 0000000000..c1e9eb3584
--- /dev/null
+++ b/platform/android/ifaddrs_android.cpp
@@ -0,0 +1,221 @@
+/*
+ * libjingle
+ * Copyright 2012, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ifaddrs_android.h"
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+struct netlinkrequest {
+ nlmsghdr header;
+ ifaddrmsg msg;
+};
+namespace {
+const int kMaxReadSize = 4096;
+};
+static int set_ifname(struct ifaddrs* ifaddr, int interface) {
+ char buf[IFNAMSIZ] = {0};
+ char* name = if_indextoname(interface, buf);
+ if (name == NULL) {
+ return -1;
+ }
+ ifaddr->ifa_name = new char[strlen(name) + 1];
+ strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
+ return 0;
+}
+static int set_flags(struct ifaddrs* ifaddr) {
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1);
+ int rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
+ close(fd);
+ if (rc == -1) {
+ return -1;
+ }
+ ifaddr->ifa_flags = ifr.ifr_flags;
+ return 0;
+}
+static int set_addresses(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* data,
+ size_t len) {
+ if (msg->ifa_family == AF_INET) {
+ sockaddr_in* sa = new sockaddr_in;
+ sa->sin_family = AF_INET;
+ memcpy(&sa->sin_addr, data, len);
+ ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(sa);
+ } else if (msg->ifa_family == AF_INET6) {
+ sockaddr_in6* sa = new sockaddr_in6;
+ sa->sin6_family = AF_INET6;
+ sa->sin6_scope_id = msg->ifa_index;
+ memcpy(&sa->sin6_addr, data, len);
+ ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(sa);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+static int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) {
+ char* prefix = NULL;
+ if (family == AF_INET) {
+ sockaddr_in* mask = new sockaddr_in;
+ mask->sin_family = AF_INET;
+ memset(&mask->sin_addr, 0, sizeof(in_addr));
+ ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
+ if (prefixlen > 32) {
+ prefixlen = 32;
+ }
+ prefix = reinterpret_cast<char*>(&mask->sin_addr);
+ } else if (family == AF_INET6) {
+ sockaddr_in6* mask = new sockaddr_in6;
+ mask->sin6_family = AF_INET6;
+ memset(&mask->sin6_addr, 0, sizeof(in6_addr));
+ ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
+ if (prefixlen > 128) {
+ prefixlen = 128;
+ }
+ prefix = reinterpret_cast<char*>(&mask->sin6_addr);
+ } else {
+ return -1;
+ }
+ for (int i = 0; i < (prefixlen / 8); i++) {
+ *prefix++ = 0xFF;
+ }
+ char remainder = 0xff;
+ remainder <<= (8 - prefixlen % 8);
+ *prefix = remainder;
+ return 0;
+}
+static int populate_ifaddrs(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* bytes,
+ size_t len) {
+ if (set_ifname(ifaddr, msg->ifa_index) != 0) {
+ return -1;
+ }
+ if (set_flags(ifaddr) != 0) {
+ return -1;
+ }
+ if (set_addresses(ifaddr, msg, bytes, len) != 0) {
+ return -1;
+ }
+ if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) {
+ return -1;
+ }
+ return 0;
+}
+int getifaddrs(struct ifaddrs** result) {
+ int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0) {
+ return -1;
+ }
+ netlinkrequest ifaddr_request;
+ memset(&ifaddr_request, 0, sizeof(ifaddr_request));
+ ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
+ ifaddr_request.header.nlmsg_type = RTM_GETADDR;
+ ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
+ ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0);
+ if (static_cast<size_t>(count) != ifaddr_request.header.nlmsg_len) {
+ close(fd);
+ return -1;
+ }
+ struct ifaddrs* start = NULL;
+ struct ifaddrs* current = NULL;
+ char buf[kMaxReadSize];
+ ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0);
+ while (amount_read > 0) {
+ nlmsghdr* header = reinterpret_cast<nlmsghdr*>(&buf[0]);
+ size_t header_size = static_cast<size_t>(amount_read);
+ for ( ; NLMSG_OK(header, header_size);
+ header = NLMSG_NEXT(header, header_size)) {
+ switch (header->nlmsg_type) {
+ case NLMSG_DONE:
+ // Success. Return.
+ *result = start;
+ close(fd);
+ return 0;
+ case NLMSG_ERROR:
+ close(fd);
+ freeifaddrs(start);
+ return -1;
+ case RTM_NEWADDR: {
+ ifaddrmsg* address_msg =
+ reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(header));
+ rtattr* rta = IFA_RTA(address_msg);
+ ssize_t payload_len = IFA_PAYLOAD(header);
+ while (RTA_OK(rta, payload_len)) {
+ if (rta->rta_type == IFA_ADDRESS) {
+ int family = address_msg->ifa_family;
+ if (family == AF_INET || family == AF_INET6) {
+ ifaddrs* newest = new ifaddrs;
+ memset(newest, 0, sizeof(ifaddrs));
+ if (current) {
+ current->ifa_next = newest;
+ } else {
+ start = newest;
+ }
+ if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta),
+ RTA_PAYLOAD(rta)) != 0) {
+ freeifaddrs(start);
+ *result = NULL;
+ return -1;
+ }
+ current = newest;
+ }
+ }
+ rta = RTA_NEXT(rta, payload_len);
+ }
+ break;
+ }
+ }
+ }
+ amount_read = recv(fd, &buf, kMaxReadSize, 0);
+ }
+ close(fd);
+ freeifaddrs(start);
+ return -1;
+}
+void freeifaddrs(struct ifaddrs* addrs) {
+ struct ifaddrs* last = NULL;
+ struct ifaddrs* cursor = addrs;
+ while (cursor) {
+ delete[] cursor->ifa_name;
+ delete cursor->ifa_addr;
+ delete cursor->ifa_netmask;
+ last = cursor;
+ cursor = cursor->ifa_next;
+ delete last;
+ }
+}
diff --git a/platform/android/ifaddrs_android.h b/platform/android/ifaddrs_android.h
new file mode 100644
index 0000000000..539fa40455
--- /dev/null
+++ b/platform/android/ifaddrs_android.h
@@ -0,0 +1,46 @@
+/*
+ * libjingle
+ * Copyright 2013, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TALK_BASE_IFADDRS_ANDROID_H_
+#define TALK_BASE_IFADDRS_ANDROID_H_
+#include <stdio.h>
+#include <sys/socket.h>
+// Implementation of getifaddrs for Android.
+// Fills out a list of ifaddr structs (see below) which contain information
+// about every network interface available on the host.
+// See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function).
+struct ifaddrs {
+ struct ifaddrs* ifa_next;
+ char* ifa_name;
+ unsigned int ifa_flags;
+ struct sockaddr* ifa_addr;
+ struct sockaddr* ifa_netmask;
+ // Real ifaddrs has broadcast, point to point and data members.
+ // We don't need them (yet?).
+};
+int getifaddrs(struct ifaddrs** result);
+void freeifaddrs(struct ifaddrs* addrs);
+#endif // TALK_BASE_IFADDRS_ANDROID_H_
diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java
index 35ecdc818e..9cadeb4231 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/com/android/godot/Godot.java
@@ -62,9 +62,13 @@ import android.widget.FrameLayout;
import com.android.godot.input.*;
import java.io.InputStream;
+import javax.microedition.khronos.opengles.GL10;
public class Godot extends Activity implements SensorEventListener
{
+
+ static final int MAX_SINGLETONS = 64;
+
static public class SingletonBase {
protected void registerClass(String p_name, String[] p_methods) {
@@ -104,8 +108,23 @@ public class Godot extends Activity implements SensorEventListener
}
+
+ Godot.singletons[Godot.singleton_count++]=this;
}
+ protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {
+
+
+ }
+
+ protected void onMainPause() {}
+ protected void onMainResume() {}
+ protected void onMainDestroy() {}
+
+ protected void onGLDrawFrame(GL10 gl) {}
+ protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
+ //protected void onGLSurfaceCreated(GL10 gl, EGLConfig config) {} // singletons won't be ready until first GodotLib.step()
+
public void registerMethods() {}
}
@@ -125,6 +144,7 @@ public class Godot extends Activity implements SensorEventListener
private Sensor mAccelerometer;
public FrameLayout layout;
+ public RelativeLayout adLayout;
static public GodotIO io;
@@ -133,6 +153,11 @@ public class Godot extends Activity implements SensorEventListener
//setTitle(title);
}
+
+ static SingletonBase singletons[] = new SingletonBase[MAX_SINGLETONS];
+ static int singleton_count=0;
+
+
public interface ResultCallback {
public void callback(int requestCode, int resultCode, Intent data);
};
@@ -147,6 +172,11 @@ public class Godot extends Activity implements SensorEventListener
result_callback.callback(requestCode, resultCode, data);
result_callback = null;
};
+
+ for(int i=0;i<singleton_count;i++) {
+
+ singletons[i].onMainActivityResult(requestCode,resultCode,data);
+ }
};
public void onVideoInit(boolean use_gl2) {
@@ -170,6 +200,12 @@ public class Godot extends Activity implements SensorEventListener
edittext.setView(mView);
io.setEdit(edittext);
+
+ // Ad layout
+ adLayout = new RelativeLayout(this);
+ adLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
+ layout.addView(adLayout);
+
}
private static Godot _self;
@@ -179,46 +215,46 @@ public class Godot extends Activity implements SensorEventListener
}
- private String[] getCommandLine() {
-
- InputStream is;
- try {
- is = getAssets().open("/_cl_");
- byte[] len = new byte[4];
- int r = is.read(len);
- if (r<4) {
- System.out.printf("**ERROR** Wrong cmdline length.\n");
- return new String[0];
- }
- int argc=((int)(len[3])<<24) | ((int)(len[2])<<16) | ((int)(len[1])<<8) | ((int)(len[0]));
- String[] cmdline = new String[argc];
- for(int i=0;i<argc;i++) {
- r = is.read(len);
- if (r<4) {
- System.out.printf("**ERROR** Wrong cmdline param lenght.\n");
- return new String[0];
- }
- int strlen=((int)(len[3])<<24) | ((int)(len[2])<<16) | ((int)(len[1])<<8) | ((int)(len[0]));
- if (strlen>65535) {
- System.out.printf("**ERROR** Wrong command len\n");
- return new String[0];
- }
- byte[] arg = new byte[strlen];
- r = is.read(arg);
- if (r!=strlen) {
- cmdline[i]=new String(arg,"UTF-8");
- }
-
- }
-
- return cmdline;
- } catch (Exception e) {
-
- return new String[0];
- }
-
-
- }
+ private String[] getCommandLine() {
+
+ InputStream is;
+ try {
+ is = getAssets().open("/_cl_");
+ byte[] len = new byte[4];
+ int r = is.read(len);
+ if (r<4) {
+ System.out.printf("**ERROR** Wrong cmdline length.\n");
+ return new String[0];
+ }
+ int argc=((int)(len[3])<<24) | ((int)(len[2])<<16) | ((int)(len[1])<<8) | ((int)(len[0]));
+ String[] cmdline = new String[argc];
+ for(int i=0;i<argc;i++) {
+ r = is.read(len);
+ if (r<4) {
+ System.out.printf("**ERROR** Wrong cmdline param lenght.\n");
+ return new String[0];
+ }
+ int strlen=((int)(len[3])<<24) | ((int)(len[2])<<16) | ((int)(len[1])<<8) | ((int)(len[0]));
+ if (strlen>65535) {
+ System.out.printf("**ERROR** Wrong command len\n");
+ return new String[0];
+ }
+ byte[] arg = new byte[strlen];
+ r = is.read(arg);
+ if (r!=strlen) {
+ cmdline[i]=new String(arg,"UTF-8");
+ }
+
+ }
+
+ return cmdline;
+ } catch (Exception e) {
+
+ return new String[0];
+ }
+
+
+ }
@Override protected void onCreate(Bundle icicle) {
@@ -255,6 +291,9 @@ public class Godot extends Activity implements SensorEventListener
@Override protected void onDestroy(){
if(mPaymentsManager != null ) mPaymentsManager.destroy();
+ for(int i=0;i<singleton_count;i++) {
+ singletons[i].onMainDestroy();
+ }
super.onDestroy();
}
@@ -264,6 +303,9 @@ public class Godot extends Activity implements SensorEventListener
mSensorManager.unregisterListener(this);
GodotLib.focusout();
+ for(int i=0;i<singleton_count;i++) {
+ singletons[i].onMainPause();
+ }
}
@Override protected void onResume() {
@@ -271,6 +313,12 @@ public class Godot extends Activity implements SensorEventListener
mView.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
GodotLib.focusin();
+
+ for(int i=0;i<singleton_count;i++) {
+
+ singletons[i].onMainResume();
+ }
+
}
@Override public void onSensorChanged(SensorEvent event) {
@@ -363,31 +411,31 @@ public class Godot extends Activity implements SensorEventListener
return true;
}
- @Override public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
- String s = event.getCharacters();
- if (s == null || s.length() == 0)
- return super.onKeyMultiple(inKeyCode, repeatCount, event);
-
- final char[] cc = s.toCharArray();
- int cnt = 0;
- for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0);
- if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
- final Activity me = this;
- queueEvent(new Runnable() {
- // This method will be called on the rendering thread:
- public void run() {
- for (int i = 0, n = cc.length; i < n; i++) {
- int keyCode;
- if ((keyCode = cc[i]) != 0) {
- // Simulate key down and up...
- GodotLib.key(0, keyCode, true);
- GodotLib.key(0, keyCode, false);
- }
- }
- }
- });
- return true;
- }
+ @Override public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
+ String s = event.getCharacters();
+ if (s == null || s.length() == 0)
+ return super.onKeyMultiple(inKeyCode, repeatCount, event);
+
+ final char[] cc = s.toCharArray();
+ int cnt = 0;
+ for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0);
+ if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
+ final Activity me = this;
+ queueEvent(new Runnable() {
+ // This method will be called on the rendering thread:
+ public void run() {
+ for (int i = 0, n = cc.length; i < n; i++) {
+ int keyCode;
+ if ((keyCode = cc[i]) != 0) {
+ // Simulate key down and up...
+ GodotLib.key(0, keyCode, true);
+ GodotLib.key(0, keyCode, false);
+ }
+ }
+ }
+ });
+ return true;
+ }
private void queueEvent(Runnable runnable) {
// TODO Auto-generated method stub
diff --git a/platform/android/java/src/com/android/godot/GodotPaymentV3.java b/platform/android/java/src/com/android/godot/GodotPaymentV3.java
index 23f5bf34d3..dba4a9a774 100644
--- a/platform/android/java/src/com/android/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/com/android/godot/GodotPaymentV3.java
@@ -1,7 +1,10 @@
package com.android.godot;
+import org.json.JSONObject;
+
import android.app.Activity;
+import android.util.Log;
public class GodotPaymentV3 extends Godot.SingletonBase {
@@ -13,14 +16,17 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
private String accessToken;
private String purchaseValidationUrlPrefix;
+
+ private String transactionId;
- public void purchase( String _sku) {
+ public void purchase( String _sku, String _transactionId) {
final String sku = _sku;
+ final String transactionId = _transactionId;
activity.getPaymentsManager().setBaseSingleton(this);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- activity.getPaymentsManager().requestPurchase(sku);
+ activity.getPaymentsManager().requestPurchase(sku, transactionId);
}
});
};
@@ -38,22 +44,31 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
public GodotPaymentV3(Activity p_activity) {
- registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix"});
+ registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature"});
activity=(Godot) p_activity;
}
+ private String signature;
+ public String getSignature(){
+ return this.signature;
+ }
+
- public void callbackSuccess(String ticket){
- GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket});
+ public void callbackSuccess(String ticket, String signature){
+ Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
+ Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
}
public void callbackFail(){
- GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
+// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
}
public void callbackCancel(){
- GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[]{});
+// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
}
public int getPurchaseCallbackId() {
@@ -84,4 +99,12 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
this.accessToken = accessToken;
}
+ public void setTransactionId(String transactionId){
+ this.transactionId = transactionId;
+ }
+
+ public String getTransactionId(){
+ return this.transactionId;
+ }
+
}
diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java
index 1993be8d2c..f02cc00c28 100644
--- a/platform/android/java/src/com/android/godot/GodotView.java
+++ b/platform/android/java/src/com/android/godot/GodotView.java
@@ -62,13 +62,14 @@ import javax.microedition.khronos.opengles.GL10;
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
public class GodotView extends GLSurfaceView {
- private static String TAG = "GodotView";
- private static final boolean DEBUG = false;
- private static Context ctx;
- private static GodotIO io;
- private static boolean firsttime=true;
- private static boolean use_gl2=false;
+ private static String TAG = "GodotView";
+ private static final boolean DEBUG = false;
+ private static Context ctx;
+
+ private static GodotIO io;
+ private static boolean firsttime=true;
+ private static boolean use_gl2=false;
private Godot activity;
@@ -113,37 +114,37 @@ public class GodotView extends GLSurfaceView {
return super.onKeyDown(keyCode, event);
}
- private void init(boolean translucent, int depth, int stencil) {
+ private void init(boolean translucent, int depth, int stencil) {
- this.setFocusableInTouchMode(true);
- /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
- * If we want a translucent one, we should change the surface's
- * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
- * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
- */
- if (translucent) {
- this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
- }
+ this.setFocusableInTouchMode(true);
+ /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
+ * If we want a translucent one, we should change the surface's
+ * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
+ * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
+ */
+ if (translucent) {
+ this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ }
- /* Setup the context factory for 2.0 rendering.
- * See ContextFactory class definition below
- */
- setEGLContextFactory(new ContextFactory());
-
- /* We need to choose an EGLConfig that matches the format of
- * our surface exactly. This is going to be done in our
- * custom config chooser. See ConfigChooser class definition
- * below.
- */
- setEGLConfigChooser( translucent ?
- new ConfigChooser(8, 8, 8, 8, depth, stencil) :
- new ConfigChooser(5, 6, 5, 0, depth, stencil) );
-
- /* Set the renderer responsible for frame rendering */
- setRenderer(new Renderer());
- }
+ /* Setup the context factory for 2.0 rendering.
+ * See ContextFactory class definition below
+ */
+ setEGLContextFactory(new ContextFactory());
+
+ /* We need to choose an EGLConfig that matches the format of
+ * our surface exactly. This is going to be done in our
+ * custom config chooser. See ConfigChooser class definition
+ * below.
+ */
+ setEGLConfigChooser( translucent ?
+ new ConfigChooser(8, 8, 8, 8, depth, stencil) :
+ new ConfigChooser(5, 6, 5, 0, depth, stencil) );
+
+ /* Set the renderer responsible for frame rendering */
+ setRenderer(new Renderer());
+ }
- private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
+ private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
if (use_gl2)
@@ -151,11 +152,11 @@ public class GodotView extends GLSurfaceView {
else
Log.w(TAG, "creating OpenGL ES 1.1 context :");
- checkEglError("Before eglCreateContext", egl);
- int[] attrib_list2 = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
- EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl2?attrib_list2:null);
- checkEglError("After eglCreateContext", egl);
- return context;
+ checkEglError("Before eglCreateContext", egl);
+ int[] attrib_list2 = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+ EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl2?attrib_list2:null);
+ checkEglError("After eglCreateContext", egl);
+ return context;
}
public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
@@ -170,225 +171,231 @@ public class GodotView extends GLSurfaceView {
}
}
- private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
-
- public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
- mRedSize = r;
- mGreenSize = g;
- mBlueSize = b;
- mAlphaSize = a;
- mDepthSize = depth;
- mStencilSize = stencil;
- }
+ private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
- /* This EGL config specification is used to specify 2.0 rendering.
- * We use a minimum size of 4 bits for red/green/blue, but will
- * perform actual matching in chooseConfig() below.
- */
- private static int EGL_OPENGL_ES2_BIT = 4;
- private static int[] s_configAttribs2 =
- {
- EGL10.EGL_RED_SIZE, 4,
- EGL10.EGL_GREEN_SIZE, 4,
- EGL10.EGL_BLUE_SIZE, 4,
- // EGL10.EGL_DEPTH_SIZE, 16,
- // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL10.EGL_NONE
- };
- private static int[] s_configAttribs =
- {
- EGL10.EGL_RED_SIZE, 4,
- EGL10.EGL_GREEN_SIZE, 4,
- EGL10.EGL_BLUE_SIZE, 4,
- // EGL10.EGL_DEPTH_SIZE, 16,
- // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
- EGL10.EGL_NONE
- };
+ public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
+ mRedSize = r;
+ mGreenSize = g;
+ mBlueSize = b;
+ mAlphaSize = a;
+ mDepthSize = depth;
+ mStencilSize = stencil;
+ }
- public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+ /* This EGL config specification is used to specify 2.0 rendering.
+ * We use a minimum size of 4 bits for red/green/blue, but will
+ * perform actual matching in chooseConfig() below.
+ */
+ private static int EGL_OPENGL_ES2_BIT = 4;
+ private static int[] s_configAttribs2 =
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ // EGL10.EGL_DEPTH_SIZE, 16,
+ // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_NONE
+ };
+ private static int[] s_configAttribs =
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ // EGL10.EGL_DEPTH_SIZE, 16,
+ // EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
+ EGL10.EGL_NONE
+ };
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+
+ /* Get the number of minimally matching EGL configurations
+ */
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, null, 0, num_config);
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ throw new IllegalArgumentException("No configs match configSpec");
+ }
+
+ /* Allocate then read the array of minimally matching EGL configs
+ */
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, configs, numConfigs, num_config);
+
+ if (DEBUG) {
+ printConfigs(egl, display, configs);
+ }
+ /* Now return the "best" one
+ */
+ return chooseConfig(egl, display, configs);
+ }
- /* Get the number of minimally matching EGL configurations
- */
- int[] num_config = new int[1];
- egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, null, 0, num_config);
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ for(EGLConfig config : configs) {
+ int d = findConfigAttrib(egl, display, config,
+ EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config,
+ EGL10.EGL_STENCIL_SIZE, 0);
+
+ // We need at least mDepthSize and mStencilSize bits
+ if (d < mDepthSize || s < mStencilSize)
+ continue;
+
+ // We want an *exact* match for red/green/blue/alpha
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
+ return config;
+ }
+ return null;
+ }
- int numConfigs = num_config[0];
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display,
+ EGLConfig config, int attribute, int defaultValue) {
- if (numConfigs <= 0) {
- throw new IllegalArgumentException("No configs match configSpec");
- }
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+ return mValue[0];
+ }
+ return defaultValue;
+ }
- /* Allocate then read the array of minimally matching EGL configs
- */
- EGLConfig[] configs = new EGLConfig[numConfigs];
- egl.eglChooseConfig(display, use_gl2?s_configAttribs2:s_configAttribs, configs, numConfigs, num_config);
+ private void printConfigs(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ int numConfigs = configs.length;
+ Log.w(TAG, String.format("%d configurations", numConfigs));
+ for (int i = 0; i < numConfigs; i++) {
+ Log.w(TAG, String.format("Configuration %d:\n", i));
+ printConfig(egl, display, configs[i]);
+ }
+ }
- if (DEBUG) {
- printConfigs(egl, display, configs);
- }
- /* Now return the "best" one
- */
- return chooseConfig(egl, display, configs);
- }
+ private void printConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig config) {
+ int[] attributes = {
+ EGL10.EGL_BUFFER_SIZE,
+ EGL10.EGL_ALPHA_SIZE,
+ EGL10.EGL_BLUE_SIZE,
+ EGL10.EGL_GREEN_SIZE,
+ EGL10.EGL_RED_SIZE,
+ EGL10.EGL_DEPTH_SIZE,
+ EGL10.EGL_STENCIL_SIZE,
+ EGL10.EGL_CONFIG_CAVEAT,
+ EGL10.EGL_CONFIG_ID,
+ EGL10.EGL_LEVEL,
+ EGL10.EGL_MAX_PBUFFER_HEIGHT,
+ EGL10.EGL_MAX_PBUFFER_PIXELS,
+ EGL10.EGL_MAX_PBUFFER_WIDTH,
+ EGL10.EGL_NATIVE_RENDERABLE,
+ EGL10.EGL_NATIVE_VISUAL_ID,
+ EGL10.EGL_NATIVE_VISUAL_TYPE,
+ 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+ EGL10.EGL_SAMPLES,
+ EGL10.EGL_SAMPLE_BUFFERS,
+ EGL10.EGL_SURFACE_TYPE,
+ EGL10.EGL_TRANSPARENT_TYPE,
+ EGL10.EGL_TRANSPARENT_RED_VALUE,
+ EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+ EGL10.EGL_TRANSPARENT_BLUE_VALUE,
+ 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
+ 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+ 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
+ 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
+ EGL10.EGL_LUMINANCE_SIZE,
+ EGL10.EGL_ALPHA_MASK_SIZE,
+ EGL10.EGL_COLOR_BUFFER_TYPE,
+ EGL10.EGL_RENDERABLE_TYPE,
+ 0x3042 // EGL10.EGL_CONFORMANT
+ };
+ String[] names = {
+ "EGL_BUFFER_SIZE",
+ "EGL_ALPHA_SIZE",
+ "EGL_BLUE_SIZE",
+ "EGL_GREEN_SIZE",
+ "EGL_RED_SIZE",
+ "EGL_DEPTH_SIZE",
+ "EGL_STENCIL_SIZE",
+ "EGL_CONFIG_CAVEAT",
+ "EGL_CONFIG_ID",
+ "EGL_LEVEL",
+ "EGL_MAX_PBUFFER_HEIGHT",
+ "EGL_MAX_PBUFFER_PIXELS",
+ "EGL_MAX_PBUFFER_WIDTH",
+ "EGL_NATIVE_RENDERABLE",
+ "EGL_NATIVE_VISUAL_ID",
+ "EGL_NATIVE_VISUAL_TYPE",
+ "EGL_PRESERVED_RESOURCES",
+ "EGL_SAMPLES",
+ "EGL_SAMPLE_BUFFERS",
+ "EGL_SURFACE_TYPE",
+ "EGL_TRANSPARENT_TYPE",
+ "EGL_TRANSPARENT_RED_VALUE",
+ "EGL_TRANSPARENT_GREEN_VALUE",
+ "EGL_TRANSPARENT_BLUE_VALUE",
+ "EGL_BIND_TO_TEXTURE_RGB",
+ "EGL_BIND_TO_TEXTURE_RGBA",
+ "EGL_MIN_SWAP_INTERVAL",
+ "EGL_MAX_SWAP_INTERVAL",
+ "EGL_LUMINANCE_SIZE",
+ "EGL_ALPHA_MASK_SIZE",
+ "EGL_COLOR_BUFFER_TYPE",
+ "EGL_RENDERABLE_TYPE",
+ "EGL_CONFORMANT"
+ };
+ int[] value = new int[1];
+ for (int i = 0; i < attributes.length; i++) {
+ int attribute = attributes[i];
+ String name = names[i];
+ if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
+ Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
+ } else {
+ // Log.w(TAG, String.format(" %s: failed\n", name));
+ while (egl.eglGetError() != EGL10.EGL_SUCCESS);
+ }
+ }
+ }
- public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
- EGLConfig[] configs) {
- for(EGLConfig config : configs) {
- int d = findConfigAttrib(egl, display, config,
- EGL10.EGL_DEPTH_SIZE, 0);
- int s = findConfigAttrib(egl, display, config,
- EGL10.EGL_STENCIL_SIZE, 0);
-
- // We need at least mDepthSize and mStencilSize bits
- if (d < mDepthSize || s < mStencilSize)
- continue;
-
- // We want an *exact* match for red/green/blue/alpha
- int r = findConfigAttrib(egl, display, config,
- EGL10.EGL_RED_SIZE, 0);
- int g = findConfigAttrib(egl, display, config,
- EGL10.EGL_GREEN_SIZE, 0);
- int b = findConfigAttrib(egl, display, config,
- EGL10.EGL_BLUE_SIZE, 0);
- int a = findConfigAttrib(egl, display, config,
- EGL10.EGL_ALPHA_SIZE, 0);
-
- if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
- return config;
- }
- return null;
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+ private int[] mValue = new int[1];
}
- private int findConfigAttrib(EGL10 egl, EGLDisplay display,
- EGLConfig config, int attribute, int defaultValue) {
-
- if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
- return mValue[0];
- }
- return defaultValue;
- }
+ private static class Renderer implements GLSurfaceView.Renderer {
- private void printConfigs(EGL10 egl, EGLDisplay display,
- EGLConfig[] configs) {
- int numConfigs = configs.length;
- Log.w(TAG, String.format("%d configurations", numConfigs));
- for (int i = 0; i < numConfigs; i++) {
- Log.w(TAG, String.format("Configuration %d:\n", i));
- printConfig(egl, display, configs[i]);
- }
- }
- private void printConfig(EGL10 egl, EGLDisplay display,
- EGLConfig config) {
- int[] attributes = {
- EGL10.EGL_BUFFER_SIZE,
- EGL10.EGL_ALPHA_SIZE,
- EGL10.EGL_BLUE_SIZE,
- EGL10.EGL_GREEN_SIZE,
- EGL10.EGL_RED_SIZE,
- EGL10.EGL_DEPTH_SIZE,
- EGL10.EGL_STENCIL_SIZE,
- EGL10.EGL_CONFIG_CAVEAT,
- EGL10.EGL_CONFIG_ID,
- EGL10.EGL_LEVEL,
- EGL10.EGL_MAX_PBUFFER_HEIGHT,
- EGL10.EGL_MAX_PBUFFER_PIXELS,
- EGL10.EGL_MAX_PBUFFER_WIDTH,
- EGL10.EGL_NATIVE_RENDERABLE,
- EGL10.EGL_NATIVE_VISUAL_ID,
- EGL10.EGL_NATIVE_VISUAL_TYPE,
- 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
- EGL10.EGL_SAMPLES,
- EGL10.EGL_SAMPLE_BUFFERS,
- EGL10.EGL_SURFACE_TYPE,
- EGL10.EGL_TRANSPARENT_TYPE,
- EGL10.EGL_TRANSPARENT_RED_VALUE,
- EGL10.EGL_TRANSPARENT_GREEN_VALUE,
- EGL10.EGL_TRANSPARENT_BLUE_VALUE,
- 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
- 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
- 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
- 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
- EGL10.EGL_LUMINANCE_SIZE,
- EGL10.EGL_ALPHA_MASK_SIZE,
- EGL10.EGL_COLOR_BUFFER_TYPE,
- EGL10.EGL_RENDERABLE_TYPE,
- 0x3042 // EGL10.EGL_CONFORMANT
- };
- String[] names = {
- "EGL_BUFFER_SIZE",
- "EGL_ALPHA_SIZE",
- "EGL_BLUE_SIZE",
- "EGL_GREEN_SIZE",
- "EGL_RED_SIZE",
- "EGL_DEPTH_SIZE",
- "EGL_STENCIL_SIZE",
- "EGL_CONFIG_CAVEAT",
- "EGL_CONFIG_ID",
- "EGL_LEVEL",
- "EGL_MAX_PBUFFER_HEIGHT",
- "EGL_MAX_PBUFFER_PIXELS",
- "EGL_MAX_PBUFFER_WIDTH",
- "EGL_NATIVE_RENDERABLE",
- "EGL_NATIVE_VISUAL_ID",
- "EGL_NATIVE_VISUAL_TYPE",
- "EGL_PRESERVED_RESOURCES",
- "EGL_SAMPLES",
- "EGL_SAMPLE_BUFFERS",
- "EGL_SURFACE_TYPE",
- "EGL_TRANSPARENT_TYPE",
- "EGL_TRANSPARENT_RED_VALUE",
- "EGL_TRANSPARENT_GREEN_VALUE",
- "EGL_TRANSPARENT_BLUE_VALUE",
- "EGL_BIND_TO_TEXTURE_RGB",
- "EGL_BIND_TO_TEXTURE_RGBA",
- "EGL_MIN_SWAP_INTERVAL",
- "EGL_MAX_SWAP_INTERVAL",
- "EGL_LUMINANCE_SIZE",
- "EGL_ALPHA_MASK_SIZE",
- "EGL_COLOR_BUFFER_TYPE",
- "EGL_RENDERABLE_TYPE",
- "EGL_CONFORMANT"
- };
- int[] value = new int[1];
- for (int i = 0; i < attributes.length; i++) {
- int attribute = attributes[i];
- String name = names[i];
- if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
- Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
- } else {
- // Log.w(TAG, String.format(" %s: failed\n", name));
- while (egl.eglGetError() != EGL10.EGL_SUCCESS);
+ public void onDrawFrame(GL10 gl) {
+ GodotLib.step();
+ for(int i=0;i<Godot.singleton_count;i++) {
+ Godot.singletons[i].onGLDrawFrame(gl);
+ }
}
- }
- }
-
- // Subclasses can adjust these values:
- protected int mRedSize;
- protected int mGreenSize;
- protected int mBlueSize;
- protected int mAlphaSize;
- protected int mDepthSize;
- protected int mStencilSize;
- private int[] mValue = new int[1];
- }
-
- private static class Renderer implements GLSurfaceView.Renderer {
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
- public void onDrawFrame(GL10 gl) {
- GodotLib.step();
- }
-
- public void onSurfaceChanged(GL10 gl, int width, int height) {
-
- GodotLib.resize(width, height,!firsttime);
- firsttime=false;
- }
+ GodotLib.resize(width, height,!firsttime);
+ firsttime=false;
+ for(int i=0;i<Godot.singleton_count;i++) {
+ Godot.singletons[i].onGLSurfaceChanged(gl, width, height);
+ }
+ }
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- GodotLib.newcontext();
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ GodotLib.newcontext();
+ }
}
- }
}
diff --git a/platform/android/java/src/com/android/godot/payments/ConsumeTask.java b/platform/android/java/src/com/android/godot/payments/ConsumeTask.java
index 855bc0578d..c983960770 100644
--- a/platform/android/java/src/com/android/godot/payments/ConsumeTask.java
+++ b/platform/android/java/src/com/android/godot/payments/ConsumeTask.java
@@ -56,8 +56,7 @@ abstract public class ConsumeTask {
protected void onPostExecute(String param){
if(param == null){
-
- success(new PaymentsCache(context).getConsumableValue("ticket", sku));
+ success( new PaymentsCache(context).getConsumableValue("ticket", sku) );
}else{
error(param);
}
diff --git a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
index a32ecf2895..a810ac40ae 100644
--- a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
+++ b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
@@ -34,7 +34,8 @@ abstract public class HandlePurchaseTask {
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
Log.d("XXX", "Purchase data:" + purchaseData);
-// String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
+ String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
+ Log.d("XXX", "Purchase signature:" + dataSignature);
if (resultCode == Activity.RESULT_OK) {
@@ -57,12 +58,13 @@ abstract public class HandlePurchaseTask {
error("Untrusted callback");
return;
}
-
+ Log.d("XXX", "Este es el product ID:" + productId);
+ pc.setConsumableValue("ticket_signautre", productId, dataSignature);
pc.setConsumableValue("ticket", productId, purchaseData);
pc.setConsumableFlag("block", productId, true);
pc.setConsumableValue("token", productId, purchaseToken);
- success(productId);
+ success(productId, dataSignature);
return;
} catch (JSONException e) {
error(e.getMessage());
@@ -72,7 +74,7 @@ abstract public class HandlePurchaseTask {
}
}
- abstract protected void success(String ticket);
+ abstract protected void success(String ticket, String signature);
abstract protected void error(String message);
abstract protected void canceled();
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java b/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
index ba84097732..7337acc0b8 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
+++ b/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
@@ -2,6 +2,7 @@ package com.android.godot.payments;
import android.content.Context;
import android.content.SharedPreferences;
+import android.util.Log;
public class PaymentsCache {
@@ -30,12 +31,14 @@ public class PaymentsCache {
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(sku, value);
+ Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
editor.commit();
}
public String getConsumableValue(String set, String sku){
SharedPreferences sharedPref = context.getSharedPreferences(
"consumables_" + set, Context.MODE_PRIVATE);
+ Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
return sharedPref.getString(sku, null);
}
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
index e8c487dbd8..d85a8ea8ea 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
@@ -6,6 +6,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.util.Log;
import com.android.godot.Godot;
import com.android.godot.GodotPaymentV3;
@@ -63,7 +64,7 @@ public class PaymentsManager {
}
};
- public void requestPurchase(String sku){
+ public void requestPurchase(String sku, String transactionId){
new PurchaseTask(mService, Godot.getInstance()) {
@Override
@@ -76,7 +77,7 @@ public class PaymentsManager {
protected void canceled() {
godotPaymentV3.callbackCancel();
}
- }.purchase(sku);
+ }.purchase(sku, transactionId);
}
@@ -84,13 +85,14 @@ public class PaymentsManager {
new HandlePurchaseTask(activity){
@Override
- protected void success(final String sku) {
+ protected void success(final String sku, final String signature) {
new ConsumeTask(mService, activity) {
@Override
protected void success(String ticket) {
// godotPaymentV3.callbackSuccess("");
- godotPaymentV3.callbackSuccess(ticket);
+ Log.d("XXX", "calling success:" + signature);
+ godotPaymentV3.callbackSuccess(ticket, signature);
}
@Override
@@ -131,7 +133,7 @@ public class PaymentsManager {
@Override
protected void success(String ticket) {
- godotPaymentV3.callbackSuccess(ticket);
+ godotPaymentV3.callbackSuccess(ticket, null);
}
diff --git a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
index f5d8a0298a..0856b4e900 100644
--- a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
+++ b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
@@ -31,7 +31,7 @@ abstract public class PurchaseTask {
private boolean isLooping = false;
- public void purchase(final String sku){
+ public void purchase(final String sku, final String transactionId){
Log.d("XXX", "Starting purchase for: " + sku);
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
@@ -40,7 +40,7 @@ abstract public class PurchaseTask {
// error("Awaiting payment confirmation");
// return;
// }
- final String hash = Crypt.createRandomHash() + Crypt.createRandomHash();
+ final String hash = transactionId;
Bundle buyIntentBundle;
try {
@@ -76,7 +76,7 @@ abstract public class PurchaseTask {
return;
}
isLooping=true;
- PurchaseTask.this.purchase(sku);
+ PurchaseTask.this.purchase(sku, transactionId);
}
diff --git a/platform/android/java_bind.cpp b/platform/android/java_bind.cpp
new file mode 100644
index 0000000000..33ecfcffb6
--- /dev/null
+++ b/platform/android/java_bind.cpp
@@ -0,0 +1,5 @@
+#include "java_bind.h"
+
+JavaBind::JavaBind()
+{
+}
diff --git a/platform/android/java_bind.h b/platform/android/java_bind.h
new file mode 100644
index 0000000000..ca6b4650d3
--- /dev/null
+++ b/platform/android/java_bind.h
@@ -0,0 +1,10 @@
+#ifndef JAVA_BIND_H
+#define JAVA_BIND_H
+
+class JavaBind
+{
+public:
+ JavaBind();
+};
+
+#endif // JAVA_BIND_H
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 5bf2fc5a73..b11994eef0 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -153,6 +153,14 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
v.l=arr;
} break;
+ case Variant::RAW_ARRAY: {
+ DVector<uint8_t> array = *p_arg;
+ jbyteArray arr = env->NewByteArray(array.size());
+ DVector<uint8_t>::Read r = array.read();
+ env->SetByteArrayRegion(arr,0,array.size(),reinterpret_cast<const signed char*>(r.ptr()));
+ v.l=arr;
+
+ } break;
case Variant::REAL_ARRAY: {
DVector<float> array = *p_arg;
@@ -244,6 +252,19 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
return sarr;
};
+ if (name == "[B") {
+
+ jbyteArray arr = (jbyteArray)obj;
+ int fCount = env->GetArrayLength(arr);
+ DVector<uint8_t> sarr;
+ sarr.resize(fCount);
+
+ DVector<uint8_t>::Write w = sarr.write();
+ env->GetByteArrayRegion(arr,0,fCount,reinterpret_cast<signed char*>(w.ptr()));
+ w = DVector<uint8_t>::Write();
+ return sarr;
+ };
+
if (name == "java.lang.Float" || name == "java.lang.Double") {
jclass nclass = env->FindClass("java/lang/Number");
@@ -354,6 +375,7 @@ public:
virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
//print_line("attempt to call "+String(p_method));
+ ERR_FAIL_COND_V(!instance,Variant());
r_error.error=Variant::CallError::CALL_OK;
@@ -519,7 +541,10 @@ public:
}
- JNISingleton() {}
+ JNISingleton() {
+ instance=NULL;
+
+ }
};
@@ -1342,6 +1367,7 @@ static Variant::Type get_jni_type(const String& p_type) {
{"double", Variant::REAL},
{"java.lang.String",Variant::STRING},
{"[I",Variant::INT_ARRAY},
+ {"[B",Variant::RAW_ARRAY},
{"[F",Variant::REAL_ARRAY},
{"[java.lang.String",Variant::STRING_ARRAY},
{"com.android.godot.Dictionary", Variant::DICTIONARY},
@@ -1377,6 +1403,7 @@ static const char* get_jni_sig(const String& p_type) {
{"java.lang.String","Ljava/lang/String;"},
{"com.android.godot.Dictionary", "Lcom/android/godot/Dictionary;"},
{"[I","[I"},
+ {"[B","[B"},
{"[F","[F"},
{"[java.lang.String","[Ljava/lang/String;"},
{NULL,"V"}
diff --git a/platform/android/sign.sh b/platform/android/sign.sh
index 8f760e6312..830da05a37 100755
--- a/platform/android/sign.sh
+++ b/platform/android/sign.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore /home/luis/Downloads/carnavalguachin.keystore -storepass 12345678 "$1" momoselacome
+jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore my-release-key.keystore "$1" reduz
echo ""
echo ""
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
index 0a19e71f08..5edcf39396 100644
--- a/platform/bb10/export/export.cpp
+++ b/platform/bb10/export/export.cpp
@@ -67,11 +67,11 @@ public:
virtual int get_device_count() const;
virtual String get_device_name(int p_device) const;
virtual String get_device_info(int p_device) const;
- virtual Error run(int p_device);
+ virtual Error run(int p_device,bool p_dumb=false);
virtual bool requieres_password(bool p_debug) const { return !p_debug; }
virtual String get_binary_extension() const { return "bar"; }
- virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+ virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual bool can_export(String *r_error=NULL) const;
@@ -270,7 +270,7 @@ void EditorExportPlatformBB10::_fix_descriptor(Vector<uint8_t>& p_descriptor) {
-Error EditorExportPlatformBB10::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debug, bool p_dumb) {
EditorProgress ep("export","Exporting for BlackBerry 10",104);
@@ -632,7 +632,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
}
-Error EditorExportPlatformBB10::run(int p_device) {
+Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) {
ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
diff --git a/platform/flash/dir_access_flash.cpp b/platform/flash/dir_access_flash.cpp
index a0f1679243..4b8992f9d6 100644
--- a/platform/flash/dir_access_flash.cpp
+++ b/platform/flash/dir_access_flash.cpp
@@ -156,6 +156,26 @@ bool DirAccessFlash::file_exists(String p_file) {
return success;
};
+bool DirAccessFlash::dir_exists(String p_dir) {
+
+ GLOBAL_LOCK_FUNCTION
+
+
+ if (p_dir.is_rel_path())
+ p_dir=current_dir+"/"+p_dir;
+ else
+ p_dir=fix_path(p_dir);
+
+ struct stat flags;
+ bool success = (stat(p_dir.utf8().get_data(),&flags)==0);
+
+ if (success && S_ISDIR(flags.st_mode)) {
+ return true;
+ }
+
+ return false;
+};
+
size_t DirAccessFlash::get_space_left() {
return 0;
diff --git a/platform/flash/dir_access_flash.h b/platform/flash/dir_access_flash.h
index 09e0b844ce..1378a6e56f 100644
--- a/platform/flash/dir_access_flash.h
+++ b/platform/flash/dir_access_flash.h
@@ -45,6 +45,7 @@ public:
Error make_dir(String p_dir);
bool file_exists(String p_file);
+ bool dir_exists(String p_dir);
size_t get_space_left();
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index a02891e817..ec6e4c98f1 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -21,7 +21,8 @@ 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/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/'),
+ ('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS7.0'),
+ ('IPHONESDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/${IOS_SDK_VERSION}.sdk/'),
('game_center', 'Support for game center', 'yes'),
('store_kit', 'Support for in-app store', 'yes'),
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
@@ -37,6 +38,7 @@ def get_flags():
('tools', 'yes'),
('nedmalloc', 'no'),
('webp', 'yes'),
+ ('openssl','builtin'), #use builtin openssl
]
@@ -81,7 +83,7 @@ def configure(env):
'-framework', 'AudioToolbox',
'-framework', 'SystemConfiguration',
'-framework', 'Security',
- '-framework', 'AdSupport',
+ #'-framework', 'AdSupport',
'-framework', 'MediaPlayer',
])
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index c482c36a30..500c7c7174 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -50,6 +50,7 @@ static String keyboard_text;
static GLView* _instance = NULL;
static bool video_found_error = false;
+static bool video_playing = false;
static float video_previous_volume = 0.0f;
void _show_keyboard(String p_existing) {
@@ -91,24 +92,29 @@ bool _play_video(String p_path, float p_volume) {
[_instance addSubview:_instance.moviePlayerController.view];
[_instance.moviePlayerController play];
+ video_playing = true;
+
return true;
}
bool _is_video_playing() {
//NSInteger playback_state = _instance.moviePlayerController.playbackState;
- if (video_found_error)
- return false;
- return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying);
+ return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying;
+ //if (video_found_error)
+ // return false;
+ //return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying);
}
void _pause_video() {
[_instance.moviePlayerController pause];
+ video_playing = false;
}
void _stop_video() {
[_instance.moviePlayerController stop];
[_instance.moviePlayerController.view removeFromSuperview];
[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
+ video_playing = false;
}
@implementation GLView
@@ -549,6 +555,7 @@ static void clear_touches() {
[_instance.moviePlayerController.view removeFromSuperview];
[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
+ video_playing = false;
}
@end
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index cd2e24216a..928d128799 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -77,11 +77,11 @@ public:
virtual int get_device_count() const { return show_run?1:0; };
virtual String get_device_name(int p_device) const { return "Run in Browser"; }
virtual String get_device_info(int p_device) const { return "Run exported HTML in the system's default browser."; }
- virtual Error run(int p_device);
+ virtual Error run(int p_device,bool p_dumb=false);
virtual bool requieres_password(bool p_debug) const { return false; }
virtual String get_binary_extension() const { return "html"; }
- virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+ virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual bool can_export(String *r_error=NULL) const;
@@ -194,7 +194,7 @@ struct JSExportData {
-Error EditorExportPlatformJavaScript::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool p_debug, bool p_dumb) {
String src_template;
@@ -299,7 +299,7 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path,bool p
}
-Error EditorExportPlatformJavaScript::run(int p_device) {
+Error EditorExportPlatformJavaScript::run(int p_device, bool p_dumb) {
String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp_export.html";
Error err = export_project(path,true,"");
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index f55e901794..087a648700 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -57,11 +57,11 @@ public:
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);
+ virtual Error run(int p_device,bool p_dumb=false);
virtual bool requieres_password(bool p_debug) const { return false; }
virtual String get_binary_extension() const { return "zip"; }
- virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+ virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual bool can_export(String *r_error=NULL) const;
@@ -245,7 +245,7 @@ void EditorExportPlatformOSX::_fix_plist(Vector<uint8_t>& plist,const String& p_
}
}
-Error EditorExportPlatformOSX::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, bool p_dumb) {
String src_pkg;
@@ -437,7 +437,7 @@ Error EditorExportPlatformOSX::export_project(const String& p_path,bool p_debug,
}
-Error EditorExportPlatformOSX::run(int p_device) {
+Error EditorExportPlatformOSX::run(int p_device, bool p_dumb) {
return OK;
}
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index d1c5e96d32..0e21540e13 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -117,7 +117,7 @@ def configure(env):
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
env.Append(CCFLAGS=['/DGLES1_ENABLED'])
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32','wsock32', 'shell32','advapi32'])
+ env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32'])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
if (os.getenv("DXSDK_DIR")):
@@ -143,10 +143,12 @@ def configure(env):
mingw_prefix=""
if (env["force_32_bits"]!="no"):
- env['OBJSUFFIX'] = ".32"+env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".32"+env['LIBSUFFIX']
- env.Append(CCFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-m32'])
+ env['OBJSUFFIX'] = ".32"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = ".32"+env['LIBSUFFIX']
+ env.Append(CCFLAGS=['-m32'])
+ env.Append(LINKFLAGS=['-m32'])
+ env.Append(LINKFLAGS=['-static-libgcc'])
+ env.Append(LINKFLAGS=['-static-libstdc++'])
@@ -196,7 +198,7 @@ def configure(env):
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLEW_ENABLED'])
- env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','wsock32','kernel32'])
+ env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
#'d3dx9d'
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
env.Append(LINKFLAGS=['-g'])
diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp
index 7b35bcc7ad..e77ca6feaa 100644
--- a/platform/windows/tcp_server_winsock.cpp
+++ b/platform/windows/tcp_server_winsock.cpp
@@ -86,6 +86,9 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_ho
closesocket(sockfd);
ERR_FAIL_V(FAILED);
};
+ }
+ else {
+ return ERR_ALREADY_IN_USE;
};
if (listen_sockfd != INVALID_SOCKET) {
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 6470f09850..e7d9a4d691 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -494,7 +494,7 @@ unsigned int OS_X11::get_mouse_button_state(unsigned int p_x11_state) {
return state;
}
-void OS_X11::handle_key_event(XKeyEvent *p_event) {
+void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
// X11 functions don't know what const is
@@ -605,17 +605,9 @@ void OS_X11::handle_key_event(XKeyEvent *p_event) {
// To detect them, i use XPeekEvent and check that their
// difference in time is below a treshold.
- bool echo=false;
-
- if (xkeyevent->type == KeyPress) {
-
- // saved the time of the last keyrelease to see
- // if it's the same as this keypress.
- if (xkeyevent->time==last_keyrelease_time)
- echo=true;
- } else {
-
+ if (xkeyevent->type != KeyPress) {
+
// make sure there are events pending,
// so this call won't block.
if (XPending(x11_display)>0) {
@@ -629,17 +621,21 @@ void OS_X11::handle_key_event(XKeyEvent *p_event) {
// not very helpful today.
::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time);
- if (peek_event.type == KeyPress && tresh<5 )
- echo=true;
+ if (peek_event.type == KeyPress && tresh<5 ) {
+ KeySym rk;
+ nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL);
+ if (rk==keysym_keycode) {
+ XEvent event;
+ XNextEvent(x11_display, &event); //erase next event
+ handle_key_event( (XKeyEvent*)&event,true );
+ return; //ignore current, echo next
+ }
+ }
// use the time from peek_event so it always works
- last_keyrelease_time=peek_event.xkey.time;
- } else {
- last_keyrelease_time=xkeyevent->time;
}
- // save the time to check for echo when keypress happens
-
+ // save the time to check for echo when keypress happens
}
@@ -657,7 +653,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event) {
event.key.scancode=keycode;
event.key.unicode=unicode;
- event.key.echo=echo;
+ event.key.echo=p_echo;
if (event.key.scancode==KEY_BACKTAB) {
//make it consistent accross platforms.
@@ -1031,7 +1027,7 @@ String OS_X11::get_name() {
Error OS_X11::shell_open(String p_uri) {
-
+ return ERR_UNAVAILABLE;
}
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 491b8fa00d..77ef37f6f4 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -90,7 +90,7 @@ class OS_X11 : public OS_Unix {
MouseMode mouse_mode;
Point2i center;
- void handle_key_event(XKeyEvent *p_event);
+ void handle_key_event(XKeyEvent *p_event,bool p_echo=false);
void process_xevents();
virtual void delete_main_loop();
IP_Unix *ip_unix;
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index a94b2347fc..d66f100b3f 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -447,7 +447,7 @@ float CanvasItem::get_self_opacity() const {
void CanvasItem::set_blend_mode(BlendMode p_blend_mode) {
- ERR_FAIL_INDEX(p_blend_mode,4);
+ ERR_FAIL_INDEX(p_blend_mode,5);
blend_mode=p_blend_mode;
VisualServer::get_singleton()->canvas_item_set_blend_mode(canvas_item,VS::MaterialBlendMode(blend_mode));
@@ -772,7 +772,7 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw_texture_rect_region","texture:Texture","rect","src_rect","modulate"),&CanvasItem::draw_texture_rect_region,DEFVAL(Color(1,1,1)));
ObjectTypeDB::bind_method(_MD("draw_style_box","style_box:StyleBox","rect"),&CanvasItem::draw_style_box);
ObjectTypeDB::bind_method(_MD("draw_primitive","points","colors","uvs","texture:Texture","width"),&CanvasItem::draw_primitive,DEFVAL(Array()),DEFVAL(Ref<Texture>()),DEFVAL(1.0));
- ObjectTypeDB::bind_method(_MD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_primitive,DEFVAL(Array()),DEFVAL(Ref<Texture>()));
+ ObjectTypeDB::bind_method(_MD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_polygon,DEFVAL(Array()),DEFVAL(Ref<Texture>()));
ObjectTypeDB::bind_method(_MD("draw_colored_polygon","points","color","uvs","texture:Texture"),&CanvasItem::draw_colored_polygon,DEFVAL(Array()),DEFVAL(Ref<Texture>()));
ObjectTypeDB::bind_method(_MD("draw_string","font:Font","pos","text","modulate","clip_w"),&CanvasItem::draw_string,DEFVAL(Color(1,1,1)),DEFVAL(-1));
ObjectTypeDB::bind_method(_MD("draw_char","font:Font","pos","char","next","modulate"),&CanvasItem::draw_char,DEFVAL(Color(1,1,1)));
@@ -794,7 +794,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
- ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
//exporting these two things doesn't really make much sense i think
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
@@ -810,6 +810,7 @@ void CanvasItem::_bind_methods() {
BIND_CONSTANT( BLEND_MODE_ADD );
BIND_CONSTANT( BLEND_MODE_SUB );
BIND_CONSTANT( BLEND_MODE_MUL );
+ BIND_CONSTANT( BLEND_MODE_PREMULT_ALPHA );
BIND_CONSTANT( NOTIFICATION_DRAW);
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 1c104c5fc2..604eef0527 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -49,7 +49,8 @@ public:
BLEND_MODE_MIX, //default
BLEND_MODE_ADD,
BLEND_MODE_SUB,
- BLEND_MODE_MUL
+ BLEND_MODE_MUL,
+ BLEND_MODE_PREMULT_ALPHA
};
private:
diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp
new file mode 100644
index 0000000000..1459f2c362
--- /dev/null
+++ b/scene/3d/immediate_geometry.cpp
@@ -0,0 +1,102 @@
+#include "immediate_geometry.h"
+
+
+void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture) {
+
+ VS::get_singleton()->immediate_begin(im,(VS::PrimitiveType)p_primitive,p_texture.is_valid()?p_texture->get_rid():RID());
+ if (p_texture.is_valid())
+ cached_textures.push_back(p_texture);
+
+}
+
+void ImmediateGeometry::set_normal(const Vector3& p_normal){
+
+ VS::get_singleton()->immediate_normal(im,p_normal);
+}
+
+void ImmediateGeometry::set_tangent(const Plane& p_tangent){
+
+ VS::get_singleton()->immediate_tangent(im,p_tangent);
+
+}
+
+void ImmediateGeometry::set_color(const Color& p_color){
+
+ VS::get_singleton()->immediate_color(im,p_color);
+
+}
+
+void ImmediateGeometry::set_uv(const Vector2& p_uv){
+
+ VS::get_singleton()->immediate_uv(im,p_uv);
+
+}
+
+void ImmediateGeometry::set_uv2(const Vector2& p_uv2){
+
+ VS::get_singleton()->immediate_uv2(im,p_uv2);
+
+}
+
+void ImmediateGeometry::add_vertex(const Vector3& p_vertex){
+
+ VS::get_singleton()->immediate_vertex(im,p_vertex);
+ if (empty) {
+ aabb.pos=p_vertex;
+ aabb.size=Vector3();
+ } else {
+ aabb.expand_to(p_vertex);
+ }
+}
+
+void ImmediateGeometry::end(){
+
+ VS::get_singleton()->immediate_end(im);
+
+}
+
+void ImmediateGeometry::clear(){
+
+ VS::get_singleton()->immediate_clear(im);
+ empty=true;
+ cached_textures.clear();
+
+}
+
+AABB ImmediateGeometry::get_aabb() const {
+
+ return aabb;
+}
+DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const {
+
+ return DVector<Face3>();
+}
+
+void ImmediateGeometry::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin);
+ ObjectTypeDB::bind_method(_MD("set_normal","normal"),&ImmediateGeometry::set_normal);
+ ObjectTypeDB::bind_method(_MD("set_tangent","tangent"),&ImmediateGeometry::set_tangent);
+ ObjectTypeDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color);
+ ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv);
+ ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2);
+ ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex);
+ ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end);
+ ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear);
+
+}
+
+ImmediateGeometry::ImmediateGeometry() {
+
+ im = VisualServer::get_singleton()->immediate_create();
+ set_base(im);
+ empty=true;
+
+}
+
+
+ImmediateGeometry::~ImmediateGeometry() {
+
+ VisualServer::get_singleton()->free(im);
+
+}
diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h
new file mode 100644
index 0000000000..2db81134c6
--- /dev/null
+++ b/scene/3d/immediate_geometry.h
@@ -0,0 +1,41 @@
+#ifndef IMMEDIATE_GEOMETRY_H
+#define IMMEDIATE_GEOMETRY_H
+
+#include "scene/3d/visual_instance.h"
+#include "scene/resources/mesh.h"
+
+class ImmediateGeometry : public GeometryInstance {
+
+ OBJ_TYPE(ImmediateGeometry,GeometryInstance);
+
+
+ RID im;
+ List<Ref<Texture> > cached_textures;
+ bool empty;
+ AABB aabb;
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ void begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture);
+ void set_normal(const Vector3& p_normal);
+ void set_tangent(const Plane& p_tangent);
+ void set_color(const Color& p_color);
+ void set_uv(const Vector2& tex_uv);
+ void set_uv2(const Vector2& tex_uv);
+
+ void add_vertex(const Vector3& p_vertex);
+
+ void end();
+ void clear();
+
+ virtual AABB get_aabb() const;
+ virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
+
+ ImmediateGeometry();
+ ~ImmediateGeometry();
+};
+
+#endif // IMMEDIATE_GEOMETRY_H
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
new file mode 100644
index 0000000000..21fdb9abd3
--- /dev/null
+++ b/scene/3d/sprite_3d.cpp
@@ -0,0 +1,772 @@
+#include "sprite_3d.h"
+#include "scene/scene_string_names.h"
+#include "core_string_names.h"
+
+
+Color SpriteBase3D::_get_color_accum() {
+
+ if (!color_dirty)
+ return color_accum;
+
+ if (parent_sprite)
+ color_accum=parent_sprite->_get_color_accum();
+ else
+ color_accum=Color(1,1,1,1);
+
+ color_accum.r*=modulate.r;
+ color_accum.g*=modulate.g;
+ color_accum.b*=modulate.b;
+ color_accum.a*=modulate.a;
+ color_dirty=false;
+ return color_accum;
+}
+
+void SpriteBase3D::_propagate_color_changed() {
+
+ if (color_dirty)
+ return;
+
+ color_dirty=true;
+ _queue_update();
+
+ for (List<SpriteBase3D*>::Element *E=children.front();E;E=E->next()) {
+
+ E->get()->_propagate_color_changed();
+ }
+}
+
+void SpriteBase3D::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_SCENE) {
+
+ if (!pending_update)
+ _im_update();
+
+ Node *parent=get_parent();
+ if (parent) {
+
+ parent_sprite=parent->cast_to<SpriteBase3D>();
+ if (parent_sprite) {
+ pI=parent_sprite->children.push_back(this);
+ }
+ }
+ }
+
+ if (p_what==NOTIFICATION_EXIT_SCENE) {
+
+
+ if (parent_sprite) {
+
+ parent_sprite->children.erase(pI);
+ pI=NULL;
+ parent_sprite=NULL;
+ }
+ }
+
+}
+
+
+void SpriteBase3D::set_centered(bool p_center) {
+
+ centered=p_center;
+ _queue_update();
+
+}
+
+bool SpriteBase3D::is_centered() const {
+
+ return centered;
+}
+
+void SpriteBase3D::set_offset(const Point2& p_offset) {
+
+ offset=p_offset;
+ _queue_update();
+
+}
+Point2 SpriteBase3D::get_offset() const {
+
+ return offset;
+}
+
+void SpriteBase3D::set_flip_h(bool p_flip) {
+
+ hflip=p_flip;
+ _queue_update();
+}
+bool SpriteBase3D::is_flipped_h() const {
+
+ return hflip;
+}
+
+void SpriteBase3D::set_flip_v(bool p_flip) {
+
+ vflip=p_flip;
+ _queue_update();
+}
+bool SpriteBase3D::is_flipped_v() const {
+
+ return vflip;
+}
+
+
+
+void SpriteBase3D::set_modulate(const Color& p_color) {
+
+ modulate=p_color;
+ _propagate_color_changed();
+ _queue_update();
+}
+
+Color SpriteBase3D::get_modulate() const{
+
+ return modulate;
+}
+
+
+void SpriteBase3D::set_pixel_size(float p_amount) {
+
+ pixel_size=p_amount;
+ _queue_update();
+}
+float SpriteBase3D::get_pixel_size() const {
+
+ return pixel_size;
+}
+
+void SpriteBase3D::set_opacity(float p_amount) {
+
+ opacity=p_amount;
+ _queue_update();
+}
+float SpriteBase3D::get_opacity() const {
+
+ return opacity;
+}
+
+
+void SpriteBase3D::set_axis(Vector3::Axis p_axis) {
+
+ axis=p_axis;
+ _queue_update();
+}
+Vector3::Axis SpriteBase3D::get_axis() const {
+
+ return axis;
+}
+
+
+
+void SpriteBase3D::_im_update() {
+
+
+ _draw();
+
+
+ pending_update=false;
+
+ //texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
+
+}
+
+void SpriteBase3D::_queue_update(){
+
+ if (pending_update)
+ return;
+
+ pending_update=true;
+ call_deferred(SceneStringNames::get_singleton()->_im_update);
+}
+
+
+AABB SpriteBase3D::get_aabb() const {
+
+ return aabb;
+}
+DVector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
+
+ return DVector<Face3>();
+
+}
+
+void SpriteBase3D::set_draw_flag(DrawFlags p_flag,bool p_enable) {
+
+ ERR_FAIL_INDEX(p_flag,FLAG_MAX);
+ flags[p_flag]=p_enable;
+ _queue_update();
+}
+
+bool SpriteBase3D::get_draw_flag(DrawFlags p_flag) const{
+ ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false);
+ return flags[p_flag];
+}
+
+void SpriteBase3D::set_alpha_cut_mode(AlphaCutMode p_mode){
+
+ ERR_FAIL_INDEX(p_mode,3);
+ alpha_cut=p_mode;
+ _queue_update();
+
+}
+
+SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const{
+
+ return alpha_cut;
+}
+
+
+void SpriteBase3D::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method(_MD("set_centered","centered"),&SpriteBase3D::set_centered);
+ ObjectTypeDB::bind_method(_MD("is_centered"),&SpriteBase3D::is_centered);
+
+ ObjectTypeDB::bind_method(_MD("set_offset","offset"),&SpriteBase3D::set_offset);
+ ObjectTypeDB::bind_method(_MD("get_offset"),&SpriteBase3D::get_offset);
+
+ ObjectTypeDB::bind_method(_MD("set_flip_h","flip_h"),&SpriteBase3D::set_flip_h);
+ ObjectTypeDB::bind_method(_MD("is_flipped_h"),&SpriteBase3D::is_flipped_h);
+
+ ObjectTypeDB::bind_method(_MD("set_flip_v","flip_v"),&SpriteBase3D::set_flip_v);
+ ObjectTypeDB::bind_method(_MD("is_flipped_v"),&SpriteBase3D::is_flipped_v);
+
+
+ ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&SpriteBase3D::set_modulate);
+ ObjectTypeDB::bind_method(_MD("get_modulate"),&SpriteBase3D::get_modulate);
+
+ ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&SpriteBase3D::set_opacity);
+ ObjectTypeDB::bind_method(_MD("get_opacity"),&SpriteBase3D::get_opacity);
+
+ ObjectTypeDB::bind_method(_MD("set_pixel_size","pixel_size"),&SpriteBase3D::set_pixel_size);
+ ObjectTypeDB::bind_method(_MD("get_pixel_size"),&SpriteBase3D::get_pixel_size);
+
+ ObjectTypeDB::bind_method(_MD("set_axis","axis"),&SpriteBase3D::set_axis);
+ ObjectTypeDB::bind_method(_MD("get_axis"),&SpriteBase3D::get_axis);
+
+ ObjectTypeDB::bind_method(_MD("set_draw_flag","flag","enabled"),&SpriteBase3D::set_draw_flag);
+ ObjectTypeDB::bind_method(_MD("get_draw_flag","flag"),&SpriteBase3D::get_draw_flag);
+
+ ObjectTypeDB::bind_method(_MD("set_alpha_cut_mode","mode"),&SpriteBase3D::set_alpha_cut_mode);
+ ObjectTypeDB::bind_method(_MD("get_alpha_cut_mode"),&SpriteBase3D::get_alpha_cut_mode);
+
+ ObjectTypeDB::bind_method(_MD("get_item_rect"),&SpriteBase3D::get_item_rect);
+
+ ObjectTypeDB::bind_method(_MD("_queue_update"),&SpriteBase3D::_queue_update);
+ ObjectTypeDB::bind_method(_MD("_im_update"),&SpriteBase3D::_im_update);
+
+
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "opacity",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "pixel_size",PROPERTY_HINT_RANGE,"0.0001,128,0.0001"), _SCS("set_pixel_size"),_SCS("get_pixel_size"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "axis",PROPERTY_HINT_ENUM,"X-Axis,Y-Axis,Z-Axis"), _SCS("set_axis"),_SCS("get_axis"));
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "flags/transparent"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_TRANSPARENT);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "flags/shaded"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_SHADED);
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "flags/alpha_cut",PROPERTY_HINT_ENUM,"Disabled,Discard,Opaque Pre-Pass"), _SCS("set_alpha_cut_mode"),_SCS("get_alpha_cut_mode"));
+
+
+ BIND_CONSTANT( FLAG_TRANSPARENT );
+ BIND_CONSTANT( FLAG_SHADED );
+ BIND_CONSTANT( FLAG_MAX );
+
+ BIND_CONSTANT( ALPHA_CUT_DISABLED );
+ BIND_CONSTANT( ALPHA_CUT_DISCARD );
+ BIND_CONSTANT( ALPHA_CUT_OPAQUE_PREPASS );
+}
+
+
+
+
+SpriteBase3D::SpriteBase3D() {
+
+ color_dirty=true;
+ centered=true;
+ hflip=false;
+ vflip=false;
+ parent_sprite=NULL;
+ pI=NULL;
+
+ for(int i=0;i<4;i++)
+ flags[i]=i==FLAG_TRANSPARENT;
+
+ axis=Vector3::AXIS_Z;
+ pixel_size=0.01;
+ modulate=Color(1,1,1,1);
+ pending_update=false;
+ opacity=1.0;
+ immediate = VisualServer::get_singleton()->immediate_create();
+ set_base(immediate);
+}
+
+
+SpriteBase3D::~SpriteBase3D() {
+
+ VisualServer::get_singleton()->free(immediate);
+}
+
+
+///////////////////////////////////////////
+
+
+void Sprite3D::_draw() {
+
+ RID immediate = get_immediate();
+
+ VS::get_singleton()->immediate_clear(immediate);
+ if (!texture.is_valid())
+ return; //no texuture no life
+ Vector2 tsize = texture->get_size();
+ if (tsize.x==0 || tsize.y==0)
+ return;
+
+ Size2i s;
+ Rect2i src_rect;
+
+ if (region) {
+
+ s=region_rect.size;
+ src_rect=region_rect;
+ } else {
+ s = texture->get_size();
+ s=s/Size2i(hframes,vframes);
+
+ src_rect.size=s;
+ src_rect.pos.x+=(frame%hframes)*s.x;
+ src_rect.pos.y+=(frame/hframes)*s.y;
+
+ }
+
+ Point2i ofs=get_offset();
+ if (is_centered())
+ ofs-=s/2;
+
+ Rect2i dst_rect(ofs,s);
+
+
+ Rect2 final_rect;
+ Rect2 final_src_rect;
+ if (!texture->get_rect_region(dst_rect,src_rect,final_rect,final_src_rect))
+ return;
+
+
+ if (final_rect.size.x==0 || final_rect.size.y==0)
+ return;
+
+ Color color=_get_color_accum();
+ color.a*=get_opacity();
+
+ float pixel_size=get_pixel_size();
+
+ Vector2 vertices[4]={
+
+ (final_rect.pos+Vector2(0,final_rect.size.y)) * pixel_size,
+ (final_rect.pos+final_rect.size) * pixel_size,
+ (final_rect.pos+Vector2(final_rect.size.x,0)) * pixel_size,
+ final_rect.pos * pixel_size,
+
+
+ };
+ Vector2 uvs[4]={
+ final_src_rect.pos / tsize,
+ (final_src_rect.pos+Vector2(final_src_rect.size.x,0)) / tsize,
+ (final_src_rect.pos+final_src_rect.size) / tsize,
+ (final_src_rect.pos+Vector2(0,final_src_rect.size.y)) / tsize,
+ };
+
+ if (is_flipped_h()) {
+ SWAP(uvs[0],uvs[1]);
+ SWAP(uvs[2],uvs[3]);
+ }
+ if (is_flipped_v()) {
+
+ SWAP(uvs[0],uvs[3]);
+ SWAP(uvs[1],uvs[2]);
+ }
+
+
+ Vector3 normal;
+ int axis = get_axis();
+ normal[axis]=1.0;
+
+ RID mat = VS::get_singleton()->material_2d_get(get_draw_flag(FLAG_SHADED),get_draw_flag(FLAG_TRANSPARENT),get_alpha_cut_mode()==ALPHA_CUT_DISCARD,get_alpha_cut_mode()==ALPHA_CUT_OPAQUE_PREPASS);
+ VS::get_singleton()->immediate_set_material(immediate,mat);
+
+ VS::get_singleton()->immediate_begin(immediate,VS::PRIMITIVE_TRIANGLE_FAN,texture->get_rid());
+
+ int x_axis = ((axis + 1) % 3);
+ int y_axis = ((axis + 2) % 3);
+
+ AABB aabb;
+
+ for(int i=0;i<4;i++) {
+ VS::get_singleton()->immediate_normal(immediate,normal);
+ VS::get_singleton()->immediate_color(immediate,color);
+ VS::get_singleton()->immediate_uv(immediate,uvs[i]);
+
+ Vector3 vtx;
+ vtx[x_axis]=vertices[i][x_axis];
+ vtx[y_axis]=vertices[i][y_axis];
+ VS::get_singleton()->immediate_vertex(immediate,vtx);
+ if (i==0) {
+ aabb.pos=vtx;
+ aabb.size=Vector3();
+ } else {
+ aabb.expand_to(vtx);
+ }
+ }
+ set_aabb(aabb);
+ VS::get_singleton()->immediate_end(immediate);
+
+
+}
+
+void Sprite3D::set_texture(const Ref<Texture>& p_texture) {
+
+ if (p_texture==texture)
+ return;
+ if (texture.is_valid()) {
+ texture->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_queue_update);
+ }
+ texture=p_texture;
+ if (texture.is_valid()) {
+ texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
+ texture->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_queue_update);
+ }
+ _queue_update();
+
+}
+
+Ref<Texture> Sprite3D::get_texture() const {
+
+ return texture;
+}
+
+void Sprite3D::set_region(bool p_region) {
+
+ if (p_region==region)
+ return;
+
+ region=p_region;
+ _queue_update();
+}
+
+bool Sprite3D::is_region() const{
+
+ return region;
+}
+
+void Sprite3D::set_region_rect(const Rect2& p_region_rect) {
+
+ bool changed=region_rect!=p_region_rect;
+ region_rect=p_region_rect;
+ if (region && changed) {
+ _queue_update();
+ }
+}
+
+Rect2 Sprite3D::get_region_rect() const {
+
+ return region_rect;
+}
+
+void Sprite3D::set_frame(int p_frame) {
+
+ ERR_FAIL_INDEX(p_frame,vframes*hframes);
+
+ if (frame != p_frame)
+
+ frame=p_frame;
+}
+
+int Sprite3D::get_frame() const {
+
+ return frame;
+}
+
+void Sprite3D::set_vframes(int p_amount) {
+
+ ERR_FAIL_COND(p_amount<1);
+ vframes=p_amount;
+ _queue_update();
+ _change_notify("frame");
+}
+int Sprite3D::get_vframes() const {
+
+ return vframes;
+}
+
+void Sprite3D::set_hframes(int p_amount) {
+
+ ERR_FAIL_COND(p_amount<1);
+ hframes=p_amount;
+ _queue_update();
+ _change_notify("frame");
+}
+int Sprite3D::get_hframes() const {
+
+ return hframes;
+}
+
+Rect2 Sprite3D::get_item_rect() const {
+
+ if (texture.is_null())
+ return Rect2(0,0,1,1);
+ //if (texture.is_null())
+ // return CanvasItem::get_item_rect();
+
+ Size2i s;
+
+ if (region) {
+
+ s=region_rect.size;
+ } else {
+ s = texture->get_size();
+ s=s/Point2(hframes,vframes);
+ }
+
+ Point2i ofs=get_offset();
+ if (is_centered())
+ ofs-=s/2;
+
+ if (s==Size2(0,0))
+ s=Size2(1,1);
+
+ return Rect2(ofs,s);
+}
+
+void Sprite3D::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite3D::set_texture);
+ ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Sprite3D::get_texture);
+
+ ObjectTypeDB::bind_method(_MD("set_region","enabled"),&Sprite3D::set_region);
+ ObjectTypeDB::bind_method(_MD("is_region"),&Sprite3D::is_region);
+
+ ObjectTypeDB::bind_method(_MD("set_region_rect","rect"),&Sprite3D::set_region_rect);
+ ObjectTypeDB::bind_method(_MD("get_region_rect"),&Sprite3D::get_region_rect);
+
+ ObjectTypeDB::bind_method(_MD("set_frame","frame"),&Sprite3D::set_frame);
+ ObjectTypeDB::bind_method(_MD("get_frame"),&Sprite3D::get_frame);
+
+ ObjectTypeDB::bind_method(_MD("set_vframes","vframes"),&Sprite3D::set_vframes);
+ ObjectTypeDB::bind_method(_MD("get_vframes"),&Sprite3D::get_vframes);
+
+ ObjectTypeDB::bind_method(_MD("set_hframes","hframes"),&Sprite3D::set_hframes);
+ ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes);
+
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
+ ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
+
+}
+
+Sprite3D::Sprite3D() {
+
+
+ region=false;
+ frame=0;
+ vframes=1;
+ hframes=1;
+
+}
+
+////////////////////////////////////////
+
+
+void AnimatedSprite3D::_draw() {
+
+ RID immediate = get_immediate();
+ VS::get_singleton()->immediate_clear(immediate);
+
+ if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) {
+ return;
+ }
+
+ Ref<Texture> texture = frames->get_frame(frame);
+ if (!texture.is_valid())
+ return; //no texuture no life
+ Vector2 tsize = texture->get_size();
+ if (tsize.x==0 || tsize.y==0)
+ return;
+
+ Size2i s=tsize;
+ Rect2i src_rect;
+
+ src_rect.size=s;
+
+ Point2i ofs=get_offset();
+ if (is_centered())
+ ofs-=s/2;
+
+ Rect2i dst_rect(ofs,s);
+
+
+ Rect2 final_rect;
+ Rect2 final_src_rect;
+ if (!texture->get_rect_region(dst_rect,src_rect,final_rect,final_src_rect))
+ return;
+
+
+ if (final_rect.size.x==0 || final_rect.size.y==0)
+ return;
+
+ Color color=_get_color_accum();
+ color.a*=get_opacity();
+
+ float pixel_size=get_pixel_size();
+
+ Vector2 vertices[4]={
+
+ (final_rect.pos+Vector2(0,final_rect.size.y)) * pixel_size,
+ (final_rect.pos+final_rect.size) * pixel_size,
+ (final_rect.pos+Vector2(final_rect.size.x,0)) * pixel_size,
+ final_rect.pos * pixel_size,
+
+
+ };
+ Vector2 uvs[4]={
+ final_src_rect.pos / tsize,
+ (final_src_rect.pos+Vector2(final_src_rect.size.x,0)) / tsize,
+ (final_src_rect.pos+final_src_rect.size) / tsize,
+ (final_src_rect.pos+Vector2(0,final_src_rect.size.y)) / tsize,
+ };
+
+ if (is_flipped_h()) {
+ SWAP(uvs[0],uvs[1]);
+ SWAP(uvs[2],uvs[3]);
+ }
+ if (is_flipped_v()) {
+
+ SWAP(uvs[0],uvs[3]);
+ SWAP(uvs[1],uvs[2]);
+ }
+
+
+ Vector3 normal;
+ int axis = get_axis();
+ normal[axis]=1.0;
+
+ RID mat = VS::get_singleton()->material_2d_get(get_draw_flag(FLAG_SHADED),get_draw_flag(FLAG_TRANSPARENT),get_alpha_cut_mode()==ALPHA_CUT_DISCARD,get_alpha_cut_mode()==ALPHA_CUT_OPAQUE_PREPASS);
+ VS::get_singleton()->immediate_set_material(immediate,mat);
+
+ VS::get_singleton()->immediate_begin(immediate,VS::PRIMITIVE_TRIANGLE_FAN,texture->get_rid());
+
+ int x_axis = ((axis + 1) % 3);
+ int y_axis = ((axis + 2) % 3);
+
+ AABB aabb;
+
+ for(int i=0;i<4;i++) {
+ VS::get_singleton()->immediate_normal(immediate,normal);
+ VS::get_singleton()->immediate_color(immediate,color);
+ VS::get_singleton()->immediate_uv(immediate,uvs[i]);
+
+ Vector3 vtx;
+ vtx[x_axis]=vertices[i][x_axis];
+ vtx[y_axis]=vertices[i][y_axis];
+ VS::get_singleton()->immediate_vertex(immediate,vtx);
+ if (i==0) {
+ aabb.pos=vtx;
+ aabb.size=Vector3();
+ } else {
+ aabb.expand_to(vtx);
+ }
+ }
+ set_aabb(aabb);
+ VS::get_singleton()->immediate_end(immediate);
+
+}
+
+void AnimatedSprite3D::_bind_methods(){
+
+ ObjectTypeDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames);
+ ObjectTypeDB::bind_method(_MD("get_sprite_frames:Texture"),&AnimatedSprite3D::get_sprite_frames);
+ ObjectTypeDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite3D::set_frame);
+ ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame);
+
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame"));
+
+}
+
+
+
+
+void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frames) {
+
+
+ if (frames==p_sprite_frames)
+ return;
+
+ if (frames.is_valid())
+ frames->disconnect("changed",this,"_queue_update");
+ frames=p_sprite_frames;
+ if (frames.is_valid())
+ frames->connect("changed",this,"_queue_update");
+
+ if (!frames.is_valid() || frame >=frames->get_frame_count()) {
+ frame=0;
+
+ }
+ _queue_update();
+
+}
+
+Ref<SpriteFrames> AnimatedSprite3D::get_sprite_frames() const{
+
+ return frames;
+}
+
+void AnimatedSprite3D::set_frame(int p_frame){
+
+ if (frames.is_null())
+ return;
+
+ ERR_FAIL_INDEX(p_frame,frames->get_frame_count());
+
+ if (frame==p_frame)
+ return;
+
+ frame=p_frame;
+ _queue_update();
+
+}
+int AnimatedSprite3D::get_frame() const{
+
+ return frame;
+}
+
+Rect2 AnimatedSprite3D::get_item_rect() const {
+
+ if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) {
+ return Rect2(0,0,1,1);
+ }
+
+ Ref<Texture> t = frames->get_frame(frame);
+ if (t.is_null())
+ return Rect2(0,0,1,1);
+ Size2i s = t->get_size();
+
+ Point2i ofs=get_offset();
+ if (is_centered())
+ ofs-=s/2;
+
+ if (s==Size2(0,0))
+ s=Size2(1,1);
+
+ return Rect2(ofs,s);
+}
+
+
+
+AnimatedSprite3D::AnimatedSprite3D() {
+
+ frame=0;
+}
+
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
new file mode 100644
index 0000000000..1330cd1c30
--- /dev/null
+++ b/scene/3d/sprite_3d.h
@@ -0,0 +1,191 @@
+#ifndef SPRITE_3D_H
+#define SPRITE_3D_H
+
+#include "scene/3d/visual_instance.h"
+#include "scene/2d/animated_sprite.h"
+
+
+class SpriteBase3D : public VisualInstance {
+
+ OBJ_TYPE(SpriteBase3D,VisualInstance);
+public:
+
+ enum DrawFlags {
+ FLAG_TRANSPARENT,
+ FLAG_SHADED,
+ FLAG_MAX
+
+ };
+
+ enum AlphaCutMode {
+ ALPHA_CUT_DISABLED,
+ ALPHA_CUT_DISCARD,
+ ALPHA_CUT_OPAQUE_PREPASS
+ };
+
+private:
+
+
+ bool color_dirty;
+ Color color_accum;
+
+ SpriteBase3D *parent_sprite;
+ List<SpriteBase3D*> children;
+ List<SpriteBase3D*>::Element *pI;
+
+ bool centered;
+ Point2 offset;
+
+ bool hflip;
+ bool vflip;
+
+
+ Color modulate;
+ float opacity;
+
+ Vector3::Axis axis;
+ float pixel_size;
+ AABB aabb;
+
+ RID immediate;
+
+ bool flags[FLAG_MAX];
+ AlphaCutMode alpha_cut;
+ bool pending_update;
+ void _im_update();
+
+
+ void _propagate_color_changed();
+
+protected:
+
+ Color _get_color_accum();
+ void _notification(int p_what);
+ static void _bind_methods();
+ virtual void _draw()=0;
+ _FORCE_INLINE_ void set_aabb(const AABB& p_aabb) { aabb=p_aabb; }
+ _FORCE_INLINE_ RID& get_immediate() { return immediate; }
+ void _queue_update();
+public:
+
+ void set_centered(bool p_center);
+ bool is_centered() const;
+
+ void set_offset(const Point2& p_offset);
+ Point2 get_offset() const;
+
+ void set_flip_h(bool p_flip);
+ bool is_flipped_h() const;
+
+ void set_flip_v(bool p_flip);
+ bool is_flipped_v() const;
+
+ void set_region(bool p_region);
+ bool is_region() const;
+
+ void set_region_rect(const Rect2& p_region_rect);
+ Rect2 get_region_rect() const;
+
+ void set_modulate(const Color& p_color);
+ Color get_modulate() const;
+
+ void set_opacity(float p_amount);
+ float get_opacity() const;
+
+ void set_pixel_size(float p_amount);
+ float get_pixel_size() const;
+
+ void set_axis(Vector3::Axis p_amount);
+ Vector3::Axis get_axis() const;
+
+ void set_draw_flag(DrawFlags p_flag,bool p_enable);
+ bool get_draw_flag(DrawFlags p_flag) const;
+
+ void set_alpha_cut_mode(AlphaCutMode p_mode);
+ AlphaCutMode get_alpha_cut_mode() const;
+
+ virtual Rect2 get_item_rect() const=0;
+
+ virtual AABB get_aabb() const;
+ virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
+
+ SpriteBase3D();
+ ~SpriteBase3D();
+};
+
+
+class Sprite3D : public SpriteBase3D {
+
+ OBJ_TYPE(Sprite3D,SpriteBase3D);
+ Ref<Texture> texture;
+
+
+ bool region;
+ Rect2 region_rect;
+
+ int frame;
+
+ int vframes;
+ int hframes;
+protected:
+ virtual void _draw();
+ static void _bind_methods();
+public:
+
+
+
+ void set_texture(const Ref<Texture>& p_texture);
+ Ref<Texture> get_texture() const;
+
+ void set_region(bool p_region);
+ bool is_region() const;
+
+ void set_region_rect(const Rect2& p_region_rect);
+ Rect2 get_region_rect() const;
+
+ void set_frame(int p_frame);
+ int get_frame() const;
+
+ void set_vframes(int p_amount);
+ int get_vframes() const;
+
+ void set_hframes(int p_amount);
+ int get_hframes() const;
+
+ virtual Rect2 get_item_rect() const;
+
+ Sprite3D();
+// ~Sprite3D();
+};
+
+class AnimatedSprite3D : public SpriteBase3D {
+
+ OBJ_TYPE(AnimatedSprite3D,SpriteBase3D);
+ Ref<SpriteFrames> frames;
+
+
+ int frame;
+
+protected:
+ virtual void _draw();
+ static void _bind_methods();
+public:
+
+
+
+ void set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frames);
+ Ref<SpriteFrames> get_sprite_frames() const;
+
+ void set_frame(int p_frame);
+ int get_frame() const;
+
+
+ virtual Rect2 get_item_rect() const;
+
+ AnimatedSprite3D();
+// ~AnimatedSprite3D();
+};
+
+VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags);
+VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode);
+#endif // SPRITE_3D_H
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index a2f837c3c4..b7918994d8 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -398,12 +398,15 @@ void Label::regenerate_word_cache() {
}
if (current=='\n') {
-
insert_newline=true;
} else {
total_char_cache++;
}
+ if (i<text.length() && text[i] == ' ') {
+ total_char_cache--; // do not count spaces
+ }
+
} else {
@@ -442,7 +445,8 @@ void Label::regenerate_word_cache() {
last_width=line_width;
}
-
+
+ total_char_cache -= line_count + 1; // do not count new lines (including the first one)
if (!autowrap) {
@@ -519,6 +523,7 @@ String Label::get_text() const {
return text;
}
+
void Label::set_visible_characters(int p_amount) {
visible_chars=p_amount;
@@ -582,7 +587,7 @@ void Label::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),_SCS("set_valign"),_SCS("get_valign") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autowrap"),_SCS("set_autowrap"),_SCS("has_autowrap") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "uppercase"),_SCS("set_uppercase"),_SCS("is_uppercase") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "percent_visible"),_SCS("set_percent_visible"),_SCS("get_percent_visible") );
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_percent_visible"),_SCS("get_percent_visible") );
}
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b30ad2d71f..f3d757b601 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -189,6 +189,8 @@
#include "scene/3d/multimesh_instance.h"
#include "scene/3d/baked_light.h"
#include "scene/3d/ray_cast.h"
+#include "scene/3d/immediate_geometry.h"
+#include "scene/3d/sprite_3d.h"
#include "scene/3d/spatial_sample_player.h"
#include "scene/3d/spatial_stream_player.h"
#include "scene/3d/proximity_group.h"
@@ -372,6 +374,9 @@ void register_scene_types() {
ObjectTypeDB::register_type<InterpolatedCamera>();
ObjectTypeDB::register_type<TestCube>();
ObjectTypeDB::register_type<MeshInstance>();
+ ObjectTypeDB::register_type<ImmediateGeometry>();
+ ObjectTypeDB::register_type<Sprite3D>();
+ ObjectTypeDB::register_type<AnimatedSprite3D>();
ObjectTypeDB::register_virtual_type<Light>();
ObjectTypeDB::register_type<DirectionalLight>();
ObjectTypeDB::register_type<OmniLight>();
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 0c55d22dbe..99447c0a0e 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -109,9 +109,13 @@ void Environment::_bind_methods() {
ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/cubemap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CUBEMAP);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/energy",PROPERTY_HINT_RANGE,"0,128,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_ENERGY);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/scale",PROPERTY_HINT_RANGE,"0.001,16,0.001"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_SCALE);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/glow",PROPERTY_HINT_RANGE,"0.00,8,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_GLOW);
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"glow/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GLOW);
ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_passes",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_PASSES);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/blur_scale",PROPERTY_HINT_RANGE,"0.01,4,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_SCALE);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/blur_strength",PROPERTY_HINT_RANGE,"0.01,4,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_STRENGTH);
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_blend_mode",PROPERTY_HINT_ENUM,"Additive,Screen,SoftLight"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_BLEND_MODE);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/bloom",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLOOM);
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/bloom_treshold",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLOOM_TRESHOLD);
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"dof_blur/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_DOF_BLUR);
@@ -180,6 +184,7 @@ void Environment::_bind_methods() {
BIND_CONSTANT( BG_PARAM_TEXTURE );
BIND_CONSTANT( BG_PARAM_CUBEMAP );
BIND_CONSTANT( BG_PARAM_ENERGY );
+ BIND_CONSTANT( BG_PARAM_GLOW );
BIND_CONSTANT( BG_PARAM_MAX );
@@ -193,7 +198,14 @@ void Environment::_bind_methods() {
BIND_CONSTANT( FX_MAX );
+ BIND_CONSTANT( FX_BLUR_BLEND_MODE_ADDITIVE );
+ BIND_CONSTANT( FX_BLUR_BLEND_MODE_SCREEN );
+ BIND_CONSTANT( FX_BLUR_BLEND_MODE_SOFTLIGHT );
+
BIND_CONSTANT( FX_PARAM_GLOW_BLUR_PASSES );
+ BIND_CONSTANT( FX_PARAM_GLOW_BLUR_SCALE );
+ BIND_CONSTANT( FX_PARAM_GLOW_BLUR_STRENGTH );
+ BIND_CONSTANT( FX_PARAM_GLOW_BLUR_BLEND_MODE );
BIND_CONSTANT( FX_PARAM_GLOW_BLOOM);
BIND_CONSTANT( FX_PARAM_GLOW_BLOOM_TRESHOLD);
BIND_CONSTANT( FX_PARAM_DOF_BLUR_PASSES );
@@ -229,11 +241,14 @@ Environment::Environment() {
set_background_param(BG_PARAM_CUBEMAP,Ref<CubeMap>());
set_background_param(BG_PARAM_ENERGY,1.0);
set_background_param(BG_PARAM_SCALE,1.0);
+ set_background_param(BG_PARAM_GLOW,0.0);
for(int i=0;i<FX_MAX;i++)
set_enable_fx(Fx(i),false);
fx_set_param(FX_PARAM_GLOW_BLUR_PASSES,1);
+ fx_set_param(FX_PARAM_GLOW_BLUR_SCALE,1);
+ fx_set_param(FX_PARAM_GLOW_BLUR_STRENGTH,1);
fx_set_param(FX_PARAM_GLOW_BLOOM,0.0);
fx_set_param(FX_PARAM_GLOW_BLOOM_TRESHOLD,0.5);
fx_set_param(FX_PARAM_DOF_BLUR_PASSES,1);
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index b90a043634..627fbb7cc0 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -56,6 +56,7 @@ public:
BG_PARAM_CUBEMAP=VS::ENV_BG_PARAM_CUBEMAP,
BG_PARAM_ENERGY=VS::ENV_BG_PARAM_ENERGY,
BG_PARAM_SCALE=VS::ENV_BG_PARAM_SCALE,
+ BG_PARAM_GLOW=VS::ENV_BG_PARAM_GLOW,
BG_PARAM_MAX=VS::ENV_BG_PARAM_MAX
};
@@ -70,8 +71,17 @@ public:
FX_MAX=VS::ENV_FX_MAX,
};
+ enum FxBlurBlendMode {
+ FX_BLUR_BLEND_MODE_ADDITIVE,
+ FX_BLUR_BLEND_MODE_SCREEN,
+ FX_BLUR_BLEND_MODE_SOFTLIGHT,
+ };
+
enum FxParam {
FX_PARAM_GLOW_BLUR_PASSES=VS::ENV_FX_PARAM_GLOW_BLUR_PASSES,
+ FX_PARAM_GLOW_BLUR_SCALE=VS::ENV_FX_PARAM_GLOW_BLUR_SCALE,
+ FX_PARAM_GLOW_BLUR_STRENGTH=VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH,
+ FX_PARAM_GLOW_BLUR_BLEND_MODE=VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE,
FX_PARAM_GLOW_BLOOM=VS::ENV_FX_PARAM_GLOW_BLOOM,
FX_PARAM_GLOW_BLOOM_TRESHOLD=VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD,
FX_PARAM_DOF_BLUR_PASSES=VS::ENV_FX_PARAM_DOF_BLUR_PASSES,
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 637a816112..091a46d4ab 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -45,6 +45,7 @@ static const char*_hint_names[Material::HINT_MAX]={
"opaque_pre_zpass",
"no_shadow",
"no_depth_draw",
+ "no_alpha_depth_draw",
};
static const Material::Flag _flag_indices[Material::FLAG_MAX]={
@@ -158,7 +159,7 @@ void Material::_bind_methods() {
for(int i=0;i<HINT_MAX;i++)
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, String()+"hints/"+_hint_names[i] ),_SCS("set_hint"),_SCS("get_hint"),_hint_indices[i]);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "params/blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub" ), _SCS("set_blend_mode"),_SCS("get_blend_mode"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "params/blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,PMAlpha" ), _SCS("set_blend_mode"),_SCS("get_blend_mode"));
ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/line_width",PROPERTY_HINT_RANGE,"0.1,32.0,0.1" ), _SCS("set_line_width"),_SCS("get_line_width"));
@@ -175,6 +176,7 @@ void Material::_bind_methods() {
BIND_CONSTANT( HINT_OPAQUE_PRE_PASS );
BIND_CONSTANT( HINT_NO_SHADOW );
BIND_CONSTANT( HINT_NO_DEPTH_DRAW );
+ BIND_CONSTANT( HINT_NO_DEPTH_DRAW_FOR_ALPHA );
BIND_CONSTANT( HINT_MAX );
BIND_CONSTANT( SHADE_MODEL_LAMBERT );
@@ -189,6 +191,8 @@ void Material::_bind_methods() {
BIND_CONSTANT( BLEND_MODE_MIX );
BIND_CONSTANT( BLEND_MODE_ADD );
BIND_CONSTANT( BLEND_MODE_SUB );
+ BIND_CONSTANT( BLEND_MODE_MUL );
+ BIND_CONSTANT( BLEND_MODE_PREMULT_ALPHA );
}
@@ -206,6 +210,7 @@ Material::Material(const RID& p_material) {
for(int i=0;i<HINT_MAX;i++)
hints[i]=false;
+ hints[HINT_NO_DEPTH_DRAW_FOR_ALPHA]=true;
blend_mode=BLEND_MODE_MIX;
shade_model = SHADE_MODEL_LAMBERT;
@@ -363,14 +368,14 @@ Material::BlendMode FixedMaterial::get_detail_blend_mode() const {
}
void FixedMaterial::set_fixed_flag(FixedFlag p_flag, bool p_value) {
- ERR_FAIL_INDEX(p_flag,3);
+ ERR_FAIL_INDEX(p_flag,4);
fixed_flags[p_flag]=p_value;
VisualServer::get_singleton()->fixed_material_set_flag(material,(VS::FixedMaterialFlags)p_flag,p_value);
}
bool FixedMaterial::get_fixed_flag(FixedFlag p_flag) const {
- ERR_FAIL_INDEX_V(p_flag,3,false);
+ ERR_FAIL_INDEX_V(p_flag,4,false);
return fixed_flags[p_flag];
}
@@ -417,6 +422,7 @@ void FixedMaterial::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_ALPHA);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_color_array" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_COLOR_ARRAY);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_point_size" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_POINT_SIZE);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/discard_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_DISCARD_ALPHA);
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/diffuse" ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_DIFFUSE);
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/specular", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPECULAR );
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/emission", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_EMISSION );
@@ -455,6 +461,7 @@ void FixedMaterial::_bind_methods() {
BIND_CONSTANT( FLAG_USE_ALPHA );
BIND_CONSTANT( FLAG_USE_COLOR_ARRAY );
BIND_CONSTANT( FLAG_USE_POINT_SIZE );
+ BIND_CONSTANT( FLAG_DISCARD_ALPHA );
}
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 7bd8b70fa4..2057b3cac9 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -75,6 +75,7 @@ public:
BLEND_MODE_MUL = VS::MATERIAL_BLEND_MODE_MUL,
BLEND_MODE_ADD = VS::MATERIAL_BLEND_MODE_ADD,
BLEND_MODE_SUB = VS::MATERIAL_BLEND_MODE_SUB,
+ BLEND_MODE_PREMULT_ALPHA = VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA,
};
@@ -84,6 +85,7 @@ public:
HINT_OPAQUE_PRE_PASS=VS::MATERIAL_HINT_OPAQUE_PRE_PASS,
HINT_NO_SHADOW=VS::MATERIAL_HINT_NO_SHADOW,
HINT_NO_DEPTH_DRAW=VS::MATERIAL_HINT_NO_DEPTH_DRAW,
+ HINT_NO_DEPTH_DRAW_FOR_ALPHA=VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA,
HINT_MAX=VS::MATERIAL_HINT_MAX
};
@@ -158,6 +160,7 @@ public:
FLAG_USE_ALPHA=VS::FIXED_MATERIAL_FLAG_USE_ALPHA,
FLAG_USE_COLOR_ARRAY=VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
FLAG_USE_POINT_SIZE=VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
+ FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA
};
private:
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index baf6fa9d8d..5b31ba1f1b 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -53,6 +53,13 @@ void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect
VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate);
}
+bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const {
+
+ r_rect=p_rect;
+ r_src_rect=p_src_rect;
+
+ return true;
+}
void Texture::_bind_methods() {
@@ -302,6 +309,16 @@ void ImageTexture::fix_alpha_edges() {
}
}
+void ImageTexture::premultiply_alpha() {
+
+ if (format==Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) {
+
+ Image img = get_data();
+ img.premultiply_alpha();
+ set_data(img);
+ }
+}
+
bool ImageTexture::has_alpha() const {
return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA );
@@ -386,8 +403,10 @@ void ImageTexture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality","quality"),&ImageTexture::set_lossy_storage_quality);
ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality);
ObjectTypeDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges);
+ ObjectTypeDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha);
ObjectTypeDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override);
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ObjectTypeDB::set_method_flags(get_type_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
ObjectTypeDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook);
@@ -597,6 +616,42 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const
VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate);
}
+bool AtlasTexture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const {
+
+ Rect2 rc=region;
+
+ if (!atlas.is_valid())
+ return false;
+
+ Rect2 src=p_src_rect;
+ src.pos+=(rc.pos-margin.pos);
+ Rect2 src_c = rc.clip(src);
+ if (src_c.size==Size2())
+ return false;
+ Vector2 ofs = (src_c.pos-src.pos);
+
+ Vector2 scale = p_rect.size / p_src_rect.size;
+ if(scale.x < 0)
+ {
+ float mx = (margin.size.width - margin.pos.x);
+ mx -= margin.pos.x;
+ ofs.x = -(ofs.x + mx);
+ }
+ if(scale.y < 0)
+ {
+ float my = margin.size.height - margin.pos.y;
+ my -= margin.pos.y;
+ ofs.y = -(ofs.y + my);
+ }
+ Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale );
+
+
+
+ r_rect=dr;
+ r_src_rect=src_c;
+ return true;
+}
+
AtlasTexture::AtlasTexture() {
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 6259362882..86ff246498 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -70,6 +70,7 @@ public:
virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+ virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
@@ -143,6 +144,7 @@ public:
float get_lossy_storage_quality() const;
void fix_alpha_edges();
+ void premultiply_alpha();
void set_size_override(const Size2& p_size);
@@ -190,6 +192,7 @@ public:
virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+ virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
AtlasTexture();
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 5c54bd74e3..a8e4c80f89 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -137,5 +137,7 @@ SceneStringNames::SceneStringNames() {
drop_data = StaticCString::create("drop_data");
can_drop_data = StaticCString::create("can_drop_data");
+ _im_update = StaticCString::create("_im_update");
+ _queue_update = StaticCString::create("_queue_update");
}
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 6a4e58ed54..2286712250 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -145,6 +145,10 @@ public:
StringName play_play;
+ StringName _im_update;
+ StringName _queue_update;
+
+
};
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index 2de49d3d81..e21848eac2 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -157,6 +157,9 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
if (p_key.use_alpha) {
code+="DIFFUSE_ALPHA=diffuse;\n";
+ if (p_key.discard_alpha) {
+ code+="DISCARD=diffuse.a<0.5;\n";
+ }
} else {
code+="DIFFUSE=diffuse.rgb;\n";
}
@@ -262,6 +265,7 @@ void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) {
void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) {
+
Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
FixedMaterial &fm=*E->get();
@@ -271,6 +275,7 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags
case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: fm.use_alpha=p_enabled; break;
case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: fm.use_color_array=p_enabled; break;
case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: fm.use_pointsize=p_enabled; break;
+ case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: fm.discard_alpha=p_enabled; break;
}
if (!fm.dirty_list.in_list())
@@ -288,6 +293,7 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags
case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: return fm.use_alpha;; break;
case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: return fm.use_color_array;; break;
case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: return fm.use_pointsize;; break;
+ case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: return fm.discard_alpha;; break;
}
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 783231d2e5..a3cdff9859 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -55,6 +55,7 @@ protected:
bool use_alpha:1;
bool use_color_array:1;
bool use_pointsize:1;
+ bool discard_alpha:1;
bool valid:1;
};
@@ -80,6 +81,7 @@ protected:
RID self;
bool use_alpha;
bool use_color_array;
+ bool discard_alpha;
bool use_pointsize;
float point_size;
Transform uv_xform;
@@ -100,6 +102,7 @@ protected:
k.use_alpha=use_alpha;
k.use_color_array=use_color_array;
k.use_pointsize=use_pointsize;
+ k.discard_alpha=discard_alpha;
k.detail_blend=detail_blend;
k.valid=true;
for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) {
@@ -119,6 +122,7 @@ protected:
use_alpha=false;
use_color_array=false;
use_pointsize=false;
+ discard_alpha=false;
point_size=1.0;
detail_blend=VS::MATERIAL_BLEND_MODE_MIX;
for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) {
@@ -298,6 +302,22 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const=0;
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create()=0;
+ virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID())=0;
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0;
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0;
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0;
+ virtual void immediate_color(RID p_immediate,const Color& p_color)=0;
+ virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0;
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0;
+ virtual void immediate_end(RID p_immediate)=0;
+ virtual void immediate_clear(RID p_immediate)=0;
+ virtual AABB immediate_get_aabb(RID p_immediate) const=0;
+ virtual void immediate_set_material(RID p_immediate,RID p_material)=0;
+ virtual RID immediate_get_material(RID p_immediate) const=0;
+
/* PARTICLES API */
@@ -487,6 +507,7 @@ public:
virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data)=0;
virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data)=0;
+ virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data)=0;
virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data)=0;
@@ -544,6 +565,7 @@ public:
virtual bool is_material(const RID& p_rid) const=0;
virtual bool is_mesh(const RID& p_rid) const=0;
virtual bool is_multimesh(const RID& p_rid) const=0;
+ virtual bool is_immediate(const RID& p_rid) const=0;
virtual bool is_particles(const RID &p_beam) const=0;
virtual bool is_light(const RID& p_rid) const=0;
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
index 39c02c2037..1d55693bfb 100644
--- a/servers/visual/rasterizer_dummy.cpp
+++ b/servers/visual/rasterizer_dummy.cpp
@@ -709,6 +709,74 @@ int RasterizerDummy::multimesh_get_visible_instances(RID p_multimesh) const {
}
+/* IMMEDIATE API */
+
+
+RID RasterizerDummy::immediate_create() {
+
+ Immediate *im = memnew( Immediate );
+ return immediate_owner.make_rid(im);
+
+}
+
+void RasterizerDummy::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){
+
+
+}
+void RasterizerDummy::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+
+}
+void RasterizerDummy::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+
+}
+void RasterizerDummy::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+
+}
+void RasterizerDummy::immediate_color(RID p_immediate,const Color& p_color){
+
+
+}
+void RasterizerDummy::immediate_uv(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+void RasterizerDummy::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+
+void RasterizerDummy::immediate_end(RID p_immediate){
+
+
+}
+void RasterizerDummy::immediate_clear(RID p_immediate) {
+
+
+}
+
+AABB RasterizerDummy::immediate_get_aabb(RID p_immediate) const {
+
+ return AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+}
+
+void RasterizerDummy::immediate_set_material(RID p_immediate,RID p_material) {
+
+ Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND(!im);
+ im->material=p_material;
+
+}
+
+RID RasterizerDummy::immediate_get_material(RID p_immediate) const {
+
+ const Immediate *im = immediate_owner.get(p_immediate);
+ ERR_FAIL_COND_V(!im,RID());
+ return im->material;
+
+}
/* PARTICLES API */
@@ -1627,6 +1695,12 @@ bool RasterizerDummy::is_mesh(const RID& p_rid) const {
return mesh_owner.owns(p_rid);
}
+
+bool RasterizerDummy::is_immediate(const RID& p_rid) const {
+
+ return immediate_owner.owns(p_rid);
+}
+
bool RasterizerDummy::is_multimesh(const RID& p_rid) const {
return multimesh_owner.owns(p_rid);
@@ -1703,6 +1777,12 @@ void RasterizerDummy::free(const RID& p_rid) {
multimesh_owner.free(p_rid);
memdelete(multimesh);
+ } else if (immediate_owner.owns(p_rid)) {
+
+ Immediate *immediate = immediate_owner.get(p_rid);
+ immediate_owner.free(p_rid);
+ memdelete(immediate);
+
} else if (particles_owner.owns(p_rid)) {
Particles *particles = particles_owner.get(p_rid);
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
index 880e19c9b0..b683a25bdc 100644
--- a/servers/visual/rasterizer_dummy.h
+++ b/servers/visual/rasterizer_dummy.h
@@ -231,8 +231,18 @@ class RasterizerDummy : public Rasterizer {
};
+
mutable RID_Owner<MultiMesh> multimesh_owner;
+ struct Immediate {
+
+
+ RID material;
+ int empty;
+ };
+
+ mutable RID_Owner<Immediate> immediate_owner;
+
struct Particles : public Geometry {
ParticleSystemSW data; // software particle system
@@ -490,6 +500,23 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create();
+ virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+ virtual void immediate_color(RID p_immediate,const Color& p_color);
+ virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_end(RID p_immediate);
+ virtual void immediate_clear(RID p_immediate);
+ virtual void immediate_set_material(RID p_immediate,RID p_material);
+ virtual RID immediate_get_material(RID p_immediate) const;
+
+ virtual AABB immediate_get_aabb(RID p_mesh) const;
+
/* PARTICLES API */
virtual RID particles_create();
@@ -647,6 +674,7 @@ public:
virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
+ virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {}
virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
virtual void end_scene();
@@ -692,6 +720,7 @@ public:
virtual bool is_texture(const RID& p_rid) const;
virtual bool is_material(const RID& p_rid) const;
virtual bool is_mesh(const RID& p_rid) const;
+ virtual bool is_immediate(const RID& p_rid) const;
virtual bool is_multimesh(const RID& p_rid) const;
virtual bool is_particles(const RID &p_beam) const;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 3061c2ddff..cdc1f678e7 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1034,7 +1034,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={
{ "SPEC_EXP", TYPE_FLOAT},
{ "GLOW", TYPE_FLOAT},
{ "SHADE_PARAM", TYPE_FLOAT},
- { "DISCARD", TYPE_FLOAT},
+ { "DISCARD", TYPE_BOOL},
{ "SCREEN_UV", TYPE_VEC2},
{ "POINT_COORD", TYPE_VEC2},
{ "INV_CAMERA_MATRIX", TYPE_MAT4},
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 6b74b34ba1..bffc1c43fe 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -519,6 +519,72 @@ int VisualServerRaster::multimesh_get_visible_instances(RID p_multimesh) const {
}
+/* IMMEDIATE API */
+
+
+RID VisualServerRaster::immediate_create() {
+
+ return rasterizer->immediate_create();
+}
+
+void VisualServerRaster::immediate_begin(RID p_immediate,PrimitiveType p_primitive,RID p_texture){
+
+ rasterizer->immediate_begin(p_immediate,p_primitive,p_texture);
+}
+void VisualServerRaster::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+ rasterizer->immediate_vertex(p_immediate,p_vertex);
+
+}
+void VisualServerRaster::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+ rasterizer->immediate_normal(p_immediate,p_normal);
+
+}
+void VisualServerRaster::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+ rasterizer->immediate_tangent(p_immediate,p_tangent);
+
+}
+void VisualServerRaster::immediate_color(RID p_immediate,const Color& p_color){
+
+ rasterizer->immediate_color(p_immediate,p_color);
+
+}
+void VisualServerRaster::immediate_uv(RID p_immediate,const Vector2& p_uv){
+
+ rasterizer->immediate_uv(p_immediate,p_uv);
+
+}
+void VisualServerRaster::immediate_uv2(RID p_immediate,const Vector2& p_uv2){
+
+ rasterizer->immediate_uv2(p_immediate,p_uv2);
+
+}
+void VisualServerRaster::immediate_end(RID p_immediate){
+
+ VS_CHANGED;
+ _dependency_queue_update(p_immediate,true);
+ rasterizer->immediate_end(p_immediate);
+
+}
+void VisualServerRaster::immediate_clear(RID p_immediate){
+
+ VS_CHANGED;
+ _dependency_queue_update(p_immediate,true);
+ rasterizer->immediate_clear(p_immediate);
+
+}
+
+void VisualServerRaster::immediate_set_material(RID p_immediate,RID p_material) {
+
+ rasterizer->immediate_set_material(p_immediate,p_material);
+}
+
+RID VisualServerRaster::immediate_get_material(RID p_immediate) const {
+
+ return rasterizer->immediate_get_material(p_immediate);
+}
/* PARTICLES API */
@@ -1705,6 +1771,8 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
instance->data.morph_values.resize( rasterizer->mesh_get_morph_target_count(p_base));
} else if (rasterizer->is_multimesh(p_base)) {
instance->base_type=INSTANCE_MULTIMESH;
+ } else if (rasterizer->is_immediate(p_base)) {
+ instance->base_type=INSTANCE_IMMEDIATE;
} else if (rasterizer->is_particles(p_base)) {
instance->base_type=INSTANCE_PARTICLES;
instance->particles_info=memnew( Instance::ParticlesInfo );
@@ -2468,6 +2536,12 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) {
new_aabb = rasterizer->multimesh_get_aabb(p_instance->base_rid);
} break;
+ case VisualServer::INSTANCE_IMMEDIATE: {
+
+ new_aabb = rasterizer->immediate_get_aabb(p_instance->base_rid);
+
+
+ } break;
case VisualServer::INSTANCE_PARTICLES: {
new_aabb = rasterizer->particles_get_aabb(p_instance->base_rid);
@@ -3498,6 +3572,9 @@ void VisualServerRaster::_instance_draw(Instance *p_instance) {
case INSTANCE_MULTIMESH: {
rasterizer->add_multimesh(p_instance->base_rid, &p_instance->data);
} break;
+ case INSTANCE_IMMEDIATE: {
+ rasterizer->add_immediate(p_instance->base_rid, &p_instance->data);
+ } break;
case INSTANCE_PARTICLES: {
rasterizer->add_particles(p_instance->particles_info->instance, &p_instance->data);
} break;
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index c281e0b9e6..f6ef4ba6d5 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -766,6 +766,21 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
virtual int multimesh_get_visible_instances(RID p_multimesh) const;
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create();
+ virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID());
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+ virtual void immediate_color(RID p_immediate,const Color& p_color);
+ virtual void immediate_uv(RID p_immediate, const Vector2& p_uv);
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+ virtual void immediate_end(RID p_immediate);
+ virtual void immediate_clear(RID p_immediate);
+ virtual void immediate_set_material(RID p_immediate,RID p_material);
+ virtual RID immediate_get_material(RID p_immediate) const;
+
/* PARTICLES API */
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 87e13cb202..cfc4bd8605 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -741,6 +741,22 @@ public:
FUNC2(multimesh_set_visible_instances,RID,int);
FUNC1RC(int,multimesh_get_visible_instances,RID);
+ /* IMMEDIATE API */
+
+
+ FUNC0R(RID,immediate_create);
+ FUNC3(immediate_begin,RID,PrimitiveType,RID);
+ FUNC2(immediate_vertex,RID,const Vector3&);
+ FUNC2(immediate_normal,RID,const Vector3&);
+ FUNC2(immediate_tangent,RID,const Plane&);
+ FUNC2(immediate_color,RID,const Color&);
+ FUNC2(immediate_uv,RID,const Vector2&);
+ FUNC2(immediate_uv2,RID,const Vector2&);
+ FUNC1(immediate_end,RID);
+ FUNC1(immediate_clear,RID);
+ FUNC2(immediate_set_material,RID,RID);
+ FUNC1RC(RID,immediate_get_material,RID);
+
/* PARTICLES API */
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index a45e2c8eaf..08cc57e307 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -274,6 +274,55 @@ RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) {
return mesh;
}
+
+RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha, bool p_opaque_prepass) {
+
+ int version=0;
+ if (p_shaded)
+ version=1;
+ if (p_transparent)
+ version|=2;
+ if (p_cut_alpha)
+ version|=4;
+ if (p_opaque_prepass)
+ version|=8;
+ if (material_2d[version].is_valid())
+ return material_2d[version];
+
+ //not valid, make
+
+ material_2d[version]=fixed_material_create();
+ fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_ALPHA,p_transparent);
+ fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
+ fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_DISCARD_ALPHA,p_cut_alpha);
+ material_set_flag(material_2d[version],MATERIAL_FLAG_UNSHADED,!p_shaded);
+ material_set_flag(material_2d[version],MATERIAL_FLAG_DOUBLE_SIDED,true);
+ material_set_hint(material_2d[version],MATERIAL_HINT_OPAQUE_PRE_PASS,p_opaque_prepass);
+ fixed_material_set_texture(material_2d[version],FIXED_MATERIAL_PARAM_DIFFUSE,get_white_texture());
+ //material cut alpha?
+ return material_2d[version];
+}
+
+RID VisualServer::get_white_texture() {
+
+ if (white_texture.is_valid())
+ return white_texture;
+
+ DVector<uint8_t> wt;
+ wt.resize(16*3);
+ {
+ DVector<uint8_t>::Write w =wt.write();
+ for(int i=0;i<16*3;i++)
+ w[i]=255;
+ }
+ Image white(4,4,0,Image::FORMAT_RGB,wt);
+ white_texture=texture_create();
+ texture_allocate(white_texture,4,4,Image::FORMAT_RGB);
+ texture_set_data(white_texture,white);
+ return white_texture;
+
+}
+
void VisualServer::_bind_methods() {
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 1e540a6753..e5d1e75702 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -56,6 +56,8 @@ class VisualServer : public Object {
protected:
RID _make_test_cube();
RID test_texture;
+ RID white_texture;
+ RID material_2d[16];
static VisualServer* (*create_func)();
static void _bind_methods();
@@ -189,6 +191,7 @@ public:
MATERIAL_HINT_OPAQUE_PRE_PASS,
MATERIAL_HINT_NO_SHADOW,
MATERIAL_HINT_NO_DEPTH_DRAW,
+ MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA,
MATERIAL_HINT_MAX
};
@@ -199,7 +202,8 @@ public:
MATERIAL_BLEND_MODE_MIX, //default
MATERIAL_BLEND_MODE_ADD,
MATERIAL_BLEND_MODE_SUB,
- MATERIAL_BLEND_MODE_MUL
+ MATERIAL_BLEND_MODE_MUL,
+ MATERIAL_BLEND_MODE_PREMULT_ALPHA
};
@@ -240,6 +244,7 @@ public:
FIXED_MATERIAL_FLAG_USE_ALPHA,
FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
+ FIXED_MATERIAL_FLAG_DISCARD_ALPHA,
FIXED_MATERIAL_FLAG_MAX,
};
@@ -359,7 +364,22 @@ public:
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const=0;
-
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create()=0;
+ virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID())=0;
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0;
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0;
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0;
+ virtual void immediate_color(RID p_immediate,const Color& p_color)=0;
+ virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0;
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0;
+ virtual void immediate_end(RID p_immediate)=0;
+ virtual void immediate_clear(RID p_immediate)=0;
+ virtual void immediate_set_material(RID p_immediate,RID p_material)=0;
+ virtual RID immediate_get_material(RID p_immediate) const=0;
+
+
/* PARTICLES API */
virtual RID particles_create()=0;
@@ -555,6 +575,8 @@ public:
virtual void portal_set_connect_range(RID p_portal, float p_range) =0;
virtual float portal_get_connect_range(RID p_portal) const =0;
+
+
/* CAMERA API */
virtual RID camera_create()=0;
@@ -674,6 +696,7 @@ public:
ENV_BG_PARAM_CUBEMAP,
ENV_BG_PARAM_ENERGY,
ENV_BG_PARAM_SCALE,
+ ENV_BG_PARAM_GLOW,
ENV_BG_PARAM_MAX
};
@@ -697,8 +720,17 @@ public:
virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled)=0;
virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_mode) const=0;
+ enum EnvironmentFxBlurBlendMode {
+ ENV_FX_BLUR_BLEND_MODE_ADDITIVE,
+ ENV_FX_BLUR_BLEND_MODE_SCREEN,
+ ENV_FX_BLUR_BLEND_MODE_SOFTLIGHT,
+ };
+
enum EnvironmentFxParam {
ENV_FX_PARAM_GLOW_BLUR_PASSES,
+ ENV_FX_PARAM_GLOW_BLUR_SCALE,
+ ENV_FX_PARAM_GLOW_BLUR_STRENGTH,
+ ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE,
ENV_FX_PARAM_GLOW_BLOOM,
ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD,
ENV_FX_PARAM_DOF_BLUR_PASSES,
@@ -755,12 +787,13 @@ public:
INSTANCE_NONE,
INSTANCE_MESH,
INSTANCE_MULTIMESH,
+ INSTANCE_IMMEDIATE,
INSTANCE_PARTICLES,
INSTANCE_LIGHT,
INSTANCE_ROOM,
INSTANCE_PORTAL,
- INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_PARTICLES)
+ INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES)
};
@@ -930,6 +963,12 @@ public:
};
virtual int get_render_info(RenderInfo p_info)=0;
+
+
+ /* Materials for 2D on 3D */
+
+
+ RID material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha,bool p_opaque_prepass);
/* TESTING */
@@ -937,6 +976,7 @@ public:
virtual RID get_test_cube()=0;
virtual RID get_test_texture();
+ virtual RID get_white_texture();
virtual RID make_sphere_mesh(int p_lats,int p_lons,float p_radius);
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index 18c0010904..9c921df5c6 100644
--- a/tools/editor/editor_import_export.cpp
+++ b/tools/editor/editor_import_export.cpp
@@ -994,7 +994,7 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
return OK;
}
-Error EditorExportPlatformPC::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug, bool p_dumb) {
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
index 94fbaba842..0f9068f8b3 100644
--- a/tools/editor/editor_import_export.h
+++ b/tools/editor/editor_import_export.h
@@ -130,14 +130,14 @@ public:
virtual int get_device_count() const { return 0; }
virtual String get_device_name(int p_device) const { return ""; }
virtual String get_device_info(int p_device) const { return ""; }
- virtual Error run(int p_device) { return OK; }
+ virtual Error run(int p_device,bool p_dumb=false) { return OK; }
virtual bool can_export(String *r_error=NULL) const=0;
virtual bool requieres_password(bool p_debug) const { return false; }
virtual String get_binary_extension() const=0;
- virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="")=0;
+ virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false)=0;
EditorExportPlatform() {};
};
@@ -187,7 +187,7 @@ public:
virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_BC; }
virtual String get_binary_extension() const { return binary_extension; }
- virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+ virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual void set_release_binary32(const String& p_binary) { release_binary32=p_binary; }
virtual void set_debug_binary32(const String& p_binary) { debug_binary32=p_binary; }
virtual void set_release_binary64(const String& p_binary) { release_binary64=p_binary; }
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 922ad80aa3..ceb5b45a03 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -2204,8 +2204,9 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case RUN_DEPLOY_DUMB_CLIENTS: {
- bool ischecked = fileserver_menu->get_popup()->is_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
- fileserver_menu->get_popup()->set_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),!ischecked);
+ bool ischecked = fileserver_menu->get_popup()->is_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
+ fileserver_menu->get_popup()->set_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),!ischecked);
+ run_native->set_deploy_dumb(!ischecked);
} break;
case SETTINGS_UPDATE_ALWAYS: {
@@ -3612,7 +3613,7 @@ EditorNode::EditorNode() {
p->set_item_tooltip(p->get_item_index(RUN_FILE_SERVER),"Enable/Disable the File Server.");
p->add_separator();
p->add_check_item("Deploy Dumb Clients",RUN_DEPLOY_DUMB_CLIENTS);
- p->set_item_checked( p->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),true );
+ //p->set_item_checked( p->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),true );
p->set_item_tooltip(p->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),"Deploy dumb clients when the File Server is active.");
p->connect("item_pressed",this,"_menu_option");
diff --git a/tools/editor/editor_run_native.cpp b/tools/editor/editor_run_native.cpp
index a0e04814a5..be1a124fc2 100644
--- a/tools/editor/editor_run_native.cpp
+++ b/tools/editor/editor_run_native.cpp
@@ -101,7 +101,7 @@ void EditorRunNative::_run_native(int p_idx,const String& p_platform) {
Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(p_platform);
ERR_FAIL_COND(eep.is_null());
- eep->run(p_idx);
+ eep->run(p_idx,deploy_dumb);
}
void EditorRunNative::_bind_methods() {
@@ -109,8 +109,20 @@ void EditorRunNative::_bind_methods() {
ObjectTypeDB::bind_method("_run_native",&EditorRunNative::_run_native);
}
+void EditorRunNative::set_deploy_dumb(bool p_enabled) {
+
+ deploy_dumb=p_enabled;
+}
+
+bool EditorRunNative::is_deploy_dumb_enabled() const{
+
+ return deploy_dumb;
+}
+
+
EditorRunNative::EditorRunNative()
{
set_process(true);
first=true;
+ deploy_dumb=false;
}
diff --git a/tools/editor/editor_run_native.h b/tools/editor/editor_run_native.h
index ca3d41126f..f4bda2d07d 100644
--- a/tools/editor/editor_run_native.h
+++ b/tools/editor/editor_run_native.h
@@ -38,6 +38,7 @@ class EditorRunNative : public HBoxContainer {
Map<StringName,MenuButton*> menus;
bool first;
+ bool deploy_dumb;
void _run_native(int p_idx,const String& p_platform);
@@ -46,6 +47,9 @@ protected:
static void _bind_methods();
void _notification(int p_what);
public:
+
+ void set_deploy_dumb(bool p_enabled);
+ bool is_deploy_dumb_enabled() const;
EditorRunNative();
};
diff --git a/tools/editor/fileserver/editor_file_server.cpp b/tools/editor/fileserver/editor_file_server.cpp
index f72498f37f..f21d9b4ec1 100644
--- a/tools/editor/fileserver/editor_file_server.cpp
+++ b/tools/editor/fileserver/editor_file_server.cpp
@@ -317,12 +317,33 @@ EditorFileServer::EditorFileServer() {
cmd=CMD_NONE;
thread=Thread::create(_thread_start,this);
+ List<IP_Address> local_ip;
+ IP::get_singleton()->get_local_addresses(&local_ip);
EDITOR_DEF("file_server/port",6010);
+ String lip;
+ String hint;
+ for(List<IP_Address>::Element *E=local_ip.front();E;E=E->next()) {
+
+ String ip = E->get();
+ if (ip=="127.0.0.1")
+ continue;
+
+ if (lip!="")
+ lip=ip;
+ if (hint!="")
+ hint+=",";
+ hint+=ip;
+
+ }
+
+ EDITOR_DEF("file_server/host",lip);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"file_server/host",PROPERTY_HINT_ENUM,hint));
EDITOR_DEF("file_server/password","");
}
EditorFileServer::~EditorFileServer() {
+
quit=true;
Thread::wait_to_finish(thread);
memdelete(wait_mutex);
diff --git a/tools/editor/icons/SCsub b/tools/editor/icons/SCsub
index a7e550feac..aea053d22b 100644
--- a/tools/editor/icons/SCsub
+++ b/tools/editor/icons/SCsub
@@ -3,13 +3,15 @@ Import('env')
def make_editor_icons_action(target, source, env):
import os
+ import cStringIO
dst = target[0].srcnode().abspath
pixmaps = source
+
+ s = cStringIO.StringIO()
- f = open(dst,"wb")
- f.write("#include \"editor_icons.h\"\n\n")
- f.write("#include \"scene/resources/theme.h\"\n\n")
+ s.write("#include \"editor_icons.h\"\n\n")
+ s.write("#include \"scene/resources/theme.h\"\n\n")
for x in pixmaps:
@@ -17,37 +19,41 @@ def make_editor_icons_action(target, source, env):
var_str=os.path.basename(x)[:-4]+"_png";
#print(var_str)
- f.write("static const unsigned char "+ var_str +"[]={\n");
+ s.write("static const unsigned char "+ var_str +"[]={\n");
pngf=open(x,"rb");
b=pngf.read(1);
while(len(b)==1):
- f.write(hex(ord(b)))
+ s.write(hex(ord(b)))
b=pngf.read(1);
if (len(b)==1):
- f.write(",")
+ s.write(",")
- f.write("\n};\n\n\n");
+ s.write("\n};\n\n\n");
pngf.close();
- f.write("static Ref<ImageTexture> make_icon(const uint8_t* p_png) {\n")
- f.write("\tRef<ImageTexture> texture( memnew( ImageTexture ) );\n")
- f.write("\ttexture->create_from_image( Image(p_png),ImageTexture::FLAG_FILTER );\n")
- f.write("\treturn texture;\n")
- f.write("}\n\n")
+ s.write("static Ref<ImageTexture> make_icon(const uint8_t* p_png) {\n")
+ s.write("\tRef<ImageTexture> texture( memnew( ImageTexture ) );\n")
+ s.write("\ttexture->create_from_image( Image(p_png),ImageTexture::FLAG_FILTER );\n")
+ s.write("\treturn texture;\n")
+ s.write("}\n\n")
- f.write("void editor_register_icons(Ref<Theme> p_theme) {\n\n")
+ s.write("void editor_register_icons(Ref<Theme> p_theme) {\n\n")
for x in pixmaps:
x=os.path.basename(str(x))
type=x[5:-4].title().replace("_","");
var_str=x[:-4]+"_png";
- f.write("\tp_theme->set_icon(\""+type+"\",\"EditorIcons\",make_icon("+var_str+"));\n");
+ s.write("\tp_theme->set_icon(\""+type+"\",\"EditorIcons\",make_icon("+var_str+"));\n");
- f.write("\n\n}\n\n");
+ s.write("\n\n}\n\n");
+
+ f = open(dst,"wb")
+ f.write(s.getvalue())
f.close()
+ s.close()
make_editor_icons_builder = Builder(action=make_editor_icons_action,
suffix = '.cpp',
diff --git a/tools/editor/icons/icon_animated_sprite_3d.png b/tools/editor/icons/icon_animated_sprite_3d.png
new file mode 100644
index 0000000000..19aa7ea207
--- /dev/null
+++ b/tools/editor/icons/icon_animated_sprite_3d.png
Binary files differ
diff --git a/tools/editor/icons/icon_sprite_3d.png b/tools/editor/icons/icon_sprite_3d.png
new file mode 100644
index 0000000000..260f7d4920
--- /dev/null
+++ b/tools/editor/icons/icon_sprite_3d.png
Binary files differ
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
index 916bd59360..4da712c7b3 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
@@ -44,6 +44,7 @@ static const char *flag_names[]={
"No MipMaps",
"Repeat",
"Filter (Magnifying)",
+ "Premultiply Alpha",
NULL
};
@@ -55,6 +56,7 @@ static const char *flag_short_names[]={
"NoMipMap",
"Repeat",
"Filter",
+ "PMAlpha",
NULL
};
@@ -919,6 +921,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
image.fix_alpha_edges();
}
+ if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_PREMULT_ALPHA) {
+
+ image.premultiply_alpha();
+ }
+
if (shrink>1) {
@@ -972,6 +979,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
image.fix_alpha_edges();
}
+ if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_PREMULT_ALPHA) {
+
+ image.premultiply_alpha();
+ }
+
int orig_w=image.get_width();
int orig_h=image.get_height();
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h
index b2950a889c..fcc1bd2d0c 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.h
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.h
@@ -91,7 +91,8 @@ public:
IMAGE_FLAG_COMPRESS_EXTRA=8, // used for pvrtc2
IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
- IMAGE_FLAG_FILTER=64 //almost always enabled
+ IMAGE_FLAG_FILTER=64, //almost always enabled
+ IMAGE_FLAG_PREMULT_ALPHA=128//almost always enabled
};
virtual String get_name() const;
diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp
index b1e42e3369..77f9d1ed78 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.cpp
+++ b/tools/editor/plugins/baked_light_editor_plugin.cpp
@@ -134,6 +134,8 @@ public:
void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light);
+ void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light);
+
void _throw_ray(const Vector3& p_from, const Vector3& p_to,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces);
@@ -165,7 +167,7 @@ public:
}
BakedLightBaker() {
- octree_depth=8;
+ octree_depth=6;
octree=NULL;
bvh=NULL;
leaf_list=NULL;
@@ -408,7 +410,7 @@ void BakedLightBaker::_make_bvh() {
void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) {
if (p_octant->leaf) {
-
+#if 0
if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) {
//face is completely enclosed, add area
p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area();
@@ -433,12 +435,18 @@ void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangl
p.d=-p_aabb.pos[i];
poly=Geometry::clip_polygon(poly,p);
}
+
+
//calculate area
+ float clipped_area=0;
for(int i=2;i<poly.size();i++) {
- p_octant->surface_area+=Face3(poly[0],poly[i-1],poly[i]).get_area();
+ clipped_area+=Face3(poly[0],poly[i-1],poly[i]).get_area();
}
- }
+ print_line(itos(poly.size())+" Base: "+rtos(Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area())+" clipped: "+rtos(clipped_area));
+ p_octant->surface_area+=clipped_area;
+ }
+#endif
} else {
@@ -500,7 +508,7 @@ void BakedLightBaker::_make_octree() {
octree_aabb=base;
cell_size=base.size.x;
- for(int i=0;i<=octree_depth;i++)
+ for(int i=0;i<octree_depth;i++)
cell_size/=2.0;
octree = memnew( Octant );
@@ -526,7 +534,7 @@ void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_a
float d = p_plot_pos.distance_to(center);
if (d>r)
return; //oh crap! outside radius
- float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
+ float intensity = 1.0;// - (d/r)*(d/r); //not gauss but..
p_octant->light_accum[0]+=p_light.r*intensity;
p_octant->light_accum[1]+=p_light.g*intensity;
p_octant->light_accum[2]+=p_light.b*intensity;
@@ -558,6 +566,42 @@ void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_a
}
}
+void BakedLightBaker::_plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light) {
+
+
+ if (p_octant->leaf) {
+
+ p_octant->light_accum[0]+=p_light.r;
+ p_octant->light_accum[1]+=p_light.g;
+ p_octant->light_accum[2]+=p_light.b;
+
+ } else {
+
+ for(int i=0;i<8;i++) {
+
+ if (!p_octant->children[i])
+ continue;
+
+ AABB aabb=p_aabb;
+ aabb.size*=0.5;
+ if (i&1)
+ aabb.pos.x+=aabb.size.x;
+ if (i&2)
+ aabb.pos.y+=aabb.size.y;
+ if (i&4)
+ aabb.pos.z+=aabb.size.z;
+
+
+ if (!aabb.has_point(p_plot_pos))
+ continue;
+
+ _plot_light_point(p_plot_pos,p_octant->children[i],aabb,p_light);
+
+ }
+
+ }
+}
+
void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces) {
@@ -692,6 +736,7 @@ void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,co
aabb.size=Vector3(2,2,2)*cell_size*plot_size;
_plot_light(r_point,aabb,octree,octree_aabb,p_light);
+// _plot_light_point(r_point,octree,octree_aabb,p_light);
}
@@ -772,9 +817,21 @@ void BakedLightBaker::bake(Node* p_node) {
+void BakedLightEditor::_end_baking() {
+
+ if (!bake_thread)
+ return;
+
+ bake_thread_exit=true;
+ Thread::wait_to_finish(bake_thread);
+ bake_thread=NULL;
+ bake_thread_exit=false;
+}
+
void BakedLightEditor::_node_removed(Node *p_node) {
if(p_node==node) {
+ _end_baking();
node=NULL;
p_node->remove_child(preview);
preview->set_mesh(Ref<Mesh>());
@@ -784,6 +841,79 @@ void BakedLightEditor::_node_removed(Node *p_node) {
}
+void BakedLightEditor::_bake_thread_func(void *arg) {
+
+ BakedLightEditor *ble = (BakedLightEditor*)arg;
+
+ while(!ble->bake_thread_exit) {
+
+ ble->baker->throw_rays(1000);
+ }
+
+}
+
+
+
+void BakedLightEditor::_notification(int p_option) {
+
+
+ if (p_option==NOTIFICATION_PROCESS) {
+
+ if (bake_thread) {
+
+ update_timeout-=get_process_delta_time();
+ if (update_timeout<0) {
+
+
+
+ float norm = baker->get_normalization();
+ float max_lum=0;
+ {
+ DVector<Color>::Write cw=colors.write();
+ BakedLightBaker::Octant *oct = baker->leaf_list;
+ int vert_idx=0;
+
+ while(oct) {
+
+ Color color;
+
+
+ color.r=oct->light_accum[0]/norm;
+ color.g=oct->light_accum[1]/norm;
+ color.b=oct->light_accum[2]/norm;
+ float lum = color.get_v();
+ //if (lum<0.05)
+ // color.a=0;
+ if (lum>max_lum)
+ max_lum=lum;
+
+ for (int i=0;i<36;i++) {
+
+
+ cw[vert_idx++]=color;
+ }
+
+ oct=oct->next_leaf;
+
+ }
+ }
+
+
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX]=vertices;
+ a[Mesh::ARRAY_COLOR]=colors;
+ while(mesh->get_surface_count())
+ mesh->surface_remove(0);
+ mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
+ mesh->surface_set_material(0,material);
+
+ update_timeout=1;
+ }
+ }
+ }
+}
+
void BakedLightEditor::_menu_option(int p_option) {
@@ -797,13 +927,9 @@ void BakedLightEditor::_menu_option(int p_option) {
preview->set_mesh(Ref<Mesh>());
baker->base_inv=node->get_global_transform().affine_inverse();
baker->bake(node);
- baker->throw_rays(100000);
- float norm = baker->get_normalization();
- float max_lum=0;
print_line("CELLS: "+itos(baker->cell_count));
- DVector<Color> colors;
- DVector<Vector3> vertices;
+ print_line("cell size: "+rtos(baker->cell_size));
colors.resize(baker->cell_count*36);
vertices.resize(baker->cell_count*36);
@@ -817,12 +943,6 @@ void BakedLightEditor::_menu_option(int p_option) {
while(oct) {
Color color;
- color.r=oct->light_accum[0]/norm;
- color.g=oct->light_accum[1]/norm;
- color.b=oct->light_accum[2]/norm;
- float lum = color.get_v();
- if (lum>max_lum)
- max_lum=lum;
for (int i=0;i<6;i++) {
@@ -845,7 +965,7 @@ void BakedLightEditor::_menu_option(int p_option) {
}
for(int j=0;j<4;j++) {
- face_points[j]*=baker->cell_size;
+ face_points[j]*=baker->cell_size*0.5;
face_points[j]+=Vector3(oct->offset[0],oct->offset[1],oct->offset[2]);
}
@@ -873,25 +993,20 @@ void BakedLightEditor::_menu_option(int p_option) {
}
- print_line("max lum: "+rtos(max_lum));
Array a;
a.resize(Mesh::ARRAY_MAX);
a[Mesh::ARRAY_VERTEX]=vertices;
a[Mesh::ARRAY_COLOR]=colors;
+ while(mesh->get_surface_count())
+ mesh->surface_remove(0);
+ mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
+ mesh->surface_set_material(0,material);
- Ref<FixedMaterial> matcol = memnew( FixedMaterial );
- matcol->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true);
- matcol->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
- matcol->set_flag(FixedMaterial::FLAG_UNSHADED,true);
- matcol->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true);
- matcol->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
- Ref<Mesh> m = memnew( Mesh );
- m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
- m->surface_set_material(0,matcol);
- preview->set_mesh(m);
-
-
-
+ bake_thread_exit=false;
+ update_timeout=0;
+ set_process(true);
+ bake_thread=Thread::create(_bake_thread_func,this);
+ preview->set_mesh(mesh);
} break;
@@ -914,6 +1029,7 @@ void BakedLightEditor::edit(BakedLight *p_baked_light) {
}
node=p_baked_light;
+ _end_baking();
if (node)
node->add_child(preview);
@@ -943,6 +1059,19 @@ BakedLightEditor::BakedLightEditor() {
node=NULL;
baker = memnew( BakedLightBaker );
preview = memnew( MeshInstance );
+ bake_thread=NULL;
+ update_timeout=0;
+
+ material = Ref<FixedMaterial> ( memnew( FixedMaterial ) );
+ material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true);
+ material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
+ material->set_flag(FixedMaterial::FLAG_UNSHADED,true);
+ material->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true);
+ material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
+
+ mesh = Ref<Mesh>( memnew( Mesh ));
+
+
}
BakedLightEditor::~BakedLightEditor() {
diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h
index 698d3f825f..9424503a16 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.h
+++ b/tools/editor/plugins/baked_light_editor_plugin.h
@@ -19,6 +19,15 @@ class BakedLightEditor : public Control {
OBJ_TYPE(BakedLightEditor, Control );
+ float update_timeout;
+ DVector<Color> colors;
+ DVector<Vector3> vertices;
+ Ref<Mesh> mesh;
+ Ref<FixedMaterial> material;
+
+ Thread *bake_thread;
+ bool bake_thread_exit;
+
MeshInstance *preview;
BakedLightBaker *baker;
AcceptDialog *err_dialog;
@@ -32,12 +41,15 @@ class BakedLightEditor : public Control {
MENU_OPTION_CLEAR
};
+ static void _bake_thread_func(void *arg);
+ void _end_baking();
void _menu_option(int);
friend class BakedLightEditorPlugin;
protected:
void _node_removed(Node *p_node);
static void _bind_methods();
+ void _notification(int p_what);
public:
void edit(BakedLight *p_baked_light);
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index 5f87b791f7..6540ae9288 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -608,7 +608,14 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
if (b.button_index==BUTTON_WHEEL_DOWN) {
+ float prev_zoom=zoom;
zoom=zoom*0.95;
+ {
+ Point2 ofs(b.x,b.y);
+ ofs = ofs/prev_zoom - ofs/zoom;
+ h_scroll->set_val( h_scroll->get_val() + ofs.x );
+ v_scroll->set_val( v_scroll->get_val() + ofs.y );
+ }
_update_scroll(0);
viewport->update();
return;
@@ -616,7 +623,15 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
if (b.button_index==BUTTON_WHEEL_UP) {
+ float prev_zoom=zoom;
zoom=zoom*(1.0/0.95);
+ {
+ Point2 ofs(b.x,b.y);
+ ofs = ofs/prev_zoom - ofs/zoom;
+ h_scroll->set_val( h_scroll->get_val() + ofs.x );
+ v_scroll->set_val( v_scroll->get_val() + ofs.y );
+ }
+
_update_scroll(0);
viewport->update();
return;
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 83cf753692..31ccc79d2a 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -688,6 +688,26 @@ void ScriptEditor::_menu_option(int p_option) {
current->get_text_edit()->query_code_comple();
} break;
+ case EDIT_AUTO_INDENT: {
+
+ TextEdit *te = current->get_text_edit();
+ String text = te->get_text();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+ int begin,end;
+ if (te->is_selection_active()) {
+ begin=te->get_selection_from_line();
+ end=te->get_selection_to_line();
+ } else {
+ begin=0;
+ end=te->get_line_count()-1;
+ }
+ scr->get_language()->auto_indent_code(text,begin,end);
+ te->set_text(text);
+
+
+ } break;
case SEARCH_FIND: {
find_replace_dialog->set_text_edit(current->get_text_edit());
@@ -1321,6 +1341,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
edit_menu->get_popup()->add_item("Select All",EDIT_SELECT_ALL,KEY_MASK_CMD|KEY_A);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CMD|KEY_SPACE);
+ edit_menu->get_popup()->add_item("Auto Indent",EDIT_AUTO_INDENT,KEY_MASK_CMD|KEY_I);
edit_menu->get_popup()->connect("item_pressed", this,"_menu_option");
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index 97f1702f8f..69b8739d67 100644
--- a/tools/editor/plugins/script_editor_plugin.h
+++ b/tools/editor/plugins/script_editor_plugin.h
@@ -122,6 +122,7 @@ class ScriptEditor : public VBoxContainer {
EDIT_PASTE,
EDIT_SELECT_ALL,
EDIT_COMPLETE,
+ EDIT_AUTO_INDENT,
SEARCH_FIND,
SEARCH_FIND_NEXT,
SEARCH_REPLACE,
diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp
index f571aba434..aac3837da9 100644
--- a/tools/editor/project_export.cpp
+++ b/tools/editor/project_export.cpp
@@ -449,7 +449,7 @@ Error ProjectExportDialog::export_platform(const String& p_platform, const Strin
ERR_PRINT("Invalid platform for export");
return ERR_INVALID_PARAMETER;
}
- Error err = exporter->export_project(p_path,p_debug,p_password);
+ Error err = exporter->export_project(p_path,p_debug);
if (err!=OK) {
error->set_text("Error exporting project!");
error->popup_centered(Size2(300,70));;
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index c45e7441b8..bd8f1641e2 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -98,22 +98,21 @@ class NewProjectDialog : public ConfirmationDialog {
void _path_text_changed(const String& p_path) {
- _test_path();
- if (import_mode) {
+ if ( _test_path() ) {
String sp=p_path;
sp=sp.replace("\\","/");
int lidx=sp.find_last("/");
+
if (lidx!=-1) {
sp=sp.substr(lidx+1,sp.length());
}
- if (sp=="")
+ if (sp=="" && import_mode )
sp="Imported Project";
project_name->set_text(sp);
}
-
}
void _file_selected(const String& p_path) {
@@ -338,21 +337,23 @@ struct ProjectItem {
String path;
String conf;
uint64_t last_modified;
+ bool favorite;
ProjectItem() {}
- ProjectItem(const String &p_project, const String &p_path, const String &p_conf, uint64_t p_last_modified) {
- project = p_project; path = p_path; conf = p_conf; last_modified = p_last_modified;
+ ProjectItem(const String &p_project, const String &p_path, const String &p_conf, uint64_t p_last_modified, bool p_favorite=false) {
+ project = p_project; path = p_path; conf = p_conf; last_modified = p_last_modified; favorite=p_favorite;
}
_FORCE_INLINE_ bool operator <(const ProjectItem& l) const { return last_modified > l.last_modified; }
+ _FORCE_INLINE_ bool operator ==(const ProjectItem& l) const { return project==l.project; }
};
+
void ProjectManager::_panel_draw(Node *p_hb) {
HBoxContainer *hb = p_hb->cast_to<HBoxContainer>();
hb->draw_line(Point2(0,hb->get_size().y+1),Point2(hb->get_size().x-10,hb->get_size().y+1),get_color("guide_color","Tree"));
- if (hb->get_meta("name")==selected) {
-
+ if (selected_list.has(hb->get_meta("name"))) {
hb->draw_style_box(get_stylebox("selected","Tree"),Rect2(Point2(),hb->get_size()-Size2(10,0)));
}
}
@@ -361,20 +362,90 @@ void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) {
if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
- selected = p_hb->get_meta("name");
- selected_main = p_hb->get_meta("main_scene");
+ String clicked = p_hb->get_meta("name");
+ String clicked_main_scene = p_hb->get_meta("main_scene");
+
+ if (p_ev.key.mod.shift && selected_list.size()>0 && last_clicked!="" && clicked != last_clicked) {
+
+ int clicked_id = -1;
+ int last_clicked_id = -1;
+ for(int i=0;i<scroll_childs->get_child_count();i++) {
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+ if (hb->get_meta("name") == clicked) clicked_id = i;
+ if (hb->get_meta("name") == last_clicked) last_clicked_id = i;
+ }
+
+ if (last_clicked_id!=-1 && clicked_id!=-1) {
+ int min = clicked_id < last_clicked_id? clicked_id : last_clicked_id;
+ int max = clicked_id > last_clicked_id? clicked_id : last_clicked_id;
+ for(int i=0; i<scroll_childs->get_child_count(); ++i) {
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+ if (i!=clicked_id && (i<min || i>max) && !p_ev.key.mod.control) {
+ selected_list.erase(hb->get_meta("name"));
+ } else if (i>=min && i<=max) {
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ }
+ }
+ }
+
+ } else if (selected_list.has(clicked) && p_ev.key.mod.control) {
+
+ selected_list.erase(clicked);
+
+ } else {
+
+ last_clicked = clicked;
+ if (p_ev.key.mod.control || selected_list.size()==0) {
+ selected_list.insert(clicked, clicked_main_scene);
+ } else {
+ selected_list.clear();
+ selected_list.insert(clicked, clicked_main_scene);
+ }
+ }
+
+ String single_selected = "";
+ if (selected_list.size() == 1) {
+ single_selected = selected_list.front()->key();
+ }
+
+ single_selected_main = "";
for(int i=0;i<scroll_childs->get_child_count();i++) {
- scroll_childs->get_child(i)->cast_to<CanvasItem>()->update();
+ CanvasItem *item = scroll_childs->get_child(i)->cast_to<CanvasItem>();
+ item->update();
+
+ if (single_selected!="" && single_selected == item->get_meta("name"))
+ single_selected_main = item->get_meta("main_scene");
}
- erase_btn->set_disabled(false);
- open_btn->set_disabled(false);
- run_btn->set_disabled(selected_main=="");
+
+ erase_btn->set_disabled(selected_list.size()<1);
+ open_btn->set_disabled(selected_list.size()<1);
+ run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main==""));
if (p_ev.mouse_button.doubleclick)
_open_project(); //open if doubleclicked
+
+ }
+}
+
+void ProjectManager::_favorite_pressed(Node *p_hb) {
+
+ String clicked = p_hb->get_meta("name");
+ bool favorite = !p_hb->get_meta("favorite");
+ String proj=clicked.replace(":::",":/");
+ proj=proj.replace("::","/");
+
+ if (favorite) {
+ EditorSettings::get_singleton()->set("favorite_projects/"+clicked,proj);
+ } else {
+ EditorSettings::get_singleton()->erase("favorite_projects/"+clicked);
}
+ EditorSettings::get_singleton()->save();
+ _load_recent_projects();
}
+
void ProjectManager::_load_recent_projects() {
while(scroll_childs->get_child_count()>0) {
@@ -387,12 +458,14 @@ void ProjectManager::_load_recent_projects() {
Color font_color = get_color("font_color","Tree");
List<ProjectItem> projects;
+ List<ProjectItem> favorite_projects;
for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
String _name = E->get().name;
- if (!_name.begins_with("projects/"))
+ if (!_name.begins_with("projects/") && !_name.begins_with("favorite_projects/"))
continue;
+ bool favorite = (_name.begins_with("favorite_projects/"))?true:false;
String project = _name.get_slice("/",1);
String path = EditorSettings::get_singleton()->get(_name);
@@ -408,11 +481,27 @@ void ProjectManager::_load_recent_projects() {
last_modified = cache_modified;
}
- ProjectItem item(project, path, conf, last_modified);
- projects.push_back(item);
+ ProjectItem item(project, path, conf, last_modified, favorite);
+ if (favorite)
+ favorite_projects.push_back(item);
+ else
+ projects.push_back(item);
}
projects.sort();
+ favorite_projects.sort();
+
+ for(List<ProjectItem>::Element *E=projects.front();E;) {
+ List<ProjectItem>::Element *next = E->next();
+ if (favorite_projects.find(E->get()) != NULL)
+ projects.erase(E->get());
+ E=next;
+ }
+ for(List<ProjectItem>::Element *E=favorite_projects.back();E;E=E->prev()) {
+ projects.push_front(E->get());
+ }
+
+ Ref<Texture> favorite_icon = get_icon("Favorites","EditorIcons");
for(List<ProjectItem>::Element *E=projects.front();E;E=E->next()) {
@@ -420,6 +509,7 @@ void ProjectManager::_load_recent_projects() {
String project = item.project;
String path = item.path;
String conf = item.conf;
+ bool is_favorite = item.favorite;
Ref<ConfigFile> cf = memnew( ConfigFile );
Error err = cf->load(conf);
@@ -428,7 +518,6 @@ void ProjectManager::_load_recent_projects() {
Ref<Texture> icon;
String project_name="Unnamed Project";
-
if (cf->has_section_key("application","icon")) {
String appicon = cf->get_value("application","icon");
if (appicon!="") {
@@ -457,15 +546,27 @@ void ProjectManager::_load_recent_projects() {
main_scene = cf->get_value("application","main_scene");
}
-
HBoxContainer *hb = memnew( HBoxContainer );
hb->set_meta("name",project);
hb->set_meta("main_scene",main_scene);
+ hb->set_meta("favorite",is_favorite);
hb->connect("draw",this,"_panel_draw",varray(hb));
hb->connect("input_event",this,"_panel_input",varray(hb));
+
+ VBoxContainer *favorite_box = memnew( VBoxContainer );
+ TextureButton *favorite = memnew( TextureButton );
+ favorite->set_normal_texture(favorite_icon);
+ if (!is_favorite)
+ favorite->set_opacity(0.2);
+ favorite->set_v_size_flags(SIZE_EXPAND);
+ favorite->connect("pressed",this,"_favorite_pressed",varray(hb));
+ favorite_box->add_child(favorite);
+ hb->add_child(favorite_box);
+
TextureFrame *tf = memnew( TextureFrame );
tf->set_texture(icon);
hb->add_child(tf);
+
VBoxContainer *vb = memnew(VBoxContainer);
hb->add_child(vb);
EmptyControl *ec = memnew( EmptyControl );
@@ -483,68 +584,92 @@ void ProjectManager::_load_recent_projects() {
scroll_childs->add_child(hb);
}
- erase_btn->set_disabled(selected=="");
- open_btn->set_disabled(selected=="");
- if (selected=="")
- run_btn->set_disabled(true);
+ erase_btn->set_disabled(selected_list.size()<1);
+ open_btn->set_disabled(selected_list.size()<1);
+ run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main==""));
}
-void ProjectManager::_open_project() {
-
+void ProjectManager::_open_project_confirm() {
- if (selected=="") {
- return;
- }
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+ const String &selected = E->key();
+ String path = EditorSettings::get_singleton()->get("projects/"+selected);
+ print_line("OPENING: "+path+" ("+selected+")");
- String path = EditorSettings::get_singleton()->get("projects/"+selected);
- print_line("OPENING: "+path+" ("+selected+")");
+ List<String> args;
- List<String> args;
+ args.push_back("-path");
+ args.push_back(path);
+ args.push_back("-editor");
- args.push_back("-path");
- args.push_back(path);
+ const String &selected_main = E->get();
+ if (selected_main!="") {
+ args.push_back(selected_main);
+ }
- args.push_back("-editor");
+ String exec = OS::get_singleton()->get_executable_path();
- if (selected_main!="") {
- args.push_back(selected_main);
+ OS::ProcessID pid=0;
+ Error err = OS::get_singleton()->execute(exec,args,false,&pid);
+ ERR_FAIL_COND(err);
}
- String exec = OS::get_singleton()->get_executable_path();
+ get_scene()->quit();
+}
- OS::ProcessID pid=0;
- Error err = OS::get_singleton()->execute(exec,args,false,&pid);
- ERR_FAIL_COND(err);
+void ProjectManager::_open_project() {
- get_scene()->quit();
+ if (selected_list.size()<1) {
+ return;
+ }
+ if (selected_list.size()>1) {
+ multi_open_ask->set_text("Are you sure to open more than one projects?");
+ multi_open_ask->popup_centered(Size2(300,100));
+ } else {
+ _open_project_confirm();
+ }
}
-void ProjectManager::_run_project() {
+void ProjectManager::_run_project_confirm() {
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
- if (selected=="") {
- return;
- }
+ const String &selected_main = E->get();
+ if (selected_main == "") continue;
- String path = EditorSettings::get_singleton()->get("projects/"+selected);
- print_line("OPENING: "+path+" ("+selected+")");
+ const String &selected = E->key();
+ String path = EditorSettings::get_singleton()->get("projects/"+selected);
+ print_line("OPENING: "+path+" ("+selected+")");
- List<String> args;
+ List<String> args;
+ args.push_back("-path");
+ args.push_back(path);
- args.push_back("-path");
- args.push_back(path);
+ String exec = OS::get_singleton()->get_executable_path();
- String exec = OS::get_singleton()->get_executable_path();
+ OS::ProcessID pid=0;
+ Error err = OS::get_singleton()->execute(exec,args,false,&pid);
+ ERR_FAIL_COND(err);
+ }
+ // get_scene()->quit(); do not quit
+}
+
+void ProjectManager::_run_project() {
- OS::ProcessID pid=0;
- Error err = OS::get_singleton()->execute(exec,args,false,&pid);
- ERR_FAIL_COND(err);
-// get_scene()->quit(); do not quit
+ if (selected_list.size()<1) {
+ return;
+ }
+ if (selected_list.size()>1) {
+ multi_run_ask->set_text("Are you sure to run more than one projects?");
+ multi_run_ask->popup_centered(Size2(300,100));
+ } else {
+ _run_project_confirm();
+ }
}
void ProjectManager::_scan_dir(DirAccess *da,float pos, float total,List<String> *r_projects) {
@@ -619,21 +744,24 @@ void ProjectManager::_import_project() {
void ProjectManager::_erase_project_confirm() {
- if (selected=="") {
+ if (selected_list.size()==0) {
return;
}
-
- EditorSettings::get_singleton()->erase("projects/"+selected);
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+ EditorSettings::get_singleton()->erase("projects/"+E->key());
+ EditorSettings::get_singleton()->erase("favorite_projects/"+E->key());
+ }
EditorSettings::get_singleton()->save();
- selected="";
- selected_main="";
+ selected_list.clear();
+ last_clicked = "";
+ single_selected_main="";
_load_recent_projects();
}
void ProjectManager::_erase_project() {
- if (selected=="")
+ if (selected_list.size()==0)
return;
@@ -651,7 +779,9 @@ void ProjectManager::_exit_dialog() {
void ProjectManager::_bind_methods() {
ObjectTypeDB::bind_method("_open_project",&ProjectManager::_open_project);
+ ObjectTypeDB::bind_method("_open_project_confirm",&ProjectManager::_open_project_confirm);
ObjectTypeDB::bind_method("_run_project",&ProjectManager::_run_project);
+ ObjectTypeDB::bind_method("_run_project_confirm",&ProjectManager::_run_project_confirm);
ObjectTypeDB::bind_method("_scan_projects",&ProjectManager::_scan_projects);
ObjectTypeDB::bind_method("_scan_begin",&ProjectManager::_scan_begin);
ObjectTypeDB::bind_method("_import_project",&ProjectManager::_import_project);
@@ -662,6 +792,8 @@ void ProjectManager::_bind_methods() {
ObjectTypeDB::bind_method("_load_recent_projects",&ProjectManager::_load_recent_projects);
ObjectTypeDB::bind_method("_panel_draw",&ProjectManager::_panel_draw);
ObjectTypeDB::bind_method("_panel_input",&ProjectManager::_panel_input);
+ ObjectTypeDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed);
+
}
@@ -712,7 +844,7 @@ ProjectManager::ProjectManager() {
scroll->set_enable_h_scroll(false);
VBoxContainer *tree_vb = memnew( VBoxContainer);
- tree_hb->add_child(tree_vb);
+ tree_hb->add_child(tree_vb);
scroll_childs = memnew( VBoxContainer );
scroll_childs->set_h_size_flags(SIZE_EXPAND_FILL);
scroll->add_child(scroll_childs);
@@ -792,6 +924,18 @@ ProjectManager::ProjectManager() {
add_child(erase_ask);
+ multi_open_ask = memnew( ConfirmationDialog );
+ multi_open_ask->get_ok()->set_text("Edit");
+ multi_open_ask->get_ok()->connect("pressed", this, "_open_project_confirm");
+
+ add_child(multi_open_ask);
+
+ multi_run_ask = memnew( ConfirmationDialog );
+ multi_run_ask->get_ok()->set_text("Run");
+ multi_run_ask->get_ok()->connect("pressed", this, "_run_project_confirm");
+
+ add_child(multi_run_ask);
+
OS::get_singleton()->set_low_processor_usage_mode(true);
npdialog = memnew( NewProjectDialog );
@@ -806,6 +950,7 @@ ProjectManager::ProjectManager() {
//get_ok()->set_text("Open");
//get_ok()->set_text("Exit");
+ last_clicked = "";
}
diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h
index b3ad106cd8..eebfc56a66 100644
--- a/tools/editor/project_manager.h
+++ b/tools/editor/project_manager.h
@@ -46,11 +46,14 @@ class ProjectManager : public Control {
FileDialog *scan_dir;
ConfirmationDialog *erase_ask;
+ ConfirmationDialog *multi_open_ask;
+ ConfirmationDialog *multi_run_ask;
NewProjectDialog *npdialog;
ScrollContainer *scroll;
VBoxContainer *scroll_childs;
- String selected;
- String selected_main;
+ Map<String, String> selected_list; // name -> main_scene
+ String last_clicked;
+ String single_selected_main;
bool importing;
void _item_doubleclicked();
@@ -59,7 +62,9 @@ class ProjectManager : public Control {
void _scan_projects();
void _run_project();
+ void _run_project_confirm();
void _open_project();
+ void _open_project_confirm();
void _import_project();
void _new_project();
void _erase_project();
@@ -72,6 +77,7 @@ class ProjectManager : public Control {
void _panel_draw(Node *p_hb);
void _panel_input(const InputEvent& p_ev,Node *p_hb);
+ void _favorite_pressed(Node *p_hb);
protected:
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index 2087345888..2197902933 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -1566,6 +1566,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
add_child(checks20[i]);
checks20[i]->hide();
checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i));
+ checks20[i]->set_tooltip("Bit "+itos(i)+", val "+itos(1<<i)+".");
}
text_edit = memnew( TextEdit );
diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp
index 86331faa1d..bc0d48367a 100644
--- a/tools/editor/scenes_dock.cpp
+++ b/tools/editor/scenes_dock.cpp
@@ -37,12 +37,14 @@
bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) {
+ String search_term = tree_filter->get_search_term();
+ String file_filter = tree_filter->get_file_filter();
+
TreeItem *item = tree->create_item(p_parent);
item->set_text(0,p_dir->get_name()+"/");
item->set_icon(0,get_icon("Folder","EditorIcons"));
item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
-
bool has_items=false;
for(int i=0;i<p_dir->get_subdir_count();i++) {
@@ -53,6 +55,15 @@ bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_di
for (int i=0;i<p_dir->get_file_count();i++) {
+ String file_name = p_dir->get_file(i);
+ String extension = file_name.extension();
+
+ if (search_term!="" && file_name.findn(search_term)==-1)
+ continue;
+
+ if (file_filter!="*" && extension != file_filter )
+ continue;
+
bool isfave = favorites.has(p_dir->get_file_path(i));
if (button_favorite->is_pressed() && !isfave)
continue;
@@ -61,7 +72,7 @@ bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_di
fitem->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
fitem->set_editable(0,true);
fitem->set_checked(0,isfave);
- fitem->set_text(0,p_dir->get_file(i));
+ fitem->set_text(0,file_name);
Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),"EditorIcons")?p_dir->get_file_type(i):String("Object")),"EditorIcons");
fitem->set_icon(0, icon );
@@ -251,45 +262,40 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
editor=p_editor;
- tree = memnew( Tree );
- add_child(tree);
- tree->set_area_as_parent_rect();
- tree->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,25);
- tree->connect("item_edited",this,"_favorite_toggled");
-
+ HBoxContainer *toolbar_hbc = memnew( HBoxContainer );
+ add_child(toolbar_hbc);
button_reload = memnew( Button );
- button_reload->set_pos(Point2(3,2));
- button_reload->set_size(Point2(20,5));
button_reload->set_flat(true);
- add_child(button_reload);
- button_reload->connect("pressed",this,"_rescan");
+ button_reload->connect("pressed",this,"_rescan");
+ toolbar_hbc->add_child(button_reload);
button_favorite = memnew( Button );
- button_favorite->set_pos(Point2(28,2));
- button_favorite->set_size(Point2(20,5));
button_favorite->set_flat(true);
button_favorite->set_toggle_mode(true);
- add_child(button_favorite);
button_favorite->connect("toggled",this,"_favorites_toggled");
+ toolbar_hbc->add_child(button_favorite);
- button_instance = memnew( Button );
- button_instance->set_anchor(MARGIN_LEFT,ANCHOR_END);
- button_instance->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- button_instance->set_begin(Point2(3+20,2));
- button_instance->set_end(Point2(2+15,5));
- button_instance->set_flat(true);
- add_child(button_instance);
- button_instance->connect("pressed",this,"_instance_pressed");
+ toolbar_hbc->add_spacer();
button_open = memnew( Button );
- button_open->set_anchor(MARGIN_LEFT,ANCHOR_END);
- button_open->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- button_open->set_begin(Point2(3+45,2));
- button_open->set_end(Point2(2+34,5));
button_open->set_flat(true);
- add_child(button_open);
button_open->connect("pressed",this,"_open_pressed");
+ toolbar_hbc->add_child(button_open);
+
+ button_instance = memnew( Button );
+ button_instance->set_flat(true);
+ button_instance->connect("pressed",this,"_instance_pressed");
+ toolbar_hbc->add_child(button_instance);
+
+ tree = memnew( Tree );
+ tree_filter=memnew( ScenesDockFilter(tree) );
+ tree_filter->connect("filter_changed", this, "_update_tree");
+ add_child(tree_filter);
+ add_child(tree);
+
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ tree->connect("item_edited",this,"_favorite_toggled");
timer = memnew( Timer );
timer->set_one_shot(true);
@@ -300,10 +306,102 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
updating_tree=false;
+}
+ScenesDock::~ScenesDock() {
}
-ScenesDock::~ScenesDock() {
+void ScenesDockFilter::_setup_filters() {
+
+ file_filter->clear();
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("",&extensions);
+
+ file_filter->add_item("All Files (*)");
+ filters.push_back("*");
+
+ List<String> filter_texts;
+ for(int i=0;i<extensions.size();i++) {
+ filter_texts.push_back("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ filters.push_back(extensions[i]);
+ }
+ for(int i=0;i<filter_texts.size();i++) {
+
+ String flt=filter_texts[i].get_slice(";",0).strip_edges();
+ String desc=filter_texts[i].get_slice(";",1).strip_edges();
+ if (desc.length())
+ file_filter->add_item(desc+" ( "+flt+" )");
+ else
+ file_filter->add_item("( "+flt+" )");
+ }
+}
+
+void ScenesDockFilter::_command(int p_command) {
+ switch (p_command) {
+
+ case CMD_CLEAR_FILTER: {
+ if (search_box->get_text()!="") {
+ search_box->clear();
+ emit_signal("filter_changed");
+ }
+ }break;
+ }
+}
+
+void ScenesDockFilter::_search_text_changed(const String &p_newtext) {
+ emit_signal("filter_changed");
+}
+
+String ScenesDockFilter::get_search_term() {
+ return search_box->get_text().strip_edges();
+}
+
+String ScenesDockFilter::get_file_filter() {
+ return _current_filter;
+}
+
+void ScenesDockFilter::_file_filter_selected(int p_idx) {
+ String selected = filters[file_filter->get_selected()];
+ if (_current_filter != selected ) {
+ _current_filter = selected;
+ emit_signal("filter_changed");
+ }
}
+
+void ScenesDockFilter::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("_command"),&ScenesDockFilter::_command);
+ ObjectTypeDB::bind_method(_MD("_search_text_changed"), &ScenesDockFilter::_search_text_changed);
+ ObjectTypeDB::bind_method(_MD("_file_filter_selected"), &ScenesDockFilter::_file_filter_selected);
+
+ ADD_SIGNAL( MethodInfo("filter_changed") );
+}
+
+ScenesDockFilter::ScenesDockFilter(Tree *p_tree) {
+
+ _current_filter = "*";
+
+ tree = p_tree;
+
+ file_filter = memnew( OptionButton );
+ file_filter->set_custom_minimum_size(Size2(90,10));
+ file_filter->set_clip_text(true);
+ file_filter->connect("item_selected", this, "_file_filter_selected");
+ add_child(file_filter);
+
+ _setup_filters();
+
+ search_box = memnew( LineEdit );
+ search_box->connect("text_changed",this,"_search_text_changed");
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_child(search_box);
+
+ clear_search_button = memnew( Button );
+ clear_search_button->set_text("clear");
+ clear_search_button->connect("pressed",this,"_command",make_binds(CMD_CLEAR_FILTER));
+ add_child(clear_search_button);
+
+}
+
diff --git a/tools/editor/scenes_dock.h b/tools/editor/scenes_dock.h
index eab31a5a4d..cf48e2885f 100644
--- a/tools/editor/scenes_dock.h
+++ b/tools/editor/scenes_dock.h
@@ -34,6 +34,8 @@
#include "scene/gui/tree.h"
#include "scene/gui/label.h"
#include "scene/gui/button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/box_container.h"
#include "os/dir_access.h"
#include "os/thread.h"
@@ -42,8 +44,9 @@
class EditorNode;
-class ScenesDock : public Control {
- OBJ_TYPE( ScenesDock, Control );
+class ScenesDockFilter;
+class ScenesDock : public VBoxContainer {
+ OBJ_TYPE( ScenesDock, VBoxContainer );
EditorNode *editor;
Set<String> favorites;
@@ -54,6 +57,8 @@ class ScenesDock : public Control {
Button *button_open;
Timer *timer;
+ ScenesDockFilter *tree_filter;
+
bool updating_tree;
Tree * tree;
bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
@@ -77,4 +82,34 @@ public:
~ScenesDock();
};
+class ScenesDockFilter : public HBoxContainer {
+
+ OBJ_TYPE( ScenesDockFilter, HBoxContainer );
+
+ enum Command {
+ CMD_CLEAR_FILTER,
+ };
+
+ Tree *tree;
+ OptionButton *file_filter;
+ LineEdit *search_box;
+ Button *clear_search_button;
+
+ String _current_filter;
+ Vector<String> filters;
+
+ void _command(int p_command);
+ void _search_text_changed(const String& p_newtext);
+ void _setup_filters();
+ void _file_filter_selected(int p_idx);
+
+protected:
+ static void _bind_methods();
+
+public:
+ String get_search_term();
+ String get_file_filter();
+ ScenesDockFilter(Tree *p_tree);
+};
+
#endif // SCENES_DOCK_H