summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct6
-rw-r--r--core/error_list.h1
-rw-r--r--core/error_macros.h18
-rw-r--r--core/global_constants.cpp1
-rw-r--r--core/globals.cpp3
-rw-r--r--core/io/compression.cpp4
-rw-r--r--core/io/image_loader.cpp11
-rw-r--r--core/io/ioapi.h1
-rw-r--r--core/io/resource_format_binary.cpp336
-rw-r--r--core/io/resource_format_binary.h14
-rw-r--r--core/io/resource_format_xml.cpp322
-rw-r--r--core/io/resource_format_xml.h25
-rw-r--r--core/io/resource_loader.cpp65
-rw-r--r--core/io/resource_loader.h22
-rw-r--r--core/io/resource_saver.h2
-rw-r--r--core/io/translation_loader_po.cpp9
-rw-r--r--core/io/translation_loader_po.h2
-rw-r--r--core/io/zip.h2
-rw-r--r--core/io/zip_io.h1
-rw-r--r--core/object_type_db.cpp19
-rw-r--r--core/object_type_db.h4
-rw-r--r--core/os/input.cpp43
-rw-r--r--core/os/input.h7
-rw-r--r--core/os/os.cpp4
-rw-r--r--core/os/os.h2
-rw-r--r--core/typedefs.h4
-rw-r--r--core/ustring.cpp31
-rw-r--r--core/ustring.h1
-rw-r--r--core/variant.cpp12
-rw-r--r--demos/2d/dynamic_collision_shapes/ball.gd21
-rw-r--r--demos/2d/dynamic_collision_shapes/ball.pngbin0 -> 321 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/ball.scnbin0 -> 1898 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/box.pngbin0 -> 253 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/circle.pngbin0 -> 889 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd23
-rw-r--r--demos/2d/dynamic_collision_shapes/dynamic_colobjs.scnbin0 -> 4348 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/engine.cfg4
-rw-r--r--demos/2d/dynamic_collision_shapes/poly.pngbin0 -> 1638 bytes
-rw-r--r--demos/2d/isometric/dungeon.scnbin2841 -> 8743 bytes
-rw-r--r--demos/2d/lights_shadows/light_shadows.scnbin4293 -> 7181 bytes
-rw-r--r--demos/2d/platformer/engine.cfg6
-rw-r--r--demos/2d/platformer/stage.xml56
-rw-r--r--drivers/chibi/event_stream_chibi.cpp13
-rw-r--r--drivers/chibi/event_stream_chibi.h2
-rw-r--r--drivers/convex_decomp/b2Glue.h3
-rw-r--r--drivers/convex_decomp/b2Polygon.cpp4
-rw-r--r--drivers/convex_decomp/b2Polygon.h2
-rw-r--r--drivers/dds/texture_loader_dds.cpp10
-rw-r--r--drivers/dds/texture_loader_dds.h2
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp6
-rw-r--r--drivers/gles2/rasterizer_gles2.h2
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp22
-rw-r--r--drivers/mpc/audio_stream_mpc.cpp133
-rw-r--r--drivers/mpc/audio_stream_mpc.h47
-rw-r--r--drivers/pvr/texture_loader_pvr.cpp9
-rw-r--r--drivers/pvr/texture_loader_pvr.h2
-rw-r--r--drivers/speex/audio_stream_speex.cpp179
-rw-r--r--drivers/speex/audio_stream_speex.h57
-rw-r--r--drivers/theora/video_stream_theora.h2
-rwxr-xr-xdrivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc2
-rw-r--r--drivers/theoraplayer/video_stream_theoraplayer.cpp4
-rw-r--r--drivers/theoraplayer/video_stream_theoraplayer.h2
-rw-r--r--drivers/unix/file_access_unix.cpp6
-rw-r--r--drivers/unix/file_access_unix.h9
-rw-r--r--drivers/unix/os_unix.cpp5
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.cpp210
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.h53
-rw-r--r--main/main.cpp97
-rw-r--r--modules/gdscript/gd_editor.cpp54
-rw-r--r--modules/gdscript/gd_parser.cpp92
-rw-r--r--modules/gdscript/gd_parser.h2
-rw-r--r--modules/gdscript/gd_script.cpp7
-rw-r--r--modules/gdscript/gd_script.h2
-rw-r--r--platform/android/detect.py3
-rw-r--r--platform/android/file_access_android.cpp11
-rw-r--r--platform/android/file_access_android.h10
-rw-r--r--platform/android/file_access_jandroid.cpp4
-rw-r--r--platform/android/java/src/com/android/godot/Godot.java2
-rw-r--r--platform/android/java/src/com/android/godot/GodotIO.java5
-rw-r--r--platform/android/java/src/com/android/godot/GodotLib.java2
-rw-r--r--platform/android/java_glue.cpp12
-rw-r--r--platform/android/java_glue.h2
-rw-r--r--platform/android/os_android.cpp10
-rw-r--r--platform/android/os_android.h3
-rw-r--r--platform/iphone/SCsub2
-rw-r--r--platform/iphone/app_delegate.mm45
-rw-r--r--platform/iphone/detect.py16
-rwxr-xr-xplatform/iphone/gl_view.h2
-rwxr-xr-xplatform/iphone/gl_view.mm2
-rw-r--r--platform/iphone/in_app_store.mm9
-rw-r--r--platform/javascript/SCsub5
-rw-r--r--platform/javascript/audio_server_javascript.cpp805
-rw-r--r--platform/javascript/audio_server_javascript.h198
-rw-r--r--platform/javascript/detect.py1
-rw-r--r--platform/javascript/export/export.cpp26
-rw-r--r--platform/javascript/javascript_main.cpp57
-rw-r--r--platform/javascript/os_javascript.cpp53
-rw-r--r--platform/javascript/os_javascript.h13
-rw-r--r--platform/osx/detect.py38
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm2
-rw-r--r--platform/x11/detect.py17
-rw-r--r--platform/x11/os_x11.cpp69
-rw-r--r--platform/x11/os_x11.h1
-rw-r--r--scene/2d/canvas_item.cpp9
-rw-r--r--scene/2d/canvas_item.h7
-rw-r--r--scene/2d/collision_polygon_2d.cpp84
-rw-r--r--scene/2d/collision_polygon_2d.h12
-rw-r--r--scene/2d/collision_shape_2d.cpp64
-rw-r--r--scene/2d/collision_shape_2d.h8
-rw-r--r--scene/2d/sprite.cpp4
-rw-r--r--scene/3d/area.cpp33
-rw-r--r--scene/3d/area.h10
-rw-r--r--scene/3d/body_shape.cpp75
-rw-r--r--scene/3d/body_shape.h14
-rw-r--r--scene/3d/collision_polygon.cpp106
-rw-r--r--scene/3d/collision_polygon.h12
-rw-r--r--scene/3d/physics_body.cpp55
-rw-r--r--scene/3d/physics_body.h14
-rw-r--r--scene/3d/spatial.cpp25
-rw-r--r--scene/3d/spatial.h5
-rw-r--r--scene/3d/spatial_stream_player.cpp288
-rw-r--r--scene/3d/spatial_stream_player.h56
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/animation/animation_player.cpp6
-rw-r--r--scene/animation/animation_player.h1
-rw-r--r--scene/audio/stream_player.cpp170
-rw-r--r--scene/audio/stream_player.h33
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/item_list.cpp37
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/patch_9_frame.cpp132
-rw-r--r--scene/gui/patch_9_frame.h40
-rw-r--r--scene/gui/spin_box.cpp54
-rw-r--r--scene/gui/spin_box.h12
-rw-r--r--scene/gui/tree.cpp113
-rw-r--r--scene/gui/tree.h11
-rw-r--r--scene/io/resource_format_image.cpp13
-rw-r--r--scene/io/resource_format_image.h2
-rw-r--r--scene/io/resource_format_wav.cpp10
-rw-r--r--scene/io/resource_format_wav.h2
-rw-r--r--scene/register_scene_types.cpp15
-rw-r--r--scene/resources/audio_stream.cpp70
-rw-r--r--scene/resources/audio_stream.h69
-rw-r--r--scene/resources/audio_stream_resampled.cpp4
-rw-r--r--scene/resources/audio_stream_resampled.h3
-rw-r--r--scene/resources/bit_mask.cpp7
-rw-r--r--scene/resources/bit_mask.h2
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/gibberish_stream.cpp3
-rw-r--r--scene/resources/gibberish_stream.h4
-rw-r--r--scene/resources/shader.cpp9
-rw-r--r--scene/resources/shader.h2
-rw-r--r--scene/resources/theme.cpp9
-rw-r--r--scene/resources/theme.h2
-rw-r--r--servers/audio/audio_rb_resampler.cpp356
-rw-r--r--servers/audio/audio_rb_resampler.h133
-rw-r--r--servers/audio/audio_server_sw.cpp6
-rw-r--r--servers/physics/area_sw.cpp17
-rw-r--r--servers/physics/area_sw.h11
-rw-r--r--servers/physics/body_sw.cpp53
-rw-r--r--servers/physics/body_sw.h15
-rw-r--r--servers/physics_2d/area_2d_sw.cpp8
-rw-r--r--servers/physics_2d/body_2d_sw.h6
-rw-r--r--servers/physics_server.cpp24
-rw-r--r--servers/physics_server.h13
-rw-r--r--servers/visual/rasterizer.h1
-rw-r--r--servers/visual/rasterizer_dummy.cpp3
-rw-r--r--servers/visual/rasterizer_dummy.h1
-rw-r--r--servers/visual/visual_server_raster.cpp20
-rw-r--r--tools/editor/animation_editor.cpp36
-rw-r--r--tools/editor/animation_editor.h6
-rw-r--r--tools/editor/array_property_edit.cpp231
-rw-r--r--tools/editor/array_property_edit.h36
-rw-r--r--tools/editor/dependency_editor.cpp512
-rw-r--r--tools/editor/dependency_editor.h94
-rw-r--r--tools/editor/editor_data.cpp29
-rw-r--r--tools/editor/editor_data.h9
-rw-r--r--tools/editor/editor_file_dialog.cpp5
-rw-r--r--tools/editor/editor_file_system.cpp44
-rw-r--r--tools/editor/editor_file_system.h9
-rw-r--r--tools/editor/editor_import_export.cpp46
-rw-r--r--tools/editor/editor_import_export.h3
-rw-r--r--tools/editor/editor_node.cpp411
-rw-r--r--tools/editor/editor_node.h34
-rw-r--r--tools/editor/editor_path.cpp6
-rw-r--r--tools/editor/editor_run.cpp66
-rw-r--r--tools/editor/editor_settings.cpp9
-rw-r--r--tools/editor/icons/icon_anchor.pngbin0 -> 428 bytes
-rw-r--r--tools/editor/icons/icon_control_align_bottom_center.pngbin0 -> 174 bytes
-rw-r--r--tools/editor/icons/icon_control_align_bottom_left.pngbin0 -> 172 bytes
-rw-r--r--tools/editor/icons/icon_control_align_bottom_right.pngbin0 -> 174 bytes
-rw-r--r--tools/editor/icons/icon_control_align_bottom_wide.pngbin0 -> 174 bytes
-rw-r--r--tools/editor/icons/icon_control_align_center.pngbin0 -> 181 bytes
-rw-r--r--tools/editor/icons/icon_control_align_center_left.pngbin0 -> 172 bytes
-rw-r--r--tools/editor/icons/icon_control_align_center_right.pngbin0 -> 171 bytes
-rw-r--r--tools/editor/icons/icon_control_align_left_center.pngbin0 -> 183 bytes
-rw-r--r--tools/editor/icons/icon_control_align_left_wide.pngbin0 -> 166 bytes
-rw-r--r--tools/editor/icons/icon_control_align_right_center.pngbin0 -> 181 bytes
-rw-r--r--tools/editor/icons/icon_control_align_right_wide.pngbin0 -> 167 bytes
-rw-r--r--tools/editor/icons/icon_control_align_top_center.pngbin0 -> 181 bytes
-rw-r--r--tools/editor/icons/icon_control_align_top_left.pngbin0 -> 176 bytes
-rw-r--r--tools/editor/icons/icon_control_align_top_right.pngbin0 -> 183 bytes
-rw-r--r--tools/editor/icons/icon_control_align_top_wide.pngbin0 -> 179 bytes
-rw-r--r--tools/editor/icons/icon_control_align_wide.pngbin0 -> 165 bytes
-rw-r--r--tools/editor/icons/icon_control_hcenter_wide.pngbin0 -> 182 bytes
-rw-r--r--tools/editor/icons/icon_control_vcenter_wide.pngbin0 -> 171 bytes
-rw-r--r--tools/editor/icons/icon_file_list.pngbin260 -> 288 bytes
-rw-r--r--tools/editor/icons/icon_filesystem.pngbin0 -> 241 bytes
-rw-r--r--tools/editor/icons/icon_history.pngbin0 -> 572 bytes
-rw-r--r--tools/editor/icons/icon_multi_node_edit.pngbin0 -> 576 bytes
-rw-r--r--tools/editor/icons/icon_non_favorite.pngbin0 -> 469 bytes
-rw-r--r--tools/editor/icons/icon_patch_9_frame.pngbin0 -> 431 bytes
-rw-r--r--tools/editor/inspector_dock.cpp22
-rw-r--r--tools/editor/inspector_dock.h35
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp245
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp85
-rw-r--r--tools/editor/multi_node_edit.cpp118
-rw-r--r--tools/editor/multi_node_edit.h32
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.cpp44
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.h7
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp120
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.h20
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/particles_2d_editor_plugin.cpp1
-rw-r--r--tools/editor/plugins/particles_editor_plugin.cpp1
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp17
-rw-r--r--tools/editor/project_export.cpp5
-rw-r--r--tools/editor/project_export.h3
-rw-r--r--tools/editor/project_settings.cpp49
-rw-r--r--tools/editor/property_editor.cpp173
-rw-r--r--tools/editor/property_editor.h6
-rw-r--r--tools/editor/quick_open.cpp42
-rw-r--r--tools/editor/quick_open.h10
-rw-r--r--tools/editor/scene_tree_dock.cpp35
-rw-r--r--tools/editor/scene_tree_dock.h2
-rw-r--r--tools/editor/scenes_dock.cpp1160
-rw-r--r--tools/editor/scenes_dock.h130
-rw-r--r--tools/editor/spatial_editor_gizmos.h4
-rw-r--r--tools/html_fs/godot.html1317
-rw-r--r--tools/html_fs/godotfs.js (renamed from tools/html_fs/filesystem.js)0
-rw-r--r--version.py7
244 files changed, 9828 insertions, 1396 deletions
diff --git a/SConstruct b/SConstruct
index 9cd1da7f45..9cce6edd81 100644
--- a/SConstruct
+++ b/SConstruct
@@ -220,14 +220,14 @@ if selected_platform in platform_list:
env.Append(LINKFLAGS=string.split(str(LINKFLAGS)))
- detect.configure(env)
-
-
flag_list = platform_flags[selected_platform]
for f in flag_list:
if not (f[0] in ARGUMENTS): # allow command line to override platform flags
env[f[0]] = f[1]
+ #must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11)
+ detect.configure(env)
+
#env['platform_libsuffix'] = env['LIBSUFFIX']
suffix="."+selected_platform
diff --git a/core/error_list.h b/core/error_list.h
index 124027172e..92c417154c 100644
--- a/core/error_list.h
+++ b/core/error_list.h
@@ -54,6 +54,7 @@ enum Error {
ERR_FILE_CANT_READ,
ERR_FILE_UNRECOGNIZED, // (15)
ERR_FILE_CORRUPT,
+ ERR_FILE_MISSING_DEPENDENCIES,
ERR_FILE_EOF,
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
ERR_CANT_CREATE,
diff --git a/core/error_macros.h b/core/error_macros.h
index 18b08d8e0e..76da88287b 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -104,7 +104,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_INDEX(m_index,m_size) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index "_STR(m_index)" out of size ("_STR(m_size)")."); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \
return; \
} else _err_error_exists=false; } while(0); \
@@ -115,7 +115,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_INDEX_V(m_index,m_size,m_retval) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index "_STR(m_index)" out of size ("_STR(m_size)")."); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \
return m_retval; \
} else _err_error_exists=false;} while (0);
@@ -125,14 +125,14 @@ extern bool _err_error_exists;
#define ERR_FAIL_NULL(m_param) \
{ if ( !m_param ) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' "_STR(m_param)" ' is null."); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \
return; \
}else _err_error_exists=false; } \
#define ERR_FAIL_NULL_V(m_param,m_retval) \
{ if ( !m_param ) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' "_STR(m_param)" ' is null."); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \
return m_retval; \
}else _err_error_exists=false; } \
@@ -142,7 +142,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_COND(m_cond) \
{ if ( m_cond ) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true."); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true."); \
return; \
}else _err_error_exists=false; } \
@@ -154,7 +154,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_COND_V(m_cond,m_retval) \
{ if ( m_cond ) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. returned: "_STR(m_retval)); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. returned: " _STR(m_retval)); \
return m_retval; \
}else _err_error_exists=false; } \
@@ -164,7 +164,7 @@ extern bool _err_error_exists;
#define ERR_CONTINUE(m_cond) \
{ if ( m_cond ) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. Continuing..:"); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Continuing..:"); \
continue;\
} else _err_error_exists=false;} \
@@ -174,7 +174,7 @@ extern bool _err_error_exists;
#define ERR_BREAK(m_cond) \
{ if ( m_cond ) { \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' "_STR(m_cond)" ' is true. Breaking..:"); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Breaking..:"); \
break;\
} else _err_error_exists=false;} \
@@ -193,7 +193,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_V(m_value) \
{ \
- _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: "__STR(m_value)); \
+ _err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: " __STR(m_value)); \
_err_error_exists=false; \
return m_value;\
} \
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index b8d113f67c..9fb45c672a 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -422,6 +422,7 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_READ ),
BIND_GLOBAL_CONSTANT( ERR_FILE_UNRECOGNIZED ),
BIND_GLOBAL_CONSTANT( ERR_FILE_CORRUPT ),
+ BIND_GLOBAL_CONSTANT( ERR_FILE_MISSING_DEPENDENCIES),
BIND_GLOBAL_CONSTANT( ERR_FILE_EOF ),
BIND_GLOBAL_CONSTANT( ERR_CANT_OPEN ), ///< Can't open a resource/socket/file
BIND_GLOBAL_CONSTANT( ERR_CANT_CREATE ),
diff --git a/core/globals.cpp b/core/globals.cpp
index 731c5b7dff..ffd4cf5d5e 100644
--- a/core/globals.cpp
+++ b/core/globals.cpp
@@ -54,7 +54,7 @@ String Globals::localize_path(const String& p_path) const {
if (resource_path=="")
return p_path; //not initialied yet
- if (p_path.begins_with("res://"))
+ if (p_path.find(":/") != -1)
return p_path.simplify_path();
@@ -1477,7 +1477,6 @@ Globals::Globals() {
custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow");
custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
- set("display/emulate_touchscreen",false);
using_datapack=false;
}
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 0bc006b41e..729b7bec52 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -26,12 +26,12 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#include "zlib.h"
+#include "os/copymem.h"
#include "compression.h"
#include "fastlz.h"
-#include "zlib.h"
#include "zip_io.h"
-#include "os/copymem.h"
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode) {
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index d3390ae199..2db6e00f0a 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -50,8 +50,10 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom
if (!f) {
Error err;
f=FileAccess::open(p_file,FileAccess::READ,&err);
- if (!f)
+ if (!f) {
+ print_line("ERROR OPENING FILE: "+p_file);
return err;
+ }
}
String extension = p_file.extension();
@@ -62,15 +64,20 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom
if (!loader[i]->recognize(extension))
continue;
Error err = loader[i]->load_image(p_image,f);
+
if (err!=ERR_FILE_UNRECOGNIZED) {
+
+
if (!p_custom)
memdelete(f);
+
return err;
}
}
-
+ print_line("NO LOADER?");
+
if (!p_custom)
memdelete(f);
diff --git a/core/io/ioapi.h b/core/io/ioapi.h
index a13d7ba621..24bf612617 100644
--- a/core/io/ioapi.h
+++ b/core/io/ioapi.h
@@ -40,7 +40,6 @@
#endif
#include <stdio.h>
-#include <stdlib.h>
#include "zlib.h"
#if defined(USE_FILE32API)
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index c6cf631de6..60bb8b658e 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -31,6 +31,7 @@
#include "globals.h"
#include "io/file_access_compressed.h"
#include "io/marshalls.h"
+#include "os/dir_access.h"
//#define print_bl(m_what) print_line(m_what)
#define print_bl(m_what)
@@ -99,7 +100,9 @@ enum {
OBJECT_EMPTY=0,
OBJECT_EXTERNAL_RESOURCE=1,
OBJECT_INTERNAL_RESOURCE=2,
- FORMAT_VERSION=0
+ OBJECT_EXTERNAL_RESOURCE_INDEX=3,
+ FORMAT_VERSION=1,
+ FORMAT_VERSION_CAN_RENAME_DEPS=1
};
@@ -375,7 +378,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
} break;
case OBJECT_INTERNAL_RESOURCE: {
uint32_t index=f->get_32();
- String path = res_path+"::"+itos(index);
+ String path = res_path+"::"+itos(index);
RES res = ResourceLoader::load(path);
if (res.is_null()) {
WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
@@ -384,6 +387,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
} break;
case OBJECT_EXTERNAL_RESOURCE: {
+ //old file format, still around for compatibility
String type = get_unicode_string();
String path = get_unicode_string();
@@ -394,6 +398,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
}
+ if (remaps.find(path)) {
+ path=remaps[path];
+ }
+
RES res=ResourceLoader::load(path,type);
if (res.is_null()) {
@@ -402,6 +410,34 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
r_v=res;
} break;
+ case OBJECT_EXTERNAL_RESOURCE_INDEX: {
+ //new file format, just refers to an index in the external list
+ uint32_t erindex = f->get_32();
+
+ if (erindex>=external_resources.size()) {
+ WARN_PRINT("Broken external resource! (index out of size");
+ r_v=Variant();
+ } else {
+
+ String type = external_resources[erindex].type;
+ String path = external_resources[erindex].path;
+
+ if (path.find("://")==-1 && path.is_rel_path()) {
+ // path is relative to file being loaded, so convert to a resource path
+ path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path));
+
+ }
+
+ RES res=ResourceLoader::load(path,type);
+
+ if (res.is_null()) {
+ WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
+ }
+ r_v=res;
+ }
+
+
+ } break;
default: {
ERR_FAIL_V(ERR_FILE_CORRUPT);
@@ -628,17 +664,20 @@ Error ResourceInteractiveLoaderBinary::poll(){
if (s<external_resources.size()) {
- RES res = ResourceLoader::load(external_resources[s].path,external_resources[s].type);
+ String path = external_resources[s].path;
+ if (remaps.has(path)) {
+ path=remaps[path];
+ }
+ RES res = ResourceLoader::load(path,external_resources[s].type);
if (res.is_null()) {
if (!ResourceLoader::get_abort_on_missing_resources()) {
- ResourceLoader::notify_load_error("Resource Not Found: "+external_resources[s].path);
+ ResourceLoader::notify_dependency_error(local_path,path,external_resources[s].type);
} else {
-
- error=ERR_FILE_CORRUPT;
- ERR_EXPLAIN("Can't load dependency: "+external_resources[s].path);
+ error=ERR_FILE_MISSING_DEPENDENCIES;
+ ERR_EXPLAIN("Can't load dependency: "+path);
ERR_FAIL_V(error);
}
@@ -787,6 +826,27 @@ int ResourceInteractiveLoaderBinary::get_stage_count() const {
return external_resources.size()+internal_resources.size();
}
+
+static void save_ustring(FileAccess* f,const String& p_string) {
+
+
+ CharString utf8 = p_string.utf8();
+ f->store_32(utf8.length()+1);
+ f->store_buffer((const uint8_t*)utf8.get_data(),utf8.length()+1);
+}
+
+
+static String get_ustring(FileAccess *f) {
+
+ int len = f->get_32();
+ Vector<char> str_buf;
+ str_buf.resize(len);
+ f->get_buffer((uint8_t*)&str_buf[0],len);
+ String s;
+ s.parse_utf8(&str_buf[0]);
+ return s;
+}
+
String ResourceInteractiveLoaderBinary::get_unicode_string() {
int len = f->get_32();
@@ -801,7 +861,7 @@ String ResourceInteractiveLoaderBinary::get_unicode_string() {
-void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<String> *p_dependencies) {
+void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<String> *p_dependencies,bool p_add_types) {
open(p_f);
if (error)
@@ -814,6 +874,10 @@ void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<Stri
dep=ResourceLoader::guess_full_filename(dep,external_resources[i].type);
}
+ if (p_add_types && external_resources[i].type!=String()) {
+ dep+="::"+external_resources[i].type;
+ }
+
p_dependencies->push_back(dep);
}
@@ -866,7 +930,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
print_bl("minor: "+itos(ver_minor));
print_bl("format: "+itos(ver_format));
- if (ver_format<FORMAT_VERSION || ver_major>VERSION_MAJOR) {
+ if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) {
f->close();
ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path);
@@ -903,6 +967,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
}
//see if the exporter has different set of external resources for more efficient loading
+ /*
String preload_depts = "deps/"+res_path.md5_text();
if (Globals::get_singleton()->has(preload_depts)) {
external_resources.clear();
@@ -913,7 +978,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
external_resources[i].path=depts.get_name(i);
}
print_line(res_path+" - EXTERNAL RESOURCES: "+itos(external_resources.size()));
- }
+ }*/
print_bl("ext resources: "+itos(ext_resources_size));
uint32_t int_resources_size=f->get_32();
@@ -973,7 +1038,7 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {
uint32_t ver_minor=f->get_32();
uint32_t ver_format=f->get_32();
- if (ver_format<FORMAT_VERSION || ver_major>VERSION_MAJOR) {
+ if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) {
f->close();
return "";
@@ -1000,8 +1065,10 @@ ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() {
}
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path, Error *r_error) {
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
Error err;
FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -1114,7 +1181,7 @@ Error ResourceFormatLoaderBinary::load_import_metadata(const String &p_path, Ref
}
-void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types) {
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
ERR_FAIL_COND(!f);
@@ -1123,7 +1190,217 @@ void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<Stri
ria->local_path=Globals::get_singleton()->localize_path(p_path);
ria->res_path=ria->local_path;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
- ria->get_dependencies(f,p_dependencies);
+ ria->get_dependencies(f,p_dependencies,p_add_types);
+}
+
+Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
+
+
+// Error error=OK;
+
+
+ FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+ FileAccess* fw=NULL;//=FileAccess::open(p_path+".depren");
+
+ String local_path=p_path.get_base_dir();
+
+ uint8_t header[4];
+ f->get_buffer(header,4);
+ if (header[0]=='R' && header[1]=='S' && header[2]=='C' && header[3]=='C') {
+ //compressed
+ FileAccessCompressed *fac = memnew( FileAccessCompressed );
+ fac->open_after_magic(f);
+ f=fac;
+
+ FileAccessCompressed *facw = memnew( FileAccessCompressed );
+ facw->configure("RSCC");
+ Error err = facw->_open(p_path+".depren",FileAccess::WRITE);
+ if (err) {
+ memdelete(fac);
+ memdelete(facw);
+ ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
+ }
+
+ fw=facw;
+
+
+ } else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') {
+ //not normal
+
+ //error=ERR_FILE_UNRECOGNIZED;
+ memdelete(f);
+ ERR_EXPLAIN("Unrecognized binary resource file: "+local_path);
+ ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+ } else {
+ fw = FileAccess::open(p_path+".depren",FileAccess::WRITE);
+ if (!fw) {
+ memdelete(f);
+ }
+ ERR_FAIL_COND_V(!fw,ERR_CANT_CREATE);
+ }
+
+ bool big_endian = f->get_32();
+#ifdef BIG_ENDIAN_ENABLED
+ endian_swap = !big_endian;
+#else
+ bool endian_swap = big_endian;
+#endif
+
+ bool use_real64 = f->get_32();
+
+ f->set_endian_swap(big_endian!=0); //read big endian if saved as big endian
+ fw->store_32(endian_swap);
+ fw->set_endian_swap(big_endian!=0);
+ fw->store_32(use_real64); //use real64
+
+ uint32_t ver_major=f->get_32();
+ uint32_t ver_minor=f->get_32();
+ uint32_t ver_format=f->get_32();
+
+ if (ver_format<FORMAT_VERSION_CAN_RENAME_DEPS) {
+
+ memdelete(f);
+ memdelete(fw);
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->remove(p_path+".depren");
+ memdelete(da);
+ //fuck it, use the old approach;
+
+ WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());
+
+ Error err;
+ f = FileAccess::open(p_path,FileAccess::READ,&err);
+ if (err!=OK) {
+ ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
+ }
+
+ Ref<ResourceInteractiveLoaderBinary> ria = memnew( ResourceInteractiveLoaderBinary );
+ ria->local_path=Globals::get_singleton()->localize_path(p_path);
+ ria->res_path=ria->local_path;
+ ria->remaps=p_map;
+ // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+ ria->open(f);
+
+ err = ria->poll();
+
+ while(err==OK) {
+ err=ria->poll();
+ }
+
+ ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
+ RES res = ria->get_resource();
+ ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);
+
+ return ResourceFormatSaverBinary::singleton->save(p_path,res);
+ }
+
+ if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) {
+
+ memdelete(f);
+ memdelete(fw);
+ ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path);
+ ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+
+ }
+
+ fw->store_32( VERSION_MAJOR ); //current version
+ fw->store_32( VERSION_MINOR );
+ fw->store_32( FORMAT_VERSION );
+
+ save_ustring(fw,get_ustring(f)); //type
+
+
+ size_t md_ofs = f->get_pos();
+ size_t importmd_ofs = f->get_64();
+ fw->store_64(0); //metadata offset
+
+ for(int i=0;i<14;i++) {
+ fw->store_32(0);
+ f->get_32();
+ }
+
+ //string table
+ uint32_t string_table_size=f->get_32();
+
+ fw->store_32(string_table_size);
+
+ for(uint32_t i=0;i<string_table_size;i++) {
+
+ String s = get_ustring(f);
+ save_ustring(fw,s);
+ }
+
+ //external resources
+ uint32_t ext_resources_size=f->get_32();
+ fw->store_32(ext_resources_size);
+ for(uint32_t i=0;i<ext_resources_size;i++) {
+
+ String type = get_ustring(f);
+ String path = get_ustring(f);
+
+ bool relative=false;
+ if (!path.begins_with("res://")) {
+ path=local_path.plus_file(path).simplify_path();
+ relative=true;
+ }
+
+
+ if (p_map.has(path)) {
+ String np=p_map[path];
+ path=np;
+ }
+
+ if (relative) {
+ //restore relative
+ path=local_path.path_to_file(path);
+ }
+
+ save_ustring(fw,type);
+ save_ustring(fw,path);
+ }
+
+ int64_t size_diff = (int64_t)fw->get_pos() - (int64_t)f->get_pos();
+
+ //internal resources
+ uint32_t int_resources_size=f->get_32();
+ fw->store_32(int_resources_size);
+
+ for(uint32_t i=0;i<int_resources_size;i++) {
+
+
+ String path=get_ustring(f);
+ uint64_t offset=f->get_64();
+ save_ustring(fw,path);
+ fw->store_64(offset+size_diff);
+ }
+
+ //rest of file
+ uint8_t b = f->get_8();
+ while(!f->eof_reached()) {
+ fw->store_8(b);
+ b = f->get_8();
+ }
+
+ bool all_ok = fw->get_error()==OK;
+
+ fw->seek(md_ofs);
+ fw->store_64(importmd_ofs+size_diff);
+
+
+ memdelete(f);
+ memdelete(fw);
+
+ if (!all_ok) {
+ return ERR_CANT_CREATE;
+ }
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ da->remove(p_path);
+ da->rename(p_path+".depren",p_path);
+ memdelete(da);
+ return OK;
}
@@ -1433,10 +1710,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,
}
if (res->get_path().length() && res->get_path().find("::")==-1) {
- f->store_32(OBJECT_EXTERNAL_RESOURCE);
- save_unicode_string(res->get_save_type());
- String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
- save_unicode_string(path);
+ f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX);
+ f->store_32(external_resources[res]);
} else {
if (!resource_set.has(res)) {
@@ -1594,11 +1869,12 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant& p_variant
RES res = p_variant.operator RefPtr();
- if (res.is_null())
+ if (res.is_null() || external_resources.has(res))
return;
if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) {
- external_resources.insert(res);
+ int idx = external_resources.size();
+ external_resources[res]=idx;
return;
}
@@ -1842,10 +2118,18 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
// save external resource table
f->store_32(external_resources.size()); //amount of external resources
- for(Set<RES>::Element *E=external_resources.front();E;E=E->next()) {
+ Vector<RES> save_order;
+ save_order.resize(external_resources.size());
+
+ for(Map<RES,int>::Element *E=external_resources.front();E;E=E->next()) {
+ save_order[E->get()]=E->key();
+ }
- save_unicode_string(E->get()->get_save_type());
- String path = E->get()->get_path();
+ for(int i=0;i<save_order.size();i++) {
+
+ save_unicode_string(save_order[i]->get_save_type());
+ String path = save_order[i]->get_path();
+ path=relative_paths?local_path.path_to_file(path):path;
save_unicode_string(path);
}
// save internal resource table
@@ -1995,3 +2279,9 @@ void ResourceFormatSaverBinary::get_recognized_extensions(const RES& p_resource,
}
+ResourceFormatSaverBinary* ResourceFormatSaverBinary::singleton=NULL;
+
+ResourceFormatSaverBinary::ResourceFormatSaverBinary() {
+
+ singleton=this;
+}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index da415d97a5..8bf20bc574 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -71,6 +71,7 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
String get_unicode_string();
void _advance_padding(uint32_t p_len);
+ Map<String,String> remaps;
Error error;
int stage;
@@ -88,9 +89,10 @@ public:
virtual int get_stage() const;
virtual int get_stage_count() const;
+ void set_remaps(const Map<String,String>& p_remaps) { remaps=p_remaps; }
void open(FileAccess *p_f);
String recognize(FileAccess *p_f);
- void get_dependencies(FileAccess *p_f,List<String> *p_dependencies);
+ void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
ResourceInteractiveLoaderBinary();
@@ -101,13 +103,14 @@ public:
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
public:
- virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
+ virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL);
virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
- virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
+ virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false);
virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const;
+ virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
@@ -134,7 +137,7 @@ class ResourceFormatSaverBinaryInstance {
Vector<StringName> strings;
- Set<RES> external_resources;
+ Map<RES,int> external_resources;
List<RES> saved_resources;
@@ -174,11 +177,12 @@ class ResourceFormatSaverBinary : public ResourceFormatSaver {
public:
+ static ResourceFormatSaverBinary* singleton;
virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
virtual bool recognize(const RES& p_resource) const;
virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
-
+ ResourceFormatSaverBinary();
};
diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp
index b744cbf967..9019b4e3c0 100644
--- a/core/io/resource_format_xml.cpp
+++ b/core/io/resource_format_xml.cpp
@@ -29,10 +29,10 @@
#include "resource_format_xml.h"
#include "globals.h"
#include "version.h"
+#include "os/dir_access.h"
-
-ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool *r_exit,bool p_printerr) {
+ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool *r_exit, bool p_printerr, List<String> *r_order) {
while(get_char()!='<' && !f->eof_reached()) {}
@@ -107,7 +107,11 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool
if (r_value.size()) {
r_value.push_back(0);
- tag.args[name].parse_utf8(r_value.get_data());
+ String str;
+ str.parse_utf8(r_value.get_data());
+ tag.args[name]=str;
+ if (r_order)
+ r_order->push_back(name);
}
break;
@@ -119,7 +123,11 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool
} else if (reading_value && r_value.size()) {
r_value.push_back(0);
- tag.args[name].parse_utf8(r_value.get_data());
+ String str;
+ str.parse_utf8(r_value.get_data());
+ tag.args[name]=str;
+ if (r_order)
+ r_order->push_back(name);
name="";
r_value.clear();
reading_value=false;
@@ -463,6 +471,10 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
}
+ if (remaps.has(path)) {
+ path=remaps[path];
+ }
+
//take advantage of the resource loader cache. The resource is cached on it, even if
RES res=ResourceLoader::load(path,hint);
@@ -473,10 +485,31 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
}
r_v=res.get_ref_ptr();
+ } else if (tag->args.has("external")) {
+
+ int index = tag->args["external"].to_int();
+ if (ext_resources.has(index)) {
+ String path=ext_resources[index].path;
+ String type=ext_resources[index].type;
+
+ //take advantage of the resource loader cache. The resource is cached on it, even if
+ RES res=ResourceLoader::load(path,type);
+
+ if (res.is_null()) {
+
+ WARN_PRINT(String("Couldn't load externalresource: "+path).ascii().get_data());
+ }
+
+ r_v=res.get_ref_ptr();
+ } else {
+ WARN_PRINT(String("Invalid external resource index: "+itos(index)).ascii().get_data());
+
+ }
}
+
Error err=goto_end_of_tag();
if (err) {
ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error closing <resource> tag.");
@@ -1364,32 +1397,6 @@ Error ResourceInteractiveLoaderXML::poll() {
if (error!=OK)
return error;
- if (ext_resources.size()) {
-
- error=ERR_FILE_CORRUPT;
- String path=ext_resources.front()->get();
-
- RES res = ResourceLoader::load(path);
-
- if (res.is_null()) {
-
- if (ResourceLoader::get_abort_on_missing_resources()) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": editor exported nonexistent resource at: "+path);
- ERR_FAIL_V(error);
- } else {
- ResourceLoader::notify_load_error("Resource Not Found: "+path);
- }
- } else {
-
- resource_cache.push_back(res);
- }
-
- error=OK;
- ext_resources.pop_front();
- resource_current++;
- return error;
- }
-
bool exit;
Tag *tag = parse_tag(&exit);
@@ -1413,12 +1420,13 @@ Error ResourceInteractiveLoaderXML::poll() {
ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> missing 'path' field.");
ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT);
- String type;
+ String type="Resource";
if (tag->args.has("type"))
type=tag->args["type"];
String path = tag->args["path"];
+
ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> can't use a local path, this is a bug?.");
ERR_FAIL_COND_V(path.begins_with("local://"),ERR_FILE_CORRUPT);
@@ -1427,6 +1435,9 @@ Error ResourceInteractiveLoaderXML::poll() {
path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
}
+ if (remaps.has(path)) {
+ path=remaps[path];
+ }
RES res = ResourceLoader::load(path,type);
@@ -1436,13 +1447,21 @@ Error ResourceInteractiveLoaderXML::poll() {
ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> referenced nonexistent resource at: "+path);
ERR_FAIL_V(error);
} else {
- ResourceLoader::notify_load_error("Resource Not Found: "+path);
+ ResourceLoader::notify_dependency_error(local_path,path,type);
}
} else {
resource_cache.push_back(res);
}
+ if (tag->args.has("index")) {
+ ExtResource er;
+ er.path=path;
+ er.type=type;
+ ext_resources[tag->args["index"].to_int()]=er;
+ }
+
+
Error err = close_tag("ext_resource");
if (err)
return error;
@@ -1566,7 +1585,7 @@ int ResourceInteractiveLoaderXML::get_stage() const {
}
int ResourceInteractiveLoaderXML::get_stage_count() const {
- return resources_total+ext_resources.size();
+ return resources_total;//+ext_resources;
}
ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() {
@@ -1574,7 +1593,7 @@ ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() {
memdelete(f);
}
-void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *p_dependencies) {
+void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *p_dependencies,bool p_add_types) {
open(f);
@@ -1617,6 +1636,10 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *
path = ResourceLoader::guess_full_filename(path,type);
}
+ if (p_add_types && tag->args.has("type")) {
+ path+="::"+tag->args["type"];
+ }
+
p_dependencies->push_back(path);
Error err = close_tag("ext_resource");
@@ -1628,6 +1651,167 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *
}
+Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) {
+
+ open(p_f);
+ ERR_FAIL_COND_V(error!=OK,error);
+
+ //FileAccess
+
+ bool old_format=false;
+
+ FileAccess *fw = NULL;
+
+ String base_path=local_path.get_base_dir();
+
+ while(true) {
+ bool exit;
+ List<String> order;
+
+ Tag *tag = parse_tag(&exit,true,&order);
+
+ bool done=false;
+
+ if (!tag) {
+ if (fw) {
+ memdelete(fw);
+ }
+ error=ERR_FILE_CORRUPT;
+ ERR_FAIL_COND_V(!exit,error);
+ error=ERR_FILE_EOF;
+
+ return error;
+ }
+
+ if (tag->name=="ext_resource") {
+
+ if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) {
+ old_format=true;
+ break;
+ }
+
+ if (!fw) {
+
+ fw=FileAccess::open(p_path+".depren",FileAccess::WRITE);
+ fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape
+ fw->store_line("<resource_file type=\""+resource_type+"\" subresource_count=\""+itos(resources_total)+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\">");
+
+ }
+
+ String path = tag->args["path"];
+ String index = tag->args["index"];
+ String type = tag->args["type"];
+
+
+ bool relative=false;
+ if (!path.begins_with("res://")) {
+ path=base_path.plus_file(path).simplify_path();
+ relative=true;
+ }
+
+
+ if (p_map.has(path)) {
+ String np=p_map[path];
+ path=np;
+ }
+
+ if (relative) {
+ //restore relative
+ path=base_path.path_to_file(path);
+ }
+
+ tag->args["path"]=path;
+ tag->args["index"]=index;
+ tag->args["type"]=type;
+
+ } else {
+
+ done=true;
+ }
+
+ String tagt="\t<";
+ if (exit)
+ tagt+="/";
+ tagt+=tag->name;
+
+ for(List<String>::Element *E=order.front();E;E=E->next()) {
+ tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\"";
+ }
+ tagt+=">";
+ fw->store_line(tagt);
+ if (done)
+ break;
+ close_tag("ext_resource");
+ fw->store_line("\t</ext_resource>");
+
+ }
+
+
+ if (old_format) {
+ if (fw)
+ memdelete(fw);
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->remove(p_path+".depren");
+ memdelete(da);
+ //fuck it, use the old approach;
+
+ WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());
+
+ Error err;
+ FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err);
+ if (err!=OK) {
+ ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
+ }
+
+ Ref<ResourceInteractiveLoaderXML> ria = memnew( ResourceInteractiveLoaderXML );
+ ria->local_path=Globals::get_singleton()->localize_path(p_path);
+ ria->res_path=ria->local_path;
+ ria->remaps=p_map;
+ // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+ ria->open(f2);
+
+ err = ria->poll();
+
+ while(err==OK) {
+ err=ria->poll();
+ }
+
+ ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
+ RES res = ria->get_resource();
+ ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);
+
+ return ResourceFormatSaverXML::singleton->save(p_path,res);
+ }
+
+ if (!fw) {
+
+ return OK; //nothing to rename, do nothing
+ }
+
+ uint8_t c=f->get_8();
+ while(!f->eof_reached()) {
+ fw->store_8(c);
+ c=f->get_8();
+ }
+
+ bool all_ok = fw->get_error()==OK;
+
+ memdelete(fw);
+
+ if (!all_ok) {
+ return ERR_CANT_CREATE;
+ }
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ da->remove(p_path);
+ da->rename(p_path+".depren",p_path);
+ memdelete(da);
+
+ return OK;
+
+}
+
void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
@@ -1686,6 +1870,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
}
+ /*
String preload_depts = "deps/"+local_path.md5_text();
if (Globals::get_singleton()->has(preload_depts)) {
ext_resources.clear();
@@ -1697,7 +1882,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
}
print_line(local_path+" - EXTERNAL RESOURCES: "+itos(ext_resources.size()));
}
-
+*/
}
@@ -1730,7 +1915,10 @@ String ResourceInteractiveLoaderXML::recognize(FileAccess *p_f) {
/////////////////////
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderXML::load_interactive(const String &p_path) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoaderXML::load_interactive(const String &p_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
Error err;
FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -1816,7 +2004,7 @@ String ResourceFormatLoaderXML::get_resource_type(const String &p_path) const{
}
-void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types) {
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
if (!f) {
@@ -1828,11 +2016,27 @@ void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String>
ria->local_path=Globals::get_singleton()->localize_path(p_path);
ria->res_path=ria->local_path;
// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
- ria->get_dependencies(f,p_dependencies);
+ ria->get_dependencies(f,p_dependencies,p_add_types);
+
+}
+
+Error ResourceFormatLoaderXML::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
+
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+ if (!f) {
+ ERR_FAIL_V(ERR_CANT_OPEN);
+ }
+
+ Ref<ResourceInteractiveLoaderXML> ria = memnew( ResourceInteractiveLoaderXML );
+ ria->local_path=Globals::get_singleton()->localize_path(p_path);
+ ria->res_path=ria->local_path;
+// ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+ return ria->rename_dependencies(f,p_path,p_map);
}
+
/****************************************************************************************/
/****************************************************************************************/
/****************************************************************************************/
@@ -2024,20 +2228,26 @@ void ResourceFormatSaverXMLInstance::write_property(const String& p_name,const V
return; // don't save it
}
- params="resource_type=\""+res->get_save_type()+"\"";
+ if (external_resources.has(res)) {
- if (res->get_path().length() && res->get_path().find("::")==-1) {
- //external resource
- String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
- escape(path);
- params+=" path=\""+path+"\"";
+ params="external=\""+itos(external_resources[res])+"\"";
} else {
+ params="resource_type=\""+res->get_save_type()+"\"";
- //internal resource
- ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
- ERR_FAIL_COND(!resource_set.has(res));
- params+=" path=\"local://"+itos(res->get_subindex())+"\"";
+ if (res->get_path().length() && res->get_path().find("::")==-1) {
+ //external resource
+ String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
+ escape(path);
+ params+=" path=\""+path+"\"";
+ } else {
+
+ //internal resource
+ ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
+ ERR_FAIL_COND(!resource_set.has(res));
+
+ params+=" path=\"local://"+itos(res->get_subindex())+"\"";
+ }
}
} break;
@@ -2441,11 +2651,12 @@ void ResourceFormatSaverXMLInstance::_find_resources(const Variant& p_variant,bo
RES res = p_variant.operator RefPtr();
- if (res.is_null())
+ if (res.is_null() || external_resources.has(res))
return;
if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) {
- external_resources.push_back(res);
+ int index = external_resources.size();
+ external_resources[res]=index;
return;
}
@@ -2533,12 +2744,12 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
enter_tag("resource_file","type=\""+p_resource->get_type()+"\" subresource_count=\""+itos(saved_resources.size()+external_resources.size())+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\"");
write_string("\n",false);
- for(List<RES>::Element *E=external_resources.front();E;E=E->next()) {
+ for(Map<RES,int>::Element *E=external_resources.front();E;E=E->next()) {
write_tabs();
- String p = E->get()->get_path();
+ String p = E->key()->get_path();
- enter_tag("ext_resource","path=\""+p+"\" type=\""+E->get()->get_save_type()+"\""); //bundled
+ enter_tag("ext_resource","path=\""+p+"\" type=\""+E->key()->get_save_type()+"\" index=\""+itos(E->get())+"\""); //bundled
exit_tag("ext_resource"); //bundled
write_string("\n",false);
}
@@ -2667,3 +2878,8 @@ void ResourceFormatSaverXML::get_recognized_extensions(const RES& p_resource,Lis
}
}
+
+ResourceFormatSaverXML* ResourceFormatSaverXML::singleton=NULL;
+ResourceFormatSaverXML::ResourceFormatSaverXML() {
+ singleton=this;
+}
diff --git a/core/io/resource_format_xml.h b/core/io/resource_format_xml.h
index d5ba9eb800..77987c6a5b 100644
--- a/core/io/resource_format_xml.h
+++ b/core/io/resource_format_xml.h
@@ -46,13 +46,21 @@ class ResourceInteractiveLoaderXML : public ResourceInteractiveLoader {
String name;
HashMap<String,String> args;
+
};
_FORCE_INLINE_ Error _parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end);
+ struct ExtResource {
+ String path;
+ String type;
+ };
+
- List<StringName> ext_resources;
+ Map<String,String> remaps;
+
+ Map<int,ExtResource> ext_resources;
int resources_total;
int resource_current;
@@ -66,7 +74,7 @@ friend class ResourceFormatLoaderXML;
List<Tag> tag_stack;
List<RES> resource_cache;
- Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true);
+ Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true,List<String> *r_order=NULL);
Error close_tag(const String& p_name);
_FORCE_INLINE_ void unquote(String& p_str);
Error goto_end_of_tag();
@@ -87,7 +95,8 @@ public:
void open(FileAccess *p_f);
String recognize(FileAccess *p_f);
- void get_dependencies(FileAccess *p_f,List<String> *p_dependencies);
+ void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
+ Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map);
~ResourceInteractiveLoaderXML();
@@ -97,12 +106,13 @@ public:
class ResourceFormatLoaderXML : public ResourceFormatLoader {
public:
- virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
+ virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL);
virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
- virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
+ virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false);
+ virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
};
@@ -125,7 +135,7 @@ class ResourceFormatSaverXMLInstance {
int depth;
Set<RES> resource_set;
List<RES> saved_resources;
- List<RES> external_resources;
+ Map<RES,int> external_resources;
void enter_tag(const char* p_tag,const String& p_args=String());
void exit_tag(const char* p_tag);
@@ -148,11 +158,12 @@ public:
class ResourceFormatSaverXML : public ResourceFormatSaver {
public:
+ static ResourceFormatSaverXML* singleton;
virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
virtual bool recognize(const RES& p_resource) const;
virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
-
+ ResourceFormatSaverXML();
};
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 22d89840ae..1e014480f4 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -103,10 +103,10 @@ public:
-Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) {
//either this
- Ref<Resource> res = load(p_path);
+ Ref<Resource> res = load(p_path,p_path,r_error);
if (res.is_null())
return Ref<ResourceInteractiveLoader>();
@@ -115,12 +115,13 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const Stri
return ril;
}
-RES ResourceFormatLoader::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoader::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
String path=p_path;
//or this must be implemented
- Ref<ResourceInteractiveLoader> ril = load_interactive(p_path);
+ Ref<ResourceInteractiveLoader> ril = load_interactive(p_path,r_error);
if (!ril.is_valid())
return RES();
ril->set_local_path(p_original_path);
@@ -130,9 +131,14 @@ RES ResourceFormatLoader::load(const String &p_path,const String& p_original_pat
Error err = ril->poll();
if (err==ERR_FILE_EOF) {
+ if (r_error)
+ *r_error=OK;
return ril->get_resource();
}
+ if (r_error)
+ *r_error=err;
+
ERR_FAIL_COND_V(err!=OK,RES());
}
@@ -140,7 +146,7 @@ RES ResourceFormatLoader::load(const String &p_path,const String& p_original_pat
}
-void ResourceFormatLoader::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceFormatLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) {
//do nothing by default
}
@@ -149,7 +155,10 @@ void ResourceFormatLoader::get_dependencies(const String& p_path,List<String> *p
///////////////////////////////////
-RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_no_cache) {
+RES ResourceLoader::load(const String &p_path, const String& p_type_hint, bool p_no_cache, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
String local_path;
if (p_path.is_rel_path())
@@ -183,7 +192,7 @@ RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_n
if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
continue;
found=true;
- RES res = loader[i]->load(remapped_path,local_path);
+ RES res = loader[i]->load(remapped_path,local_path,r_error);
if (res.is_null())
continue;
if (!p_no_cache)
@@ -289,9 +298,11 @@ String ResourceLoader::find_complete_path(const String& p_path,const String& p_t
return local_path;
}
-Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache) {
+Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache,Error *r_error) {
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
String local_path;
if (p_path.is_rel_path())
@@ -327,7 +338,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
continue;
found=true;
- Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(remapped_path);
+ Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(remapped_path,r_error);
if (ril.is_null())
continue;
if (!p_no_cache)
@@ -352,7 +363,32 @@ void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_l
loader[loader_count++]=p_format_loader;
}
-void ResourceLoader::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) {
+
+
+ String local_path;
+ if (p_path.is_rel_path())
+ local_path="res://"+p_path;
+ else
+ local_path = Globals::get_singleton()->localize_path(p_path);
+
+ String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
+
+ String extension=remapped_path.extension();
+
+ for (int i=0;i<loader_count;i++) {
+
+ if (!loader[i]->recognize(extension))
+ continue;
+ //if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
+ // continue;
+
+ loader[i]->get_dependencies(remapped_path,p_dependencies,p_add_types);
+
+ }
+}
+
+Error ResourceLoader::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
String local_path;
@@ -372,11 +408,15 @@ void ResourceLoader::get_dependencies(const String& p_path,List<String> *p_depen
//if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
// continue;
- loader[i]->get_dependencies(remapped_path,p_dependencies);
+ return loader[i]->rename_dependencies(p_path,p_map);
}
+
+ return OK; // ??
+
}
+
String ResourceLoader::guess_full_filename(const String &p_path,const String& p_type) {
String local_path;
@@ -414,6 +454,9 @@ String ResourceLoader::get_resource_type(const String &p_path) {
ResourceLoadErrorNotify ResourceLoader::err_notify=NULL;
void *ResourceLoader::err_notify_ud=NULL;
+DependencyErrorNotify ResourceLoader::dep_err_notify=NULL;
+void *ResourceLoader::dep_err_notify_ud=NULL;
+
bool ResourceLoader::abort_on_missing_resource=true;
bool ResourceLoader::timestamp_on_load=false;
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index d25727f19f..00a05dcb43 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -57,21 +57,23 @@ public:
class ResourceFormatLoader {
public:
- virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL);
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
bool recognize(const String& p_extension) const;
virtual bool handles_type(const String& p_type) const=0;
virtual String get_resource_type(const String &p_path) const=0;
- virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
+ virtual void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false);
virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const { return ERR_UNAVAILABLE; }
+ virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map) { return OK; }
virtual ~ResourceFormatLoader() {}
};
typedef void (*ResourceLoadErrorNotify)(void *p_ud,const String& p_text);
+typedef void (*DependencyErrorNotify)(void *p_ud,const String& p_loading,const String& p_which,const String& p_type);
class ResourceLoader {
@@ -86,6 +88,8 @@ class ResourceLoader {
static void* err_notify_ud;
static ResourceLoadErrorNotify err_notify;
+ static void* dep_err_notify_ud;
+ static DependencyErrorNotify dep_err_notify;
static bool abort_on_missing_resource;
static String find_complete_path(const String& p_path,const String& p_type);
@@ -93,14 +97,15 @@ public:
- static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false);
- static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false);
+ static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL);
+ static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL);
static Ref<ResourceImportMetadata> load_import_metadata(const String &p_path);
static void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions);
static void add_resource_format_loader(ResourceFormatLoader *p_format_loader);
static String get_resource_type(const String &p_path);
- static void get_dependencies(const String& p_path,List<String> *p_dependencies);
+ static void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false);
+ static Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
static String guess_full_filename(const String &p_path,const String& p_type);
@@ -108,6 +113,11 @@ public:
static void notify_load_error(const String& p_err) { if (err_notify) err_notify(err_notify_ud,p_err); }
static void set_error_notify_func(void* p_ud,ResourceLoadErrorNotify p_err_notify) { err_notify=p_err_notify; err_notify_ud=p_ud;}
+
+ static void notify_dependency_error(const String& p_path,const String& p_dependency,const String& p_type) { if (dep_err_notify) dep_err_notify(dep_err_notify_ud,p_path,p_dependency,p_type); }
+ static void set_dependency_error_notify_func(void* p_ud,DependencyErrorNotify p_err_notify) { dep_err_notify=p_err_notify; dep_err_notify_ud=p_ud;}
+
+
static void set_abort_on_missing_resources(bool p_abort) { abort_on_missing_resource=p_abort; }
static bool get_abort_on_missing_resources() { return abort_on_missing_resource; }
};
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 05cbe7f98e..8382b65290 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -46,7 +46,7 @@ public:
virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0)=0;
virtual bool recognize(const RES& p_resource) const=0;
virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const=0;
-
+
virtual ~ResourceFormatSaver() {}
};
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index c32b25c407..020d168208 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -30,7 +30,10 @@
#include "os/file_access.h"
#include "translation.h"
-RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path) {
+RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
ERR_FAIL_COND_V(!f,RES());
@@ -49,6 +52,8 @@ RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path
String msg_id;
String msg_str;
String config;
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
Ref<Translation> translation = Ref<Translation>( memnew( Translation ));
int line = 1;
@@ -174,6 +179,8 @@ RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path
}
}
+ if (r_error)
+ *r_error=OK;
return translation;
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index 9d8ad97a29..e07ae15e28 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -34,7 +34,7 @@
class TranslationLoaderPO : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/core/io/zip.h b/core/io/zip.h
index cca06c2ee8..85f93568c9 100644
--- a/core/io/zip.h
+++ b/core/io/zip.h
@@ -39,6 +39,8 @@
#ifndef _zip12_H
#define _zip12_H
+#include <stdlib.h>
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index c4b4d6b34d..dd3c371a4a 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -34,6 +34,7 @@
#include "os/file_access.h"
#include "os/copymem.h"
+
static void* zipio_open(void* data, const char* p_fname, int mode) {
FileAccess *&f = *(FileAccess**)data;
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index c291714573..a64b3d2715 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -746,6 +746,25 @@ bool ObjectTypeDB::has_method(StringName p_type,StringName p_method,bool p_no_in
}
+bool ObjectTypeDB::get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter) {
+
+ TypeInfo *type=types.getptr(p_class);
+ TypeInfo *check=type;
+ while(check) {
+
+ if (check->property_setget.has(p_prop)) {
+ r_class=check->name;
+ r_setter=check->property_setget[p_prop].setter;
+ return true;
+ }
+
+ check=check->inherits_ptr;
+ }
+
+ return false;
+
+}
+
#ifdef DEBUG_METHODS_ENABLED
MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname=method_name.name;
diff --git a/core/object_type_db.h b/core/object_type_db.h
index caa5baddd5..bfa0f921e5 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -475,7 +475,9 @@ public:
static void get_integer_constant_list(const StringName& p_type, List<String> *p_constants, bool p_no_inheritance=false);
static int get_integer_constant(const StringName& p_type, const StringName &p_name, bool *p_success=NULL);
static StringName get_category(const StringName& p_node);
-
+
+ static bool get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter);
+
static void set_type_enabled(StringName p_type,bool p_enable);
static bool is_type_enabled(StringName p_type);
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 2b939ede46..cf2938f5cd 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -271,6 +271,38 @@ void InputDefault::parse_input_event(const InputEvent& p_event) {
mouse_button_mask|=(1<<p_event.mouse_button.button_index);
else
mouse_button_mask&=~(1<<p_event.mouse_button.button_index);
+
+ if (main_loop && emulate_touch && p_event.mouse_button.button_index==1) {
+ InputEventScreenTouch touch_event;
+ touch_event.index=0;
+ touch_event.pressed=p_event.mouse_button.pressed;
+ touch_event.x=p_event.mouse_button.x;
+ touch_event.y=p_event.mouse_button.y;
+ InputEvent ev;
+ ev.type=InputEvent::SCREEN_TOUCH;
+ ev.screen_touch=touch_event;
+ main_loop->input_event(ev);
+ }
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ if (main_loop && emulate_touch && p_event.mouse_motion.button_mask&1) {
+ InputEventScreenDrag drag_event;
+ drag_event.index=0;
+ drag_event.x=p_event.mouse_motion.x;
+ drag_event.y=p_event.mouse_motion.y;
+ drag_event.relative_x=p_event.mouse_motion.relative_x;
+ drag_event.relative_y=p_event.mouse_motion.relative_y;
+ drag_event.speed_x=p_event.mouse_motion.speed_x;
+ drag_event.speed_y=p_event.mouse_motion.speed_y;
+
+ InputEvent ev;
+ ev.type=InputEvent::SCREEN_DRAG;
+ ev.screen_drag=drag_event;
+
+ main_loop->input_event(ev);
+ }
+
} break;
case InputEvent::JOYSTICK_BUTTON: {
@@ -362,8 +394,19 @@ void InputDefault::action_release(const StringName& p_action){
}
}
+void InputDefault::set_emulate_touch(bool p_emulate) {
+
+ emulate_touch=p_emulate;
+}
+
+bool InputDefault::is_emulating_touchscreen() const {
+
+ return emulate_touch;
+}
+
InputDefault::InputDefault() {
mouse_button_mask=0;
+ emulate_touch=false;
main_loop=NULL;
}
diff --git a/core/os/input.h b/core/os/input.h
index ce14c2166e..5c69ced825 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -78,6 +78,8 @@ public:
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
+ virtual bool is_emulating_touchscreen() const=0;
+
Input();
};
@@ -99,6 +101,8 @@ class InputDefault : public Input {
Vector2 mouse_pos;
MainLoop *main_loop;
+ bool emulate_touch;
+
struct SpeedTrack {
uint64_t last_tick;
@@ -147,6 +151,9 @@ public:
void iteration(float p_step);
+ void set_emulate_touch(bool p_emulate);
+ virtual bool is_emulating_touchscreen() const;
+
InputDefault();
};
diff --git a/core/os/os.cpp b/core/os/os.cpp
index efcd492230..2db926e556 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -31,7 +31,7 @@
#include <stdarg.h>
#include "dir_access.h"
#include "globals.h"
-
+#include "input.h"
OS* OS::singleton=NULL;
@@ -363,7 +363,7 @@ Error OS::set_cwd(const String& p_cwd) {
bool OS::has_touchscreen_ui_hint() const {
//return false;
- return GLOBAL_DEF("display/emulate_touchscreen",false);
+ return Input::get_singleton() && Input::get_singleton()->is_emulating_touchscreen();
}
int OS::get_free_static_memory() const {
diff --git a/core/os/os.h b/core/os/os.h
index e8ecfa1054..d89734d7d3 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -155,7 +155,7 @@ public:
virtual int get_screen_count() const{ return 1; }
virtual int get_current_screen() const { return 0; }
virtual void set_current_screen(int p_screen) { }
- virtual Point2 get_screen_position(int p_screen=0) { return Point2(); }
+ virtual Point2 get_screen_position(int p_screen=0) const { return Point2(); }
virtual Size2 get_screen_size(int p_screen=0) const { return get_window_size(); }
virtual Point2 get_window_position() const { return Vector2(); }
virtual void set_window_position(const Point2& p_position) {}
diff --git a/core/typedefs.h b/core/typedefs.h
index ae1eb1f5e7..6ca31fd137 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -41,8 +41,8 @@
#define _MKSTR(m_x) _STR(m_x)
#endif
// have to include version.h for this to work, include it in the .cpp not the .h
-#define VERSION_MKSTRING _MKSTR(VERSION_MAJOR)"."_MKSTR(VERSION_MINOR)"."_MKSTR(VERSION_STATUS)"."_MKSTR(VERSION_REVISION)
-#define VERSION_FULL_NAME _MKSTR(VERSION_NAME)" v"VERSION_MKSTRING
+#define VERSION_MKSTRING _MKSTR(VERSION_MAJOR)"." _MKSTR(VERSION_MINOR)"." _MKSTR(VERSION_STATUS)"." _MKSTR(VERSION_REVISION)
+#define VERSION_FULL_NAME _MKSTR(VERSION_NAME)" v" VERSION_MKSTRING
#ifndef _ALWAYS_INLINE_
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 3cfc1e4a3c..ff7c8984fa 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -3048,6 +3048,37 @@ bool String::is_valid_identifier() const {
//kind of poor should be rewritten properly
+String String::world_wrap(int p_chars_per_line) const {
+
+ int from=0;
+ int last_space=0;
+ String ret;
+ for(int i=0;i<length();i++) {
+ if (i-from>=p_chars_per_line) {
+ if (last_space==-1) {
+ ret+=substr(from,i-from+1)+"\n";
+ } else {
+ ret+=substr(from,last_space-from)+"\n";
+ i=last_space; //rewind
+ }
+ from=i+1;
+ last_space=-1;
+ } else if (operator[](i)==' ' || operator[](i)=='\t') {
+ last_space=i;
+ } else if (operator[](i)=='\n') {
+ ret+=substr(from,i-from);
+ from=i+1;
+ last_space=-1;
+ }
+ }
+
+ if (from<length()) {
+ ret+=substr(from,length());
+ }
+
+ return ret;
+}
+
String String::c_unescape() const {
String escaped=*this;
diff --git a/core/ustring.h b/core/ustring.h
index 1000c1cc8a..fa25a07eb0 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -209,6 +209,7 @@ public:
String xml_unescape() const;
String c_escape() const;
String c_unescape() const;
+ String world_wrap(int p_chars_per_line) const;
String percent_encode() const;
String percent_decode() const;
diff --git a/core/variant.cpp b/core/variant.cpp
index e0bceb4dd8..c6a55b10e6 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1592,9 +1592,17 @@ Variant::operator String() const {
} break;
case OBJECT: {
- if (_get_obj().obj)
+ if (_get_obj().obj) {
+ #ifdef DEBUG_ENABLED
+ if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
+ //only if debugging!
+ if (!ObjectDB::instance_validate(_get_obj().obj)) {
+ return "[Deleted Object]";
+ };
+ };
+ #endif
return "["+_get_obj().obj->get_type()+":"+itos(_get_obj().obj->get_instance_ID())+"]";
- else
+ } else
return "[Object:null]";
} break;
diff --git a/demos/2d/dynamic_collision_shapes/ball.gd b/demos/2d/dynamic_collision_shapes/ball.gd
new file mode 100644
index 0000000000..c17b20f9c8
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/ball.gd
@@ -0,0 +1,21 @@
+
+extends RigidBody2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+var timeout=5
+
+func _process(delta):
+ timeout-=delta
+ if (timeout<1):
+ set_opacity(timeout)
+ if (timeout<0):
+ queue_free()
+func _ready():
+ set_process(true)
+ # Initialization here
+ pass
+
+
diff --git a/demos/2d/dynamic_collision_shapes/ball.png b/demos/2d/dynamic_collision_shapes/ball.png
new file mode 100644
index 0000000000..b7cf71da29
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/ball.png
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/ball.scn b/demos/2d/dynamic_collision_shapes/ball.scn
new file mode 100644
index 0000000000..e332de276d
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/ball.scn
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/box.png b/demos/2d/dynamic_collision_shapes/box.png
new file mode 100644
index 0000000000..f29b83ce38
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/box.png
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/circle.png b/demos/2d/dynamic_collision_shapes/circle.png
new file mode 100644
index 0000000000..9fdfa550b1
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/circle.png
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd
new file mode 100644
index 0000000000..a6a42a1914
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd
@@ -0,0 +1,23 @@
+
+extends Node2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const EMIT_INTERVAL=0.1
+var timeout=EMIT_INTERVAL
+
+func _process(delta):
+ timeout-=delta
+ if (timeout<0):
+ timeout=EMIT_INTERVAL
+ var ball = preload("res://ball.scn").instance()
+ ball.set_pos( Vector2(randf() * get_viewport_rect().size.x, 0) )
+ add_child(ball)
+
+func _ready():
+ set_process(true)
+ # Initialization here
+ pass
+
+
diff --git a/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn
new file mode 100644
index 0000000000..e6d1ebf9cf
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/engine.cfg b/demos/2d/dynamic_collision_shapes/engine.cfg
new file mode 100644
index 0000000000..536b75f2f2
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/engine.cfg
@@ -0,0 +1,4 @@
+[application]
+
+name="Run-Time CollisionShape"
+main_scene="res://dynamic_colobjs.scn"
diff --git a/demos/2d/dynamic_collision_shapes/poly.png b/demos/2d/dynamic_collision_shapes/poly.png
new file mode 100644
index 0000000000..49ed55cc7d
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/poly.png
Binary files differ
diff --git a/demos/2d/isometric/dungeon.scn b/demos/2d/isometric/dungeon.scn
index 64efc257c0..e03a3bd3dd 100644
--- a/demos/2d/isometric/dungeon.scn
+++ b/demos/2d/isometric/dungeon.scn
Binary files differ
diff --git a/demos/2d/lights_shadows/light_shadows.scn b/demos/2d/lights_shadows/light_shadows.scn
index a13e31376e..152f68a407 100644
--- a/demos/2d/lights_shadows/light_shadows.scn
+++ b/demos/2d/lights_shadows/light_shadows.scn
Binary files differ
diff --git a/demos/2d/platformer/engine.cfg b/demos/2d/platformer/engine.cfg
index 50b6b862e9..044d661e3e 100644
--- a/demos/2d/platformer/engine.cfg
+++ b/demos/2d/platformer/engine.cfg
@@ -4,14 +4,14 @@ name="Platformer"
main_scene="res://stage.xml"
icon="res://icon.png"
name_es="Plataformero"
+target_fps="60"
[display]
width=800
height=480
-stretch_2d=false
-stretch_mode="viewport"
-stretch_aspect="keep"
+stretch_mode="2d"
+stretch_aspect="keep_height"
[image_loader]
diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml
index 4d6083adf6..d081a1be38 100644
--- a/demos/2d/platformer/stage.xml
+++ b/demos/2d/platformer/stage.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="10" version="1.1" version_name="Godot Engine v1.1.rc1.custom_build">
+<resource_file type="PackedScene" subresource_count="10" version="1.1" version_name="Godot Engine v1.1.stable.custom_build">
<ext_resource path="res://tileset.xml" type="TileSet"></ext_resource>
<ext_resource path="res://coin.xml" type="PackedScene"></ext_resource>
<ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource>
@@ -16,22 +16,12 @@
<string> "conns" </string>
<int_array len="0"> </int_array>
<string> "names" </string>
- <string_array len="133">
+ <string_array len="117">
<string> "stage" </string>
<string> "Node" </string>
- <string> "_import_path" </string>
<string> "__meta__" </string>
<string> "tile_map" </string>
<string> "TileMap" </string>
- <string> "visibility/visible" </string>
- <string> "visibility/opacity" </string>
- <string> "visibility/self_opacity" </string>
- <string> "visibility/light_mask" </string>
- <string> "transform/pos" </string>
- <string> "transform/rot" </string>
- <string> "transform/scale" </string>
- <string> "z/z" </string>
- <string> "z/relative" </string>
<string> "mode" </string>
<string> "tile_set" </string>
<string> "cell/size" </string>
@@ -49,6 +39,8 @@
<string> "coins" </string>
<string> "coin" </string>
<string> "Area2D" </string>
+ <string> "_import_path" </string>
+ <string> "transform/pos" </string>
<string> "coin 2" </string>
<string> "coin 3" </string>
<string> "coin 4" </string>
@@ -129,14 +121,9 @@
<string> "margin/top" </string>
<string> "margin/right" </string>
<string> "margin/bottom" </string>
- <string> "focus_neighbour/left" </string>
- <string> "focus_neighbour/top" </string>
- <string> "focus_neighbour/right" </string>
- <string> "focus_neighbour/bottom" </string>
<string> "focus/ignore_mouse" </string>
<string> "focus/stop_mouse" </string>
<string> "size_flags/horizontal" </string>
- <string> "size_flags/stretch_ratio" </string>
<string> "range/min" </string>
<string> "range/max" </string>
<string> "range/step" </string>
@@ -145,19 +132,15 @@
<string> "range/exp_edit" </string>
<string> "rounded_values" </string>
<string> "text" </string>
- <string> "align" </string>
- <string> "valign" </string>
<string> "autowrap" </string>
- <string> "uppercase" </string>
<string> "percent_visible" </string>
</string_array>
<string> "node_count" </string>
<int> 67 </int>
<string> "nodes" </string>
- <int_array len="973"> -1, -1, 1, 0, -1, 2, 2, 0, 3, 1, 0, 0, 0, 5, 4, -1, 25, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 2, 15, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 8, 22, 14, 23, 14, 24, 3, 25, 6, 26, 4, 27, 4, 28, 15, 3, 16, 0, 0, 0, 1, 29, -1, 1, 2, 0, 0, 2, 0, 31, 30, 17, 3, 2, 0, 10, 18, 3, 19, 0, 2, 0, 31, 32, 17, 3, 2, 0, 10, 20, 3, 19, 0, 2, 0, 31, 33, 17, 3, 2, 0, 10, 21, 3, 19, 0, 2, 0, 31, 34, 17, 3, 2, 0, 10, 22, 3, 19, 0, 2, 0, 31, 35, 17, 3, 2, 0, 10, 23, 3, 19, 0, 2, 0, 31, 36, 17, 3, 2, 0, 10, 24, 3, 19, 0, 2, 0, 31, 37, 17, 3, 2, 0, 10, 25, 3, 19, 0, 2, 0, 31, 38, 17, 3, 2, 0, 10, 26, 3, 19, 0, 2, 0, 31, 39, 17, 3, 2, 0, 10, 27, 3, 19, 0, 2, 0, 31, 40, 17, 3, 2, 0, 10, 28, 3, 19, 0, 2, 0, 31, 41, 17, 3, 2, 0, 10, 29, 3, 19, 0, 2, 0, 31, 42, 17, 3, 2, 0, 10, 30, 3, 19, 0, 2, 0, 31, 43, 17, 3, 2, 0, 10, 31, 3, 19, 0, 2, 0, 31, 44, 17, 3, 2, 0, 10, 32, 3, 19, 0, 2, 0, 31, 45, 17, 3, 2, 0, 10, 33, 3, 19, 0, 2, 0, 31, 46, 17, 3, 2, 0, 10, 34, 3, 19, 0, 2, 0, 31, 47, 17, 3, 2, 0, 10, 35, 3, 19, 0, 2, 0, 31, 48, 17, 3, 2, 0, 10, 36, 3, 19, 0, 2, 0, 31, 49, 17, 3, 2, 0, 10, 37, 3, 19, 0, 2, 0, 31, 50, 17, 3, 2, 0, 10, 38, 3, 19, 0, 2, 0, 31, 51, 17, 3, 2, 0, 10, 39, 3, 19, 0, 2, 0, 31, 52, 17, 3, 2, 0, 10, 40, 3, 19, 0, 2, 0, 31, 53, 17, 3, 2, 0, 10, 41, 3, 19, 0, 2, 0, 31, 54, 17, 3, 2, 0, 10, 42, 3, 19, 0, 2, 0, 31, 55, 17, 3, 2, 0, 10, 43, 3, 19, 0, 2, 0, 31, 56, 17, 3, 2, 0, 10, 44, 3, 19, 0, 2, 0, 31, 57, 17, 3, 2, 0, 10, 45, 3, 19, 0, 2, 0, 31, 58, 17, 3, 2, 0, 10, 46, 3, 19, 0, 2, 0, 31, 59, 17, 3, 2, 0, 10, 47, 3, 19, 0, 2, 0, 31, 60, 17, 3, 2, 0, 10, 48, 3, 19, 0, 2, 0, 31, 61, 17, 3, 2, 0, 10, 49, 3, 19, 0, 2, 0, 31, 62, 17, 3, 2, 0, 10, 50, 3, 19, 0, 2, 0, 31, 63, 17, 3, 2, 0, 10, 51, 3, 19, 0, 2, 0, 31, 64, 17, 3, 2, 0, 10, 52, 3, 19, 0, 2, 0, 31, 65, 17, 3, 2, 0, 10, 53, 3, 19, 0, 2, 0, 31, 66, 17, 3, 2, 0, 10, 54, 3, 19, 0, 2, 0, 31, 67, 17, 3, 2, 0, 10, 55, 3, 19, 0, 2, 0, 31, 68, 17, 3, 2, 0, 10, 56, 3, 19, 0, 2, 0, 31, 69, 17, 3, 2, 0, 10, 57, 3, 19, 0, 2, 0, 31, 70, 17, 3, 2, 0, 10, 58, 3, 19, 0, 2, 0, 31, 71, 17, 3, 2, 0, 10, 59, 3, 19, 0, 2, 0, 31, 72, 17, 3, 2, 0, 10, 60, 3, 19, 0, 0, 0, 1, 73, -1, 1, 2, 0, 0, 45, 0, 75, 74, 61, 5, 2, 0, 10, 62, 3, 63, 76, 64, 77, 65, 0, 45, 0, 75, 78, 61, 5, 2, 0, 10, 66, 3, 63, 76, 67, 77, 68, 0, 45, 0, 75, 79, 61, 5, 2, 0, 10, 69, 3, 63, 76, 70, 77, 68, 0, 45, 0, 75, 80, 71, 3, 2, 0, 10, 72, 3, 73, 0, 45, 0, 82, 81, 74, 3, 2, 0, 10, 75, 3, 76, 0, 0, 0, 84, 83, 77, 3, 2, 0, 10, 78, 3, 79, 0, 0, 0, 86, 85, -1, 7, 2, 0, 87, 80, 88, 14, 89, 2, 90, 81, 91, 2, 92, 14, 0, 0, 0, 1, 93, -1, 1, 2, 0, 0, 53, 0, 84, 94, 82, 3, 2, 0, 10, 83, 3, 84, 0, 53, 0, 84, 95, 82, 3, 2, 0, 10, 85, 3, 84, 0, 53, 0, 84, 96, 82, 3, 2, 0, 10, 86, 3, 84, 0, 53, 0, 84, 97, 82, 3, 2, 0, 10, 87, 3, 84, 0, 53, 0, 84, 98, 82, 3, 2, 0, 10, 88, 3, 84, 0, 53, 0, 84, 99, 82, 3, 2, 0, 10, 89, 3, 84, 0, 53, 0, 84, 100, 82, 3, 2, 0, 10, 90, 3, 84, 0, 53, 0, 84, 101, 82, 3, 2, 0, 10, 91, 3, 84, 0, 53, 0, 84, 102, 82, 3, 2, 0, 10, 92, 3, 84, 0, 53, 0, 84, 103, 82, 3, 2, 0, 10, 93, 3, 84, 0, 53, 0, 84, 104, 82, 3, 2, 0, 10, 94, 3, 84, 0, 0, 0, 106, 105, 95, 2, 2, 0, 3, 96, 0, 0, 0, 107, 107, -1, 30, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 108, 97, 109, 98, 110, 99, 111, 100, 112, 0, 113, 0, 114, 0, 115, 0, 116, 2, 117, 2, 118, 13, 119, 3, 120, 6, 121, 101, 122, 3, 123, 102, 124, 6, 125, 14, 126, 14, 127, 103, 128, 8, 129, 8, 130, 2, 131, 14, 132, 104, 0 </int_array>
+ <int_array len="917"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 4, 3, -1, 15, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 1, 12, 7, 13, 7, 14, 8, 15, 9, 16, 10, 17, 10, 18, 11, 2, 12, 0, 0, 0, 1, 19, -1, 0, 0, 2, 0, 21, 20, 13, 3, 22, 14, 23, 15, 2, 16, 0, 2, 0, 21, 24, 13, 3, 22, 14, 23, 17, 2, 16, 0, 2, 0, 21, 25, 13, 3, 22, 14, 23, 18, 2, 16, 0, 2, 0, 21, 26, 13, 3, 22, 14, 23, 19, 2, 16, 0, 2, 0, 21, 27, 13, 3, 22, 14, 23, 20, 2, 16, 0, 2, 0, 21, 28, 13, 3, 22, 14, 23, 21, 2, 16, 0, 2, 0, 21, 29, 13, 3, 22, 14, 23, 22, 2, 16, 0, 2, 0, 21, 30, 13, 3, 22, 14, 23, 23, 2, 16, 0, 2, 0, 21, 31, 13, 3, 22, 14, 23, 24, 2, 16, 0, 2, 0, 21, 32, 13, 3, 22, 14, 23, 25, 2, 16, 0, 2, 0, 21, 33, 13, 3, 22, 14, 23, 26, 2, 16, 0, 2, 0, 21, 34, 13, 3, 22, 14, 23, 27, 2, 16, 0, 2, 0, 21, 35, 13, 3, 22, 14, 23, 28, 2, 16, 0, 2, 0, 21, 36, 13, 3, 22, 14, 23, 29, 2, 16, 0, 2, 0, 21, 37, 13, 3, 22, 14, 23, 30, 2, 16, 0, 2, 0, 21, 38, 13, 3, 22, 14, 23, 31, 2, 16, 0, 2, 0, 21, 39, 13, 3, 22, 14, 23, 32, 2, 16, 0, 2, 0, 21, 40, 13, 3, 22, 14, 23, 33, 2, 16, 0, 2, 0, 21, 41, 13, 3, 22, 14, 23, 34, 2, 16, 0, 2, 0, 21, 42, 13, 3, 22, 14, 23, 35, 2, 16, 0, 2, 0, 21, 43, 13, 3, 22, 14, 23, 36, 2, 16, 0, 2, 0, 21, 44, 13, 3, 22, 14, 23, 37, 2, 16, 0, 2, 0, 21, 45, 13, 3, 22, 14, 23, 38, 2, 16, 0, 2, 0, 21, 46, 13, 3, 22, 14, 23, 39, 2, 16, 0, 2, 0, 21, 47, 13, 3, 22, 14, 23, 40, 2, 16, 0, 2, 0, 21, 48, 13, 3, 22, 14, 23, 41, 2, 16, 0, 2, 0, 21, 49, 13, 3, 22, 14, 23, 42, 2, 16, 0, 2, 0, 21, 50, 13, 3, 22, 14, 23, 43, 2, 16, 0, 2, 0, 21, 51, 13, 3, 22, 14, 23, 44, 2, 16, 0, 2, 0, 21, 52, 13, 3, 22, 14, 23, 45, 2, 16, 0, 2, 0, 21, 53, 13, 3, 22, 14, 23, 46, 2, 16, 0, 2, 0, 21, 54, 13, 3, 22, 14, 23, 47, 2, 16, 0, 2, 0, 21, 55, 13, 3, 22, 14, 23, 48, 2, 16, 0, 2, 0, 21, 56, 13, 3, 22, 14, 23, 49, 2, 16, 0, 2, 0, 21, 57, 13, 3, 22, 14, 23, 50, 2, 16, 0, 2, 0, 21, 58, 13, 3, 22, 14, 23, 51, 2, 16, 0, 2, 0, 21, 59, 13, 3, 22, 14, 23, 52, 2, 16, 0, 2, 0, 21, 60, 13, 3, 22, 14, 23, 53, 2, 16, 0, 2, 0, 21, 61, 13, 3, 22, 14, 23, 54, 2, 16, 0, 2, 0, 21, 62, 13, 3, 22, 14, 23, 55, 2, 16, 0, 2, 0, 21, 63, 13, 3, 22, 14, 23, 56, 2, 16, 0, 2, 0, 21, 64, 13, 3, 22, 14, 23, 57, 2, 16, 0, 0, 0, 1, 65, -1, 0, 0, 45, 0, 67, 66, 58, 5, 22, 14, 23, 59, 2, 60, 68, 61, 69, 62, 0, 45, 0, 67, 70, 58, 5, 22, 14, 23, 63, 2, 60, 68, 64, 69, 65, 0, 45, 0, 67, 71, 58, 5, 22, 14, 23, 66, 2, 60, 68, 67, 69, 65, 0, 45, 0, 67, 72, 68, 3, 22, 14, 23, 69, 2, 70, 0, 45, 0, 74, 73, 71, 3, 22, 14, 23, 72, 2, 73, 0, 0, 0, 76, 75, 74, 3, 22, 14, 23, 75, 2, 76, 0, 0, 0, 78, 77, -1, 6, 79, 77, 80, 7, 81, 78, 82, 79, 83, 78, 84, 7, 0, 0, 0, 1, 85, -1, 0, 0, 53, 0, 76, 86, 80, 3, 22, 14, 23, 81, 2, 82, 0, 53, 0, 76, 87, 80, 3, 22, 14, 23, 83, 2, 82, 0, 53, 0, 76, 88, 80, 3, 22, 14, 23, 84, 2, 82, 0, 53, 0, 76, 89, 80, 3, 22, 14, 23, 85, 2, 82, 0, 53, 0, 76, 90, 80, 3, 22, 14, 23, 86, 2, 82, 0, 53, 0, 76, 91, 80, 3, 22, 14, 23, 87, 2, 82, 0, 53, 0, 76, 92, 80, 3, 22, 14, 23, 88, 2, 82, 0, 53, 0, 76, 93, 80, 3, 22, 14, 23, 89, 2, 82, 0, 53, 0, 76, 94, 80, 3, 22, 14, 23, 90, 2, 82, 0, 53, 0, 76, 95, 80, 3, 22, 14, 23, 91, 2, 82, 0, 53, 0, 76, 96, 80, 3, 22, 14, 23, 92, 2, 82, 0, 0, 0, 98, 97, 93, 2, 22, 14, 2, 94, 0, 0, 0, 99, 99, -1, 17, 100, 95, 101, 96, 102, 97, 103, 98, 104, 78, 105, 78, 106, 6, 107, 9, 108, 99, 109, 8, 110, 100, 111, 9, 112, 7, 113, 7, 114, 101, 115, 78, 116, 102, 0 </int_array>
<string> "variants" </string>
- <array len="105" shared="false">
- <node_path> "" </node_path>
+ <array len="103" shared="false">
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
<string> "2D" </string>
@@ -166,7 +149,7 @@
<string> "2D" </string>
<dictionary shared="false">
<string> "ofs" </string>
- <vector2> 328.379, 822.226 </vector2>
+ <vector2> -70.6559, 735.599 </vector2>
<string> "snap_grid" </string>
<bool> False </bool>
<string> "snap_offset" </string>
@@ -186,7 +169,7 @@
<string> "snap_step" </string>
<vector2> 10, 10 </vector2>
<string> "zoom" </string>
- <real> 1.108032 </real>
+ <real> 0.663419 </real>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
@@ -280,18 +263,6 @@
<string> "znear" </string>
<real> 0.1 </real>
</dictionary>
- <string> "Script" </string>
- <dictionary shared="false">
- <string> "current" </string>
- <int> 0 </int>
- <string> "sources" </string>
- <array len="4" shared="false">
- <string> "res://moving_platform.gd" </string>
- <string> "res://enemy.gd" </string>
- <string> "res://player.gd" </string>
- <string> "res://coin.gd" </string>
- </array>
- </dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
<dictionary shared="false">
@@ -301,12 +272,6 @@
<int> 0 </int>
</dictionary>
</dictionary>
- <bool> True </bool>
- <real> 1 </real>
- <int> 1 </int>
- <vector2> 0, 0 </vector2>
- <real> 0 </real>
- <vector2> 1, 1 </vector2>
<int> 0 </int>
<resource resource_type="TileSet" path="res://tileset.xml"> </resource>
<vector2> 64, 64 </vector2>
@@ -314,12 +279,16 @@
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
<int> 2 </int>
<bool> False </bool>
+ <real> 1 </real>
+ <real> 0 </real>
+ <int> 1 </int>
<int_array len="2008"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 0, 983052, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870914, 1048587, 536870922, 1048588, 2, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114122, 536870925, 1114123, 11, 1114124, 13, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179663, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 0, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array>
<dictionary shared="false">
<string> "_edit_lock_" </string>
<bool> True </bool>
</dictionary>
<resource resource_type="PackedScene" path="res://coin.xml"> </resource>
+ <node_path> "" </node_path>
<vector2> 672, 1179 </vector2>
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
@@ -957,6 +926,7 @@
</dictionary>
</dictionary>
<resource resource_type="AudioStream" path="res://music.ogg"> </resource>
+ <bool> True </bool>
<real> 2 </real>
<resource resource_type="PackedScene" path="res://enemy.xml"> </resource>
<vector2> 834.664, 1309.6 </vector2>
diff --git a/drivers/chibi/event_stream_chibi.cpp b/drivers/chibi/event_stream_chibi.cpp
index e87e0a9aaa..ecb5c3f22b 100644
--- a/drivers/chibi/event_stream_chibi.cpp
+++ b/drivers/chibi/event_stream_chibi.cpp
@@ -779,8 +779,10 @@ EventStreamChibi::EventStreamChibi() {
-RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderChibi::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
String el = p_path.extension().to_lower();
CPFileAccessWrapperImpl f;
@@ -791,6 +793,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
CPLoader_IT loader(&f);
CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false);
ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+ if (r_error)
+ *r_error=OK;
return esc;
@@ -800,6 +804,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
CPLoader_XM loader(&f);
CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+ if (r_error)
+ *r_error=OK;
return esc;
} else if (el=="s3m") {
@@ -808,6 +814,9 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
CPLoader_S3M loader(&f);
CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+ if (r_error)
+ *r_error=OK;
+
return esc;
} else if (el=="mod") {
@@ -816,6 +825,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
CPLoader_MOD loader(&f);
CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+ if (r_error)
+ *r_error=OK;
return esc;
}
diff --git a/drivers/chibi/event_stream_chibi.h b/drivers/chibi/event_stream_chibi.h
index 7b2ee4b471..b564c16018 100644
--- a/drivers/chibi/event_stream_chibi.h
+++ b/drivers/chibi/event_stream_chibi.h
@@ -301,7 +301,7 @@ public:
class ResourceFormatLoaderChibi : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/convex_decomp/b2Glue.h b/drivers/convex_decomp/b2Glue.h
index db765f7eb9..7ec6d7f181 100644
--- a/drivers/convex_decomp/b2Glue.h
+++ b/drivers/convex_decomp/b2Glue.h
@@ -20,7 +20,8 @@
#define B2GLUE_H
#include "math_2d.h"
-#include <limits>
+#include <limits.h>
+
namespace b2ConvexDecomp {
typedef real_t float32;
diff --git a/drivers/convex_decomp/b2Polygon.cpp b/drivers/convex_decomp/b2Polygon.cpp
index 668313967e..775f2adfe2 100644
--- a/drivers/convex_decomp/b2Polygon.cpp
+++ b/drivers/convex_decomp/b2Polygon.cpp
@@ -21,8 +21,8 @@
#include "b2Triangle.h"
#include "b2Polygon.h"
-#include <cmath>
-#include <climits>
+#include <math.h>
+#include <limits.h>
#include <assert.h>
#define b2Assert assert
diff --git a/drivers/convex_decomp/b2Polygon.h b/drivers/convex_decomp/b2Polygon.h
index 82cdc56804..36af2fd9d0 100644
--- a/drivers/convex_decomp/b2Polygon.h
+++ b/drivers/convex_decomp/b2Polygon.h
@@ -22,7 +22,7 @@
#include "b2Triangle.h"
#include "stdio.h"
#include <string.h>
-#include <limits>
+#include <limits.h>
namespace b2ConvexDecomp {
static bool B2_POLYGON_REPORT_ERRORS = false;
diff --git a/drivers/dds/texture_loader_dds.cpp b/drivers/dds/texture_loader_dds.cpp
index 8e6c3b62e6..9b2e401fd9 100644
--- a/drivers/dds/texture_loader_dds.cpp
+++ b/drivers/dds/texture_loader_dds.cpp
@@ -64,8 +64,10 @@ static const DDSFormatInfo dds_format_info[DDS_MAX]={
};
-RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
Error err;
FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -73,6 +75,8 @@ RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path)
return RES();
FileAccessRef fref(f);
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
ERR_EXPLAIN("Unable to open DDS texture file: "+p_path);
ERR_FAIL_COND_V(err!=OK,RES());
@@ -427,6 +431,10 @@ RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path)
Ref<ImageTexture> texture = memnew( ImageTexture );
texture->create_from_image(img);
+ if (r_error)
+ *r_error=OK;
+
+
return texture;
}
diff --git a/drivers/dds/texture_loader_dds.h b/drivers/dds/texture_loader_dds.h
index 18a1485073..c8b3610063 100644
--- a/drivers/dds/texture_loader_dds.h
+++ b/drivers/dds/texture_loader_dds.h
@@ -7,7 +7,7 @@
class ResourceFormatDDS : public ResourceFormatLoader{
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index d3a5f3b5bc..ebe0c61967 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -11188,6 +11188,12 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
tc0_idx=0;
};
+void RasterizerGLES2::restore_framebuffer() {
+
+ glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
+
+}
+
RasterizerGLES2::~RasterizerGLES2() {
memdelete_arr(skinned_buffer);
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index d337ecfb64..f759e84b53 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -1695,6 +1695,8 @@ public:
void reload_vram();
virtual bool has_feature(VS::Features p_feature) const;
+
+ virtual void restore_framebuffer();
static RasterizerGLES2* get_singleton();
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 157f2e398b..d57512c936 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -132,18 +132,18 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
SL::BlockNode *bnode=(SL::BlockNode*)p_node;
//variables
- code+="{"ENDL;
+ code+="{" ENDL;
for(Map<StringName,SL::DataType>::Element *E=bnode->variables.front();E;E=E->next()) {
- code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";"ENDL;
+ code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";" ENDL;
}
for(int i=0;i<bnode->statements.size();i++) {
- code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";"ENDL;
+ code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";" ENDL;
}
- code+="}"ENDL;
+ code+="}" ENDL;
} break;
case SL::Node::TYPE_VARIABLE: {
@@ -489,15 +489,15 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node;
if (cfnode->flow_op==SL::FLOW_OP_IF) {
- code+="if ("+dump_node_code(cfnode->statements[0],p_level)+") {"ENDL;
+ code+="if ("+dump_node_code(cfnode->statements[0],p_level)+") {" ENDL;
code+=dump_node_code(cfnode->statements[1],p_level+1);
if (cfnode->statements.size()==3) {
- code+="} else {"ENDL;
+ code+="} else {" ENDL;
code+=dump_node_code(cfnode->statements[2],p_level+1);
}
- code+="}"ENDL;
+ code+="}" ENDL;
} else if (cfnode->flow_op==SL::FLOW_OP_RETURN) {
@@ -560,7 +560,7 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) {
ubase=uniforms->size();
for(Map<StringName,SL::Uniform>::Element *E=p_program->uniforms.front();E;E=E->next()) {
- String uline="uniform "+_typestr(E->get().type)+" _"+E->key().operator String()+";"ENDL;
+ String uline="uniform "+_typestr(E->get().type)+" _"+E->key().operator String()+";" ENDL;
global_code+=uline;
if (uniforms) {
@@ -593,10 +593,10 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) {
header+=_typestr(fnode->arguments[i].type)+" "+replace_string(fnode->arguments[i].name);
}
- header+=") {"ENDL;
+ header+=") {" ENDL;
String fcode=header;
fcode+=dump_node_code(fnode->body,1);
- fcode+="}"ENDL;
+ fcode+="}" ENDL;
global_code+=fcode;
}
@@ -605,7 +605,7 @@ Error ShaderCompilerGLES2::compile_node(SL::ProgramNode *p_program) {
StringName varname=E->key();
String newvarname=replace_string(varname);
- global_code+="uniform "+_typestr(E->get())+" "+newvarname+";"ENDL;
+ global_code+="uniform "+_typestr(E->get())+" "+newvarname+";" ENDL;
}*/
code=dump_node_code(p_program,0);
diff --git a/drivers/mpc/audio_stream_mpc.cpp b/drivers/mpc/audio_stream_mpc.cpp
index cd8125c9af..fe6aa05d00 100644
--- a/drivers/mpc/audio_stream_mpc.cpp
+++ b/drivers/mpc/audio_stream_mpc.cpp
@@ -1,7 +1,7 @@
#include "audio_stream_mpc.h"
-Error AudioStreamMPC::_open_file() {
+Error AudioStreamPlaybackMPC::_open_file() {
if (f) {
memdelete(f);
@@ -41,7 +41,7 @@ Error AudioStreamMPC::_open_file() {
return OK;
}
-void AudioStreamMPC::_close_file() {
+void AudioStreamPlaybackMPC::_close_file() {
if (f) {
memdelete(f);
@@ -52,7 +52,7 @@ void AudioStreamMPC::_close_file() {
data_ofs=0;
}
-int AudioStreamMPC::_read_file(void *p_dst,int p_bytes) {
+int AudioStreamPlaybackMPC::_read_file(void *p_dst,int p_bytes) {
if (f)
return f->get_buffer((uint8_t*)p_dst,p_bytes);
@@ -68,7 +68,7 @@ int AudioStreamMPC::_read_file(void *p_dst,int p_bytes) {
return p_bytes;
}
-bool AudioStreamMPC::_seek_file(int p_pos){
+bool AudioStreamPlaybackMPC::_seek_file(int p_pos){
if (p_pos<0 || p_pos>streamlen)
return false;
@@ -83,7 +83,7 @@ bool AudioStreamMPC::_seek_file(int p_pos){
return true;
}
-int AudioStreamMPC::_tell_file() const{
+int AudioStreamPlaybackMPC::_tell_file() const{
if (f)
return f->get_pos();
@@ -93,13 +93,13 @@ int AudioStreamMPC::_tell_file() const{
}
-int AudioStreamMPC::_sizeof_file() const{
+int AudioStreamPlaybackMPC::_sizeof_file() const{
//print_line("sizeof file, get: "+itos(streamlen));
return streamlen;
}
-bool AudioStreamMPC::_canseek_file() const{
+bool AudioStreamPlaybackMPC::_canseek_file() const{
//print_line("canseek file, get true");
return true;
@@ -107,51 +107,46 @@ bool AudioStreamMPC::_canseek_file() const{
/////////////////////
-mpc_int32_t AudioStreamMPC::_mpc_read(mpc_reader *p_reader,void *p_dst, mpc_int32_t p_bytes) {
+mpc_int32_t AudioStreamPlaybackMPC::_mpc_read(mpc_reader *p_reader,void *p_dst, mpc_int32_t p_bytes) {
- AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data;
+ AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data;
return smpc->_read_file(p_dst,p_bytes);
}
-mpc_bool_t AudioStreamMPC::_mpc_seek(mpc_reader *p_reader,mpc_int32_t p_offset) {
+mpc_bool_t AudioStreamPlaybackMPC::_mpc_seek(mpc_reader *p_reader,mpc_int32_t p_offset) {
- AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data;
+ AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data;
return smpc->_seek_file(p_offset);
}
-mpc_int32_t AudioStreamMPC::_mpc_tell(mpc_reader *p_reader) {
+mpc_int32_t AudioStreamPlaybackMPC::_mpc_tell(mpc_reader *p_reader) {
- AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data;
+ AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data;
return smpc->_tell_file();
}
-mpc_int32_t AudioStreamMPC::_mpc_get_size(mpc_reader *p_reader) {
+mpc_int32_t AudioStreamPlaybackMPC::_mpc_get_size(mpc_reader *p_reader) {
- AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data;
+ AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data;
return smpc->_sizeof_file();
}
-mpc_bool_t AudioStreamMPC::_mpc_canseek(mpc_reader *p_reader) {
+mpc_bool_t AudioStreamPlaybackMPC::_mpc_canseek(mpc_reader *p_reader) {
- AudioStreamMPC *smpc=(AudioStreamMPC *)p_reader->data;
+ AudioStreamPlaybackMPC *smpc=(AudioStreamPlaybackMPC *)p_reader->data;
return smpc->_canseek_file();
}
-bool AudioStreamMPC::_can_mix() const {
- return /*active &&*/ !paused;
-}
-
-
-void AudioStreamMPC::update() {
+int AudioStreamPlaybackMPC::mix(int16_t* p_bufer,int p_frames) {
if (!active || paused)
- return;
+ return 0;
- int todo=get_todo();
+ int todo=p_frames;
while(todo>MPC_DECODER_BUFFER_LENGTH/si.channels) {
@@ -162,7 +157,7 @@ void AudioStreamMPC::update() {
mpc_status err = mpc_demux_decode(demux, &frame);
if (frame.bits!=-1) {
- int16_t *dst_buff = get_write_buffer();
+ int16_t *dst_buff = p_bufer;
#ifdef MPC_FIXED_POINT
@@ -185,21 +180,21 @@ void AudioStreamMPC::update() {
#endif
int frames = frame.samples;
- write(frames);
+ p_bufer+=si.channels*frames;
todo-=frames;
} else {
if (err != MPC_STATUS_OK) {
stop();
- ERR_EXPLAIN("Error decoding MPC");
- ERR_FAIL();
+ ERR_PRINT("Error decoding MPC");
+ break;
} else {
//finished
if (!loop) {
stop();
- return;
+ break;
} else {
@@ -213,9 +208,11 @@ void AudioStreamMPC::update() {
}
}
}
+
+ return p_frames-todo;
}
-Error AudioStreamMPC::_reload() {
+Error AudioStreamPlaybackMPC::_reload() {
ERR_FAIL_COND_V(demux!=NULL, ERR_FILE_ALREADY_IN_USE);
@@ -224,30 +221,39 @@ Error AudioStreamMPC::_reload() {
demux = mpc_demux_init(&reader);
ERR_FAIL_COND_V(!demux,ERR_CANT_CREATE);
-
mpc_demux_get_info(demux, &si);
- _setup(si.channels,si.sample_freq,MPC_DECODER_BUFFER_LENGTH*2/si.channels);
return OK;
}
-void AudioStreamMPC::set_file(const String& p_file) {
+void AudioStreamPlaybackMPC::set_file(const String& p_file) {
file=p_file;
+ Error err = _open_file();
+ ERR_FAIL_COND(err!=OK);
+ demux = mpc_demux_init(&reader);
+ ERR_FAIL_COND(!demux);
+ mpc_demux_get_info(demux, &si);
+ stream_min_size=MPC_DECODER_BUFFER_LENGTH*2/si.channels;
+ stream_rate=si.sample_freq;
+ stream_channels=si.channels;
+
+ mpc_demux_exit(demux);
+ demux=NULL;
+ _close_file();
+
}
-String AudioStreamMPC::get_file() const {
+String AudioStreamPlaybackMPC::get_file() const {
return file;
}
-void AudioStreamMPC::play() {
-
+void AudioStreamPlaybackMPC::play(float p_offset) {
- _THREAD_SAFE_METHOD_
if (active)
stop();
@@ -262,9 +268,9 @@ void AudioStreamMPC::play() {
}
-void AudioStreamMPC::stop() {
+void AudioStreamPlaybackMPC::stop() {
+
- _THREAD_SAFE_METHOD_
if (!active)
return;
if (demux) {
@@ -275,70 +281,58 @@ void AudioStreamMPC::stop() {
active=false;
}
-bool AudioStreamMPC::is_playing() const {
+bool AudioStreamPlaybackMPC::is_playing() const {
- return active || (get_total() - get_todo() -1 > 0);
+ return active;
}
-void AudioStreamMPC::set_paused(bool p_paused) {
- paused=p_paused;
-}
-bool AudioStreamMPC::is_paused(bool p_paused) const {
-
- return paused;
-}
-
-void AudioStreamMPC::set_loop(bool p_enable) {
+void AudioStreamPlaybackMPC::set_loop(bool p_enable) {
loop=p_enable;
}
-bool AudioStreamMPC::has_loop() const {
+bool AudioStreamPlaybackMPC::has_loop() const {
return loop;
}
-float AudioStreamMPC::get_length() const {
+float AudioStreamPlaybackMPC::get_length() const {
return 0;
}
-String AudioStreamMPC::get_stream_name() const {
+String AudioStreamPlaybackMPC::get_stream_name() const {
return "";
}
-int AudioStreamMPC::get_loop_count() const {
+int AudioStreamPlaybackMPC::get_loop_count() const {
return 0;
}
-float AudioStreamMPC::get_pos() const {
+float AudioStreamPlaybackMPC::get_pos() const {
return 0;
}
-void AudioStreamMPC::seek_pos(float p_time) {
+void AudioStreamPlaybackMPC::seek_pos(float p_time) {
}
-AudioStream::UpdateMode AudioStreamMPC::get_update_mode() const {
- return UPDATE_THREAD;
-}
+void AudioStreamPlaybackMPC::_bind_methods() {
-void AudioStreamMPC::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_file","name"),&AudioStreamMPC::set_file);
- ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamMPC::get_file);
+ ObjectTypeDB::bind_method(_MD("set_file","name"),&AudioStreamPlaybackMPC::set_file);
+ ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamPlaybackMPC::get_file);
ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"mpc"), _SCS("set_file"), _SCS("get_file"));
}
-AudioStreamMPC::AudioStreamMPC() {
+AudioStreamPlaybackMPC::AudioStreamPlaybackMPC() {
- preload=true;
+ preload=false;
f=NULL;
streamlen=0;
data_ofs=0;
@@ -356,7 +350,7 @@ AudioStreamMPC::AudioStreamMPC() {
}
-AudioStreamMPC::~AudioStreamMPC() {
+AudioStreamPlaybackMPC::~AudioStreamPlaybackMPC() {
stop();
@@ -366,8 +360,9 @@ AudioStreamMPC::~AudioStreamMPC() {
-RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path,const String& p_original_path) {
-
+RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=OK; //streamed so it will always work..
AudioStreamMPC *mpc_stream = memnew(AudioStreamMPC);
mpc_stream->set_file(p_path);
return Ref<AudioStreamMPC>(mpc_stream);
diff --git a/drivers/mpc/audio_stream_mpc.h b/drivers/mpc/audio_stream_mpc.h
index fa949acd00..122d0d0bbb 100644
--- a/drivers/mpc/audio_stream_mpc.h
+++ b/drivers/mpc/audio_stream_mpc.h
@@ -1,18 +1,17 @@
#ifndef AUDIO_STREAM_MPC_H
#define AUDIO_STREAM_MPC_H
-#include "scene/resources/audio_stream_resampled.h"
+#include "scene/resources/audio_stream.h"
#include "os/file_access.h"
#include "mpc/mpcdec.h"
#include "os/thread_safe.h"
#include "io/resource_loader.h"
//#include "../libmpcdec/decoder.h"
//#include "../libmpcdec/internal.h"
-class AudioStreamMPC : public AudioStreamResampled {
- OBJ_TYPE( AudioStreamMPC, AudioStreamResampled );
+class AudioStreamPlaybackMPC : public AudioStreamPlayback {
- _THREAD_SAFE_CLASS_
+ OBJ_TYPE( AudioStreamPlaybackMPC, AudioStreamPlayback );
bool preload;
FileAccess *f;
@@ -39,7 +38,9 @@ class AudioStreamMPC : public AudioStreamResampled {
static mpc_int32_t _mpc_get_size(mpc_reader *p_reader);
static mpc_bool_t _mpc_canseek(mpc_reader *p_reader);
- virtual bool _can_mix() const ;
+ int stream_min_size;
+ int stream_rate;
+ int stream_channels;
protected:
Error _open_file();
@@ -59,12 +60,10 @@ public:
void set_file(const String& p_file);
String get_file() const;
- virtual void play();
+ virtual void play(float p_offset=0);
virtual void stop();
virtual bool is_playing() const;
- virtual void set_paused(bool p_paused);
- virtual bool is_paused(bool p_paused) const;
virtual void set_loop(bool p_enable);
virtual bool has_loop() const;
@@ -78,17 +77,39 @@ public:
virtual float get_pos() const;
virtual void seek_pos(float p_time);
- virtual UpdateMode get_update_mode() const;
- virtual void update();
+ virtual int get_channels() const { return stream_channels; }
+ virtual int get_mix_rate() const { return stream_rate; }
- AudioStreamMPC();
- ~AudioStreamMPC();
+ virtual int get_minimum_buffer_size() const { return stream_min_size; }
+ virtual int mix(int16_t* p_bufer,int p_frames);
+
+ virtual void set_loop_restart_time(float p_time) { }
+
+ AudioStreamPlaybackMPC();
+ ~AudioStreamPlaybackMPC();
};
+class AudioStreamMPC : public AudioStream {
+
+ OBJ_TYPE( AudioStreamMPC, AudioStream );
+
+ String file;
+public:
+
+ Ref<AudioStreamPlayback> instance_playback() {
+ Ref<AudioStreamPlaybackMPC> pb = memnew( AudioStreamPlaybackMPC );
+ pb->set_file(file);
+ return pb;
+ }
+
+ void set_file(const String& p_file) { file=p_file; }
+
+
+};
class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/pvr/texture_loader_pvr.cpp b/drivers/pvr/texture_loader_pvr.cpp
index 5268b953f4..eb67dad8cf 100644
--- a/drivers/pvr/texture_loader_pvr.cpp
+++ b/drivers/pvr/texture_loader_pvr.cpp
@@ -22,8 +22,10 @@ enum PVRFLags {
-RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path,Error *r_error) {
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
Error err;
FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -34,6 +36,8 @@ RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path)
ERR_FAIL_COND_V(err,RES());
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
uint32_t hsize = f->get_32();
@@ -135,6 +139,9 @@ RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path)
Ref<ImageTexture> texture = memnew( ImageTexture );
texture->create_from_image(image,tex_flags);
+ if (r_error)
+ *r_error=OK;
+
return texture;
}
diff --git a/drivers/pvr/texture_loader_pvr.h b/drivers/pvr/texture_loader_pvr.h
index ad86660aa1..735cb2b48b 100644
--- a/drivers/pvr/texture_loader_pvr.h
+++ b/drivers/pvr/texture_loader_pvr.h
@@ -9,7 +9,7 @@
class ResourceFormatPVR : public ResourceFormatLoader{
public:
- virtual RES load(const String &p_path,const String& p_original_path);
+ virtual RES load(const String &p_path,const String& p_original_path,Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/speex/audio_stream_speex.cpp b/drivers/speex/audio_stream_speex.cpp
index bcf4c515f8..2440969345 100644
--- a/drivers/speex/audio_stream_speex.cpp
+++ b/drivers/speex/audio_stream_speex.cpp
@@ -15,14 +15,15 @@ static _FORCE_INLINE_ uint16_t le_short(uint16_t s)
}
-void AudioStreamSpeex::update() {
+int AudioStreamPlaybackSpeex::mix(int16_t* p_buffer,int p_frames) {
+
+
- _THREAD_SAFE_METHOD_;
//printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs);
//printf("playing %i, paused %i\n", (int)playing, (int)paused);
if (!active || !playing || paused || !data.size())
- return;
+ return 0;
/*
if (read_ofs >= data.size()) {
@@ -35,12 +36,13 @@ void AudioStreamSpeex::update() {
};
*/
- int todo = get_todo();
+ int todo = p_frames;
if (todo < page_size) {
- return;
+ return 0;
};
- int eos = 0;
+ int eos = 0;
+ bool reloaded=false;
while (todo > page_size) {
@@ -92,7 +94,7 @@ void AudioStreamSpeex::update() {
for (int j=0;j!=nframes;j++)
{
- int16_t* out = get_write_buffer();
+ int16_t* out = p_buffer;
int ret;
/*Decode frame*/
@@ -120,7 +122,7 @@ void AudioStreamSpeex::update() {
/*Convert to short and save to output file*/
- for (int i=0;i<frame_size*get_channel_count();i++) {
+ for (int i=0;i<frame_size*stream_channels;i++) {
out[i]=le_short(out[i]);
}
@@ -149,7 +151,7 @@ void AudioStreamSpeex::update() {
}
- write(new_frame_size);
+ p_buffer+=new_frame_size*stream_channels;
todo-=new_frame_size;
}
}
@@ -175,6 +177,7 @@ void AudioStreamSpeex::update() {
if (loops) {
reload();
++loop_count;
+ //break;
} else {
playing=false;
unload();
@@ -183,18 +186,22 @@ void AudioStreamSpeex::update() {
}
};
};
+
+ return p_frames-todo;
};
-void AudioStreamSpeex::unload() {
+void AudioStreamPlaybackSpeex::unload() {
+
- _THREAD_SAFE_METHOD_
if (!active) return;
speex_bits_destroy(&bits);
if (st)
speex_decoder_destroy(st);
+
+ ogg_sync_clear(&oy);
active = false;
//data.resize(0);
st = NULL;
@@ -204,7 +211,7 @@ void AudioStreamSpeex::unload() {
loop_count = 0;
}
-void *AudioStreamSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) {
+void *AudioStreamPlaybackSpeex::process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers) {
void *st;
SpeexHeader *header;
@@ -276,9 +283,9 @@ void *AudioStreamSpeex::process_header(ogg_packet *op, int *frame_size, int *rat
-void AudioStreamSpeex::reload() {
+void AudioStreamPlaybackSpeex::reload() {
+
- _THREAD_SAFE_METHOD_
if (active)
unload();
@@ -359,8 +366,10 @@ void AudioStreamSpeex::reload() {
};
page_size = nframes * frame_size;
+ stream_srate=rate;
+ stream_channels=channels;
+ stream_minbuff_size=page_size;
- _setup(channels, rate,page_size);
} else if (packet_count==1)
{
@@ -374,23 +383,23 @@ void AudioStreamSpeex::reload() {
} while (packet_count <= extra_headers);
- active = true;
+ active=true;
}
-void AudioStreamSpeex::_bind_methods() {
+void AudioStreamPlaybackSpeex::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_file","file"),&AudioStreamSpeex::set_file);
- ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamSpeex::get_file);
+ //ObjectTypeDB::bind_method(_MD("set_file","file"),&AudioStreamPlaybackSpeex::set_file);
+// ObjectTypeDB::bind_method(_MD("get_file"),&AudioStreamPlaybackSpeex::get_file);
- ObjectTypeDB::bind_method(_MD("_set_bundled"),&AudioStreamSpeex::_set_bundled);
- ObjectTypeDB::bind_method(_MD("_get_bundled"),&AudioStreamSpeex::_get_bundled);
+ ObjectTypeDB::bind_method(_MD("_set_bundled"),&AudioStreamPlaybackSpeex::_set_bundled);
+ ObjectTypeDB::bind_method(_MD("_get_bundled"),&AudioStreamPlaybackSpeex::_get_bundled);
ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_BUNDLE),_SCS("_set_bundled"),_SCS("_get_bundled"));
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"*.spx"),_SCS("set_file"),_SCS("get_file"));
+ //ADD_PROPERTY( PropertyInfo(Variant::STRING,"file",PROPERTY_HINT_FILE,"*.spx"),_SCS("set_file"),_SCS("get_file"));
};
-void AudioStreamSpeex::_set_bundled(const Dictionary& dict) {
+void AudioStreamPlaybackSpeex::_set_bundled(const Dictionary& dict) {
ERR_FAIL_COND( !dict.has("filename"));
ERR_FAIL_COND( !dict.has("data"));
@@ -399,7 +408,7 @@ void AudioStreamSpeex::_set_bundled(const Dictionary& dict) {
data = dict["data"];
};
-Dictionary AudioStreamSpeex::_get_bundled() const {
+Dictionary AudioStreamPlaybackSpeex::_get_bundled() const {
Dictionary d;
d["filename"] = filename;
@@ -408,43 +417,17 @@ Dictionary AudioStreamSpeex::_get_bundled() const {
};
-String AudioStreamSpeex::get_file() const {
-
- return filename;
-};
-
-void AudioStreamSpeex::set_file(const String& p_file){
-
- if (filename == p_file)
- return;
-
- if (active) {
- unload();
- }
-
- if (p_file == "") {
- data.resize(0);
- return;
- };
-
- Error err;
- FileAccess* file = FileAccess::open(p_file, FileAccess::READ,&err);
- if (err != OK) {
- data.resize(0);
- };
- ERR_FAIL_COND(err != OK);
- filename = p_file;
- data.resize(file->get_len());
- int read = file->get_buffer(&data[0], data.size());
- memdelete(file);
+void AudioStreamPlaybackSpeex::set_data(const Vector<uint8_t>& p_data) {
+ data=p_data;
reload();
}
-void AudioStreamSpeex::play() {
- _THREAD_SAFE_METHOD_
+void AudioStreamPlaybackSpeex::play(float p_from_pos) {
+
+
reload();
if (!active)
@@ -452,85 +435,107 @@ void AudioStreamSpeex::play() {
playing = true;
}
-void AudioStreamSpeex::stop(){
+void AudioStreamPlaybackSpeex::stop(){
+
- _THREAD_SAFE_METHOD_
unload();
playing = false;
- _clear();
-}
-bool AudioStreamSpeex::is_playing() const{
- return _is_ready() && (playing || (get_total() - get_todo() -1 > 0));
}
+bool AudioStreamPlaybackSpeex::is_playing() const{
-void AudioStreamSpeex::set_paused(bool p_paused){
-
- playing = !p_paused;
- paused = p_paused;
+ return playing;
}
-bool AudioStreamSpeex::is_paused(bool p_paused) const{
- return paused;
-}
-void AudioStreamSpeex::set_loop(bool p_enable){
+void AudioStreamPlaybackSpeex::set_loop(bool p_enable){
loops = p_enable;
}
-bool AudioStreamSpeex::has_loop() const{
+bool AudioStreamPlaybackSpeex::has_loop() const{
return loops;
}
-float AudioStreamSpeex::get_length() const{
+float AudioStreamPlaybackSpeex::get_length() const{
return 0;
}
-String AudioStreamSpeex::get_stream_name() const{
+String AudioStreamPlaybackSpeex::get_stream_name() const{
return "";
}
-int AudioStreamSpeex::get_loop_count() const{
+int AudioStreamPlaybackSpeex::get_loop_count() const{
return 0;
}
-float AudioStreamSpeex::get_pos() const{
+float AudioStreamPlaybackSpeex::get_pos() const{
return 0;
}
-void AudioStreamSpeex::seek_pos(float p_time){
+void AudioStreamPlaybackSpeex::seek_pos(float p_time){
};
-bool AudioStreamSpeex::_can_mix() const {
- //return playing;
- return data.size() != 0;
-};
+AudioStreamPlaybackSpeex::AudioStreamPlaybackSpeex() {
-AudioStream::UpdateMode AudioStreamSpeex::get_update_mode() const {
+ active=false;
+ st = NULL;
+ stream_channels=1;
+ stream_srate=1;
+ stream_minbuff_size=1;
- return UPDATE_THREAD;
}
-AudioStreamSpeex::AudioStreamSpeex() {
+AudioStreamPlaybackSpeex::~AudioStreamPlaybackSpeex() {
- active=false;
- st = NULL;
+ unload();
}
-AudioStreamSpeex::~AudioStreamSpeex() {
- unload();
+
+
+
+////////////////////////////////////////
+
+
+
+void AudioStreamSpeex::set_file(const String& p_file) {
+
+ if (this->file == p_file)
+ return;
+
+ this->file=p_file;
+
+ if (p_file == "") {
+ data.resize(0);
+ return;
+ };
+
+ Error err;
+ FileAccess* file = FileAccess::open(p_file, FileAccess::READ,&err);
+ if (err != OK) {
+ data.resize(0);
+ };
+ ERR_FAIL_COND(err != OK);
+
+ this->file = p_file;
+ data.resize(file->get_len());
+ int read = file->get_buffer(&data[0], data.size());
+ memdelete(file);
+
}
-RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=OK;
AudioStreamSpeex *stream = memnew(AudioStreamSpeex);
stream->set_file(p_path);
diff --git a/drivers/speex/audio_stream_speex.h b/drivers/speex/audio_stream_speex.h
index 9557ebe0b8..570e846734 100644
--- a/drivers/speex/audio_stream_speex.h
+++ b/drivers/speex/audio_stream_speex.h
@@ -1,7 +1,7 @@
#ifndef AUDIO_STREAM_SPEEX_H
#define AUDIO_STREAM_SPEEX_H
-#include "scene/resources/audio_stream_resampled.h"
+#include "scene/resources/audio_stream.h"
#include "speex/speex.h"
#include "os/file_access.h"
#include "io/resource_loader.h"
@@ -14,10 +14,10 @@
#include <ogg/ogg.h>
-class AudioStreamSpeex : public AudioStreamResampled {
+class AudioStreamPlaybackSpeex : public AudioStreamPlayback {
+
+ OBJ_TYPE(AudioStreamPlaybackSpeex, AudioStreamPlayback);
- OBJ_TYPE(AudioStreamSpeex, AudioStreamResampled);
- _THREAD_SAFE_CLASS_
void *st;
SpeexBits bits;
@@ -45,6 +45,9 @@ class AudioStreamSpeex : public AudioStreamResampled {
ogg_int64_t page_granule, last_granule;
int skip_samples, page_nb_packets;
+ int stream_channels;
+ int stream_srate;
+ int stream_minbuff_size;
void* process_header(ogg_packet *op, int *frame_size, int *rate, int *nframes, int *channels, int *extra_headers);
@@ -52,7 +55,7 @@ class AudioStreamSpeex : public AudioStreamResampled {
protected:
- virtual bool _can_mix() const;
+ //virtual bool _can_mix() const;
Dictionary _get_bundled() const;
void _set_bundled(const Dictionary& dict);
@@ -60,16 +63,12 @@ protected:
public:
- void set_file(const String& p_file);
- String get_file() const;
+ void set_data(const Vector<uint8_t>& p_data);
- virtual void play();
+ virtual void play(float p_from_pos=0);
virtual void stop();
virtual bool is_playing() const;
- virtual void set_paused(bool p_paused);
- virtual bool is_paused(bool p_paused) const;
-
virtual void set_loop(bool p_enable);
virtual bool has_loop() const;
@@ -82,16 +81,42 @@ public:
virtual float get_pos() const;
virtual void seek_pos(float p_time);
- virtual UpdateMode get_update_mode() const;
- virtual void update();
+ virtual int get_channels() const { return stream_channels; }
+ virtual int get_mix_rate() const { return stream_srate; }
+
+ virtual int get_minimum_buffer_size() const { return stream_minbuff_size; }
+ virtual int mix(int16_t* p_bufer,int p_frames);
+
+ virtual void set_loop_restart_time(float p_time) { } //no loop restart, ignore
+
+ AudioStreamPlaybackSpeex();
+ ~AudioStreamPlaybackSpeex();
+};
+
+
+
+class AudioStreamSpeex : public AudioStream {
+
+ OBJ_TYPE(AudioStreamSpeex,AudioStream);
+
+ Vector<uint8_t> data;
+ String file;
+public:
+
+ Ref<AudioStreamPlayback> instance_playback() {
+ Ref<AudioStreamPlaybackSpeex> pb = memnew( AudioStreamPlaybackSpeex );
+ pb->set_data(data);
+ return pb;
+ }
+
+ void set_file(const String& p_file);
- AudioStreamSpeex();
- ~AudioStreamSpeex();
};
+
class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/theora/video_stream_theora.h b/drivers/theora/video_stream_theora.h
index b408f9db13..12aac731fc 100644
--- a/drivers/theora/video_stream_theora.h
+++ b/drivers/theora/video_stream_theora.h
@@ -102,7 +102,7 @@ public:
class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc b/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc
index f52bd95551..aac7390b32 100755
--- a/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc
+++ b/drivers/theoraplayer/src/YUV/libyuv/src/cpu_id.cc
@@ -174,7 +174,7 @@ int cpu_info_ = kCpuInit; // cpu_info is not initialized yet.
#if !defined(__native_client__) && !defined(_M_ARM)
static LIBYUV_BOOL TestEnv(const char* name) {
-#ifndef _WINRT
+#if !defined(_WINRT) && !defined(ORBIS_ENABLED)
const char* var = getenv(name);
if (var) {
if (var[0] != '0') {
diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp
index ef1f5651ab..876cac3425 100644
--- a/drivers/theoraplayer/video_stream_theoraplayer.cpp
+++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp
@@ -525,7 +525,9 @@ VideoStreamTheoraplayer::VideoStreamTheoraplayer() {
};
-RES ResourceFormatLoaderVideoStreamTheoraplayer::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderVideoStreamTheoraplayer::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=OK;
VideoStreamTheoraplayer *stream = memnew(VideoStreamTheoraplayer);
stream->set_file(p_path);
diff --git a/drivers/theoraplayer/video_stream_theoraplayer.h b/drivers/theoraplayer/video_stream_theoraplayer.h
index d43c12609f..69cae7c4a2 100644
--- a/drivers/theoraplayer/video_stream_theoraplayer.h
+++ b/drivers/theoraplayer/video_stream_theoraplayer.h
@@ -54,7 +54,7 @@ public:
class ResourceFormatLoaderVideoStreamTheoraplayer : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 76042089ff..8e70ecc932 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -63,7 +63,7 @@ Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) {
fclose(f);
f=NULL;
- String path=fix_path(p_path);
+ path=fix_path(p_path);
//printf("opening %ls, %i\n", path.c_str(), Memory::get_static_mem_usage());
ERR_FAIL_COND_V(f,ERR_ALREADY_IN_USE);
@@ -114,6 +114,9 @@ void FileAccessUnix::close() {
return;
fclose(f);
f = NULL;
+ if (close_notification_func) {
+ close_notification_func(path,flags);
+ }
if (save_path!="") {
//unlink(save_path.utf8().get_data());
@@ -240,6 +243,7 @@ FileAccess * FileAccessUnix::create_libc() {
return memnew( FileAccessUnix );
}
+CloseNotificationFunc FileAccessUnix::close_notification_func=NULL;
FileAccessUnix::FileAccessUnix() {
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 5b0f0e7cb7..6c41a51ec5 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -38,6 +38,10 @@
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
+
+typedef void (*CloseNotificationFunc)(const String& p_file,int p_flags);
+
class FileAccessUnix : public FileAccess {
FILE *f;
@@ -45,10 +49,13 @@ class FileAccessUnix : public FileAccess {
void check_errors() const;
mutable Error last_error;
String save_path;
+ String path;
- static FileAccess* create_libc();
+ static FileAccess* create_libc();
public:
+ static CloseNotificationFunc close_notification_func;
+
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 314e13cee4..96f90e6be1 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -226,8 +226,9 @@ uint64_t OS_Unix::get_unix_time() const {
uint64_t OS_Unix::get_system_time_msec() const {
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
- localtime(&tv_now.tv_usec);
- uint64_t msec = tv_now.tv_usec/1000;
+ //localtime(&tv_now.tv_usec);
+ //localtime((const long *)&tv_now.tv_usec);
+ uint64_t msec = uint64_t(tv_now.tv_sec)*1000+tv_now.tv_usec/1000;
return msec;
}
diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp
index 249059e2c1..ca055c8b62 100644
--- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp
@@ -30,7 +30,7 @@
-size_t AudioStreamOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) {
+size_t AudioStreamPlaybackOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) {
//printf("read to %p, %i bytes, %i nmemb, %p\n",p_dst,p_data,p_count,_f);
FileAccess *fa=(FileAccess*)_f;
@@ -46,7 +46,7 @@ size_t AudioStreamOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_c
return read;
}
-int AudioStreamOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) {
+int AudioStreamPlaybackOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) {
//printf("seek to %p, offs %i, whence %i\n",_f,(int)offs,whence);
@@ -76,7 +76,7 @@ int AudioStreamOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) {
#endif
}
-int AudioStreamOGGVorbis::_ov_close_func(void *_f) {
+int AudioStreamPlaybackOGGVorbis::_ov_close_func(void *_f) {
// printf("close %p\n",_f);
if (!_f)
@@ -86,7 +86,7 @@ int AudioStreamOGGVorbis::_ov_close_func(void *_f) {
fa->close();
return 0;
}
-long AudioStreamOGGVorbis::_ov_tell_func(void *_f) {
+long AudioStreamPlaybackOGGVorbis::_ov_tell_func(void *_f) {
//printf("close %p\n",_f);
@@ -95,38 +95,32 @@ long AudioStreamOGGVorbis::_ov_tell_func(void *_f) {
}
-bool AudioStreamOGGVorbis::_can_mix() const {
- return /*playing &&*/ !paused;
-}
-
-
-void AudioStreamOGGVorbis::update() {
+int AudioStreamPlaybackOGGVorbis::mix(int16_t* p_bufer,int p_frames) {
- _THREAD_SAFE_METHOD_
-
- if (!playing && !setting_up)
- return;
+ if (!playing)
+ return 0;
+ int total=p_frames;
while (true) {
- int todo = get_todo();
+ int todo = p_frames;
- if (todo==0 || todo<MIN_MIX)
+ if (todo==0 || todo<MIN_MIX) {
break;
+ }
//printf("to mix %i - mix me %i bytes\n",to_mix,to_mix*stream_channels*sizeof(int16_t));
#ifdef BIG_ENDIAN_ENABLED
- long ret=ov_read(&vf,(char*)get_write_buffer(),todo*stream_channels*sizeof(int16_t), 1, 2, 1, &current_section);
+ long ret=ov_read(&vf,(char*)p_bufer,todo*stream_channels*sizeof(int16_t), 1, 2, 1, &current_section);
#else
- long ret=ov_read(&vf,(char*)get_write_buffer(),todo*stream_channels*sizeof(int16_t), 0, 2, 1, &current_section);
+ long ret=ov_read(&vf,(char*)p_bufer,todo*stream_channels*sizeof(int16_t), 0, 2, 1, &current_section);
#endif
+
if (ret<0) {
playing = false;
- setting_up=false;
-
ERR_EXPLAIN("Error reading OGG Vorbis File: "+file);
ERR_BREAK(ret<0);
} else if (ret==0) { // end of song, reload?
@@ -138,9 +132,8 @@ void AudioStreamOGGVorbis::update() {
if (!has_loop()) {
playing=false;
- setting_up=false;
repeats=1;
- return;
+ break;
}
f=FileAccess::open(file,FileAccess::READ);
@@ -148,11 +141,22 @@ void AudioStreamOGGVorbis::update() {
int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks);
if (errv!=0) {
playing=false;
- setting_up=false;
- return; // :(
+ break;; // :(
}
- frames_mixed=0;
+ if (loop_restart_time) {
+ bool ok = ov_time_seek(&vf,loop_restart_time)==0;
+ if (!ok) {
+ playing=false;
+ //ERR_EXPLAIN("loop restart time rejected");
+ ERR_PRINT("loop restart time rejected")
+ }
+
+ frames_mixed=stream_srate*loop_restart_time;
+ } else {
+
+ frames_mixed=0;
+ }
repeats++;
continue;
@@ -162,16 +166,19 @@ void AudioStreamOGGVorbis::update() {
ret/=sizeof(int16_t);
frames_mixed+=ret;
- write(ret);
+
+ p_bufer+=ret*stream_channels;
+ p_frames-=ret;
+
}
-}
+ return total-p_frames;
+}
-void AudioStreamOGGVorbis::play() {
- _THREAD_SAFE_METHOD_
+void AudioStreamPlaybackOGGVorbis::play(float p_from) {
if (playing)
stop();
@@ -179,56 +186,46 @@ void AudioStreamOGGVorbis::play() {
if (_load_stream()!=OK)
return;
+
frames_mixed=0;
- playing=false;
- setting_up=true;
- update();
- if (!setting_up)
- return;
- setting_up=false;
playing=true;
+ if (p_from>0) {
+ seek_pos(p_from);
+ }
}
-void AudioStreamOGGVorbis::_close_file() {
+void AudioStreamPlaybackOGGVorbis::_close_file() {
if (f) {
+
memdelete(f);
f=NULL;
}
}
-void AudioStreamOGGVorbis::stop() {
-
- _THREAD_SAFE_METHOD_
+bool AudioStreamPlaybackOGGVorbis::is_playing() const {
+ return playing;
+}
+void AudioStreamPlaybackOGGVorbis::stop() {
_clear_stream();
playing=false;
- _clear();
-}
-
-AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const {
-
- return UPDATE_THREAD;
+ //_clear();
}
-bool AudioStreamOGGVorbis::is_playing() const {
+float AudioStreamPlaybackOGGVorbis::get_pos() const {
- return playing || (get_total() - get_todo() -1 > 0);
-}
-
-float AudioStreamOGGVorbis::get_pos() const {
-
- int32_t frames = int32_t(frames_mixed) - (int32_t(get_total()) - get_todo());
+ int32_t frames = int32_t(frames_mixed);
if (frames < 0)
frames=0;
return double(frames) / stream_srate;
}
-void AudioStreamOGGVorbis::seek_pos(float p_time) {
+void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) {
+
- _THREAD_SAFE_METHOD_
if (!playing)
return;
@@ -237,85 +234,107 @@ void AudioStreamOGGVorbis::seek_pos(float p_time) {
frames_mixed=stream_srate*p_time;
}
-String AudioStreamOGGVorbis::get_stream_name() const {
+String AudioStreamPlaybackOGGVorbis::get_stream_name() const {
return "";
}
-void AudioStreamOGGVorbis::set_loop(bool p_enable) {
+void AudioStreamPlaybackOGGVorbis::set_loop(bool p_enable) {
loops=p_enable;
}
-bool AudioStreamOGGVorbis::has_loop() const {
+bool AudioStreamPlaybackOGGVorbis::has_loop() const {
return loops;
}
-int AudioStreamOGGVorbis::get_loop_count() const {
+int AudioStreamPlaybackOGGVorbis::get_loop_count() const {
return repeats;
}
-void AudioStreamOGGVorbis::set_file(const String& p_file) {
+Error AudioStreamPlaybackOGGVorbis::set_file(const String& p_file) {
file=p_file;
-}
-
-Error AudioStreamOGGVorbis::_load_stream() {
-
- _clear_stream();
- if (file=="")
- return ERR_INVALID_DATA;
-
+ stream_valid=false;
Error err;
f=FileAccess::open(file,FileAccess::READ,&err);
-
if (err) {
ERR_FAIL_COND_V( err, err );
}
int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks);
+ switch(errv) {
-
+ case OV_EREAD: { // - A read from media returned an error.
+ memdelete(f); f=NULL;
+ ERR_FAIL_V( ERR_FILE_CANT_READ );
+ } break;
+ case OV_EVERSION: // - Vorbis version mismatch.
+ case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data.
+ memdelete(f); f=NULL;
+ ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
+ } break;
+ case OV_EBADHEADER: { // - Invalid Vorbis bitstream header.
+ memdelete(f); f=NULL;
+ ERR_FAIL_V( ERR_FILE_CORRUPT );
+ } break;
+ case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption.
+ memdelete(f); f=NULL;
+ ERR_FAIL_V( ERR_BUG );
+ } break;
+ }
const vorbis_info *vinfo=ov_info(&vf,-1);
stream_channels=vinfo->channels;
stream_srate=vinfo->rate;
- Error serr = _setup(stream_channels,stream_srate);
+ ogg_int64_t len = ov_time_total(&vf,-1);
+ length=len/1000.0;
+ ov_clear(&vf);
+ memdelete(f);
+ f=NULL;
+ stream_valid=true;
+
+
+ return OK;
+}
+
+Error AudioStreamPlaybackOGGVorbis::_load_stream() {
+
+ ERR_FAIL_COND_V(!stream_valid,ERR_UNCONFIGURED);
- if (serr) {
- _close_file();
- ERR_FAIL_V( ERR_INVALID_DATA );
+ _clear_stream();
+ if (file=="")
+ return ERR_INVALID_DATA;
+
+ Error err;
+ f=FileAccess::open(file,FileAccess::READ,&err);
+ if (err) {
+ ERR_FAIL_COND_V( err, err );
}
+ int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks);
switch(errv) {
case OV_EREAD: { // - A read from media returned an error.
- _close_file();
+ memdelete(f); f=NULL;
ERR_FAIL_V( ERR_FILE_CANT_READ );
} break;
case OV_EVERSION: // - Vorbis version mismatch.
case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data.
- _close_file();
+ memdelete(f); f=NULL;
ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
} break;
case OV_EBADHEADER: { // - Invalid Vorbis bitstream header.
- _close_file();
+ memdelete(f); f=NULL;
ERR_FAIL_V( ERR_FILE_CORRUPT );
} break;
case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption.
-
- _close_file();
+ memdelete(f); f=NULL;
ERR_FAIL_V( ERR_BUG );
} break;
}
-
-
- ogg_int64_t len = ov_time_total(&vf,-1);
-
- length=len/1000.0;
-
repeats=0;
stream_loaded=true;
@@ -324,16 +343,16 @@ Error AudioStreamOGGVorbis::_load_stream() {
}
-float AudioStreamOGGVorbis::get_length() const {
+float AudioStreamPlaybackOGGVorbis::get_length() const {
if (!stream_loaded) {
- if (const_cast<AudioStreamOGGVorbis*>(this)->_load_stream()!=OK)
+ if (const_cast<AudioStreamPlaybackOGGVorbis*>(this)->_load_stream()!=OK)
return 0;
}
return length;
}
-void AudioStreamOGGVorbis::_clear_stream() {
+void AudioStreamPlaybackOGGVorbis::_clear_stream() {
if (!stream_loaded)
return;
@@ -346,18 +365,18 @@ void AudioStreamOGGVorbis::_clear_stream() {
playing=false;
}
-void AudioStreamOGGVorbis::set_paused(bool p_paused) {
+void AudioStreamPlaybackOGGVorbis::set_paused(bool p_paused) {
paused=p_paused;
}
-bool AudioStreamOGGVorbis::is_paused(bool p_paused) const {
+bool AudioStreamPlaybackOGGVorbis::is_paused(bool p_paused) const {
return paused;
}
-AudioStreamOGGVorbis::AudioStreamOGGVorbis() {
+AudioStreamPlaybackOGGVorbis::AudioStreamPlaybackOGGVorbis() {
loops=false;
playing=false;
@@ -367,17 +386,18 @@ AudioStreamOGGVorbis::AudioStreamOGGVorbis() {
_ov_callbacks.tell_func=_ov_tell_func;
f = NULL;
stream_loaded=false;
- repeats=0;
- setting_up=false;
+ stream_valid=false;
+ repeats=0;
paused=true;
stream_channels=0;
stream_srate=0;
current_section=0;
length=0;
+ loop_restart_time=0;
}
-AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {
+AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() {
_clear_stream();
@@ -385,7 +405,9 @@ AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {
-RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=OK;
AudioStreamOGGVorbis *ogg_stream = memnew(AudioStreamOGGVorbis);
ogg_stream->set_file(p_path);
diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h
index 8a35fc09cb..827d8b0be3 100644
--- a/drivers/vorbis/audio_stream_ogg_vorbis.h
+++ b/drivers/vorbis/audio_stream_ogg_vorbis.h
@@ -29,17 +29,16 @@
#ifndef AUDIO_STREAM_OGG_VORBIS_H
#define AUDIO_STREAM_OGG_VORBIS_H
-#include "scene/resources/audio_stream_resampled.h"
+#include "scene/resources/audio_stream.h"
#include "vorbis/vorbisfile.h"
#include "os/file_access.h"
#include "io/resource_loader.h"
#include "os/thread_safe.h"
-class AudioStreamOGGVorbis : public AudioStreamResampled {
- OBJ_TYPE(AudioStreamOGGVorbis,AudioStreamResampled);
- _THREAD_SAFE_CLASS_
+class AudioStreamPlaybackOGGVorbis : public AudioStreamPlayback {
+ OBJ_TYPE(AudioStreamPlaybackOGGVorbis,AudioStreamPlayback);
enum {
MIN_MIX=1024
@@ -54,9 +53,6 @@ class AudioStreamOGGVorbis : public AudioStreamResampled {
static int _ov_close_func(void *_f);
static long _ov_tell_func(void *_f);
-
- virtual bool _can_mix() const;
-
String file;
int64_t frames_mixed;
@@ -67,7 +63,7 @@ class AudioStreamOGGVorbis : public AudioStreamResampled {
int stream_srate;
int current_section;
- volatile bool setting_up;
+
bool paused;
bool loops;
int repeats;
@@ -76,17 +72,21 @@ class AudioStreamOGGVorbis : public AudioStreamResampled {
void _clear_stream();
void _close_file();
+ bool stream_valid;
+ float loop_restart_time;
-public:
+public:
- void set_file(const String& p_file);
+ Error set_file(const String& p_file);
- virtual void play();
+ virtual void play(float p_from=0);
virtual void stop();
virtual bool is_playing() const;
+ virtual void set_loop_restart_time(float p_time) { loop_restart_time=0; }
+
virtual void set_paused(bool p_paused);
virtual bool is_paused(bool p_paused) const;
@@ -102,16 +102,37 @@ public:
virtual float get_pos() const;
virtual void seek_pos(float p_time);
- virtual UpdateMode get_update_mode() const;
- virtual void update();
+ virtual int get_channels() const { return stream_channels; }
+ virtual int get_mix_rate() const { return stream_srate; }
+
+ virtual int get_minimum_buffer_size() const { return 0; }
+ virtual int mix(int16_t* p_bufer,int p_frames);
+
+ AudioStreamPlaybackOGGVorbis();
+ ~AudioStreamPlaybackOGGVorbis();
+};
+
+
+class AudioStreamOGGVorbis : public AudioStream {
+
+ OBJ_TYPE(AudioStreamOGGVorbis,AudioStream);
+
+ String file;
+public:
+
+ Ref<AudioStreamPlayback> instance_playback() {
+ Ref<AudioStreamPlaybackOGGVorbis> pb = memnew( AudioStreamPlaybackOGGVorbis );
+ pb->set_file(file);
+ return pb;
+ }
+
+ void set_file(const String& p_file) { file=p_file; }
- AudioStreamOGGVorbis();
- ~AudioStreamOGGVorbis();
};
class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/main/main.cpp b/main/main.cpp
index 19ee1c115f..9b7e190e03 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -75,7 +75,7 @@
#include "core/io/file_access_zip.h"
#include "translation.h"
#include "version.h"
-
+#include "os/input.h"
#include "performance.h"
static Globals *globals=NULL;
@@ -94,11 +94,15 @@ static FileAccessNetworkClient *file_access_network_client=NULL;
static TranslationServer *translation_server = NULL;
static OS::VideoMode video_mode;
+static bool init_maximized=false;
+static bool init_fullscreen=false;
+static bool init_use_custom_pos=false;
+static Vector2 init_custom_pos;
static int video_driver_idx=-1;
static int audio_driver_idx=-1;
static String locale;
-static bool init_maximized=false;
+
static int init_screen=-1;
static String unescape_cmdline(const String& p_str) {
@@ -136,8 +140,10 @@ void Main::print_help(const char* p_binary) {
}
OS::get_singleton()->print(")\n");
- OS::get_singleton()->print("\t-r WIDTHxHEIGHT\t : Request Screen Resolution\n");
+ OS::get_singleton()->print("\t-r WIDTHxHEIGHT\t : Request Window Resolution\n");
+ OS::get_singleton()->print("\t-p XxY\t : Request Window Position\n");
OS::get_singleton()->print("\t-f\t\t : Request Fullscreen\n");
+ OS::get_singleton()->print("\t-mx\t\t Request Maximized\n");
OS::get_singleton()->print("\t-vd DRIVER\t : Video Driver (");
for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
@@ -287,6 +293,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
if (vm.find("x")==-1) { // invalid parameter format
+ OS::get_singleton()->print("Invalid -r argument: %s\n",vm.utf8().get_data());
goto error;
@@ -297,6 +304,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
if (w==0 || h==0) {
+ OS::get_singleton()->print("Invalid -r resolution, x and y must be >0\n");
goto error;
}
@@ -307,11 +315,43 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
N=I->next()->next();
} else {
+ OS::get_singleton()->print("Invalid -p argument, needs resolution\n");
goto error;
}
-
+ } else if (I->get()=="-p") { // position
+
+ if (I->next()) {
+
+ String vm=I->next()->get();
+
+ if (vm.find("x")==-1) { // invalid parameter format
+
+ OS::get_singleton()->print("Invalid -p argument: %s\n",vm.utf8().get_data());
+ goto error;
+
+
+ }
+
+ int x=vm.get_slice("x",0).to_int();
+ int y=vm.get_slice("x",1).to_int();
+
+ init_custom_pos=Point2(x,y);
+ init_use_custom_pos=true;
+
+ N=I->next()->next();
+ } else {
+ OS::get_singleton()->print("Invalid -r argument, needs position\n");
+ goto error;
+
+
+ }
+
+
+ } else if (I->get()=="-mx") { // video driver
+
+ init_maximized=true;
} else if (I->get()=="-vd") { // video driver
if (I->next()) {
@@ -319,6 +359,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
video_driver=I->next()->get();
N=I->next()->next();
} else {
+ OS::get_singleton()->print("Invalid -cd argument, needs driver name\n");
goto error;
}
@@ -329,6 +370,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
locale=I->next()->get();
N=I->next()->next();
} else {
+ OS::get_singleton()->print("Invalid -lang argument, needs language code\n");
goto error;
}
@@ -383,7 +425,8 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
} else if (I->get()=="-f") { // fullscreen
- video_mode.fullscreen=true;
+ //video_mode.fullscreen=false;
+ init_fullscreen=true;
} else if (I->get()=="-e" || I->get()=="-editor") { // fonud editor
editor=true;
@@ -406,7 +449,6 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
} else {
game_path=I->next()->get(); //use game_path instead
}
-
N=I->next()->next();
} else {
goto error;
@@ -487,8 +529,10 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
debug_mode="remote";
debug_host=I->next()->get();
- if (debug_host.find(":")==-1) //wrong host
+ if (debug_host.find(":")==-1) { //wrong host
+ OS::get_singleton()->print("Invalid debug host string\n");
goto error;
+ }
N=I->next()->next();
} else {
goto error;
@@ -732,6 +776,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
if (p_second_phase)
return setup2();
+
return OK;
error:
@@ -785,6 +830,14 @@ Error Main::setup2() {
OS::get_singleton()->initialize(video_mode,video_driver_idx,audio_driver_idx);
+ if (init_use_custom_pos) {
+ OS::get_singleton()->set_window_position(init_custom_pos);
+ }
+ if (init_maximized) {
+ OS::get_singleton()->set_window_maximized(true);
+ } else if (init_fullscreen) {
+ OS::get_singleton()->set_window_fullscreen(true);
+ }
register_core_singletons();
@@ -801,17 +854,29 @@ Error Main::setup2() {
if (init_maximized) {
OS::get_singleton()->set_window_maximized(true);
}
+ MAIN_PRINT("Main: Load Remaps");
+
+ path_remap->load_remaps();
if (show_logo) { //boot logo!
String boot_logo_path=GLOBAL_DEF("application/boot_splash",String());
bool boot_logo_scale=GLOBAL_DEF("application/boot_splash_fullsize",true);
Globals::get_singleton()->set_custom_property_info("application/boot_splash",PropertyInfo(Variant::STRING,"application/boot_splash",PROPERTY_HINT_FILE,"*.png"));
-
+ print_line("BOOT SPLASH: "+boot_logo_path);
Image boot_logo;
- if (boot_logo_path.strip_edges()!="" && FileAccess::exists(boot_logo_path)) {
- boot_logo.load(boot_logo_path);
+ boot_logo_path = boot_logo_path.strip_edges();
+ print_line("BOOT SPLASH IS : "+boot_logo_path);
+
+ if (boot_logo_path!=String() /*&& FileAccess::exists(boot_logo_path)*/) {
+ Error err = boot_logo.load(boot_logo_path);
+ if (err!=OK) {
+ print_line("ËRROR LOADING BOOT LOGO SPLASH :"+boot_logo_path);
+ } else {
+ print_line("BOOT SPLASH OK!");
+
+ }
}
if (!boot_logo.empty()) {
@@ -822,7 +887,7 @@ Error Main::setup2() {
VisualServer::get_singleton()->set_boot_image(boot_logo, boot_bg,boot_logo_scale);
#ifndef TOOLS_ENABLED
//no tools, so free the boot logo (no longer needed)
- Globals::get_singleton()->set("application/boot_logo",Image());
+ // Globals::get_singleton()->set("application/boot_logo",Image());
#endif
} else {
@@ -847,10 +912,16 @@ Error Main::setup2() {
GLOBAL_DEF("application/icon",String());
Globals::get_singleton()->set_custom_property_info("application/icon",PropertyInfo(Variant::STRING,"application/icon",PROPERTY_HINT_FILE,"*.png,*.webp"));
+ if (bool(GLOBAL_DEF("display/emulate_touchscreen",false))) {
+ if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
+ //only if no touchscreen ui hint, set emulation
+ InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
+ if (id)
+ id->set_emulate_touch(true);
+ }
+ }
MAIN_PRINT("Main: Load Remaps");
- path_remap->load_remaps();
-
MAIN_PRINT("Main: Load Scene Types");
register_scene_types();
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 7cb9882f3a..0d986e92a2 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -998,6 +998,44 @@ static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_l
return false;
}
+
+static bool _guess_identifier_from_assignment_in_function(GDCompletionContext& context,const StringName& p_identifier, const StringName& p_function,GDCompletionIdentifier &r_type) {
+
+ const GDParser::FunctionNode* func=NULL;
+ for(int i=0;i<context._class->functions.size();i++) {
+ if (context._class->functions[i]->name==p_function) {
+ func=context._class->functions[i];
+ break;
+ }
+ }
+
+ if (!func)
+ return false;
+
+ for(int i=0;i<func->body->statements.size();i++) {
+
+
+
+ if (func->body->statements[i]->type==GDParser::BlockNode::TYPE_OPERATOR) {
+ const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(func->body->statements[i]);
+ if (op->op==GDParser::OperatorNode::OP_ASSIGN) {
+
+ if (op->arguments.size() && op->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER) {
+
+ const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[0]);
+
+ if (id->name==p_identifier) {
+
+ return _guess_expression_type(context,op->arguments[1],func->body->statements[i]->line,r_type);
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) {
//go to block first
@@ -1089,8 +1127,22 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const
r_type=_get_type_from_pinfo(context._class->variables[i]._export);
return true;
} else if (context._class->variables[i].expression) {
- return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type);
+
+ bool rtype = _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type);
+ if (rtype && r_type.type!=Variant::NIL)
+ return true;
+ //return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type);
}
+
+ //try to guess from assignment in construtor or _ready
+ if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_ready",r_type))
+ return true;
+ if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_enter_tree",r_type))
+ return true;
+ if (_guess_identifier_from_assignment_in_function(context,p_identifier,"_init",r_type))
+ return true;
+
+ return false;
}
}
}
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index f7aaaf7ee5..9c39051b7f 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -170,6 +170,7 @@ void GDParser::_make_completable_call(int p_arg) {
completion_line=tokenizer->get_token_line();
completion_argument=p_arg;
completion_block=current_block;
+ completion_found=true;
tokenizer->advance();
}
@@ -190,6 +191,7 @@ bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& ide
completion_function=current_function;
completion_line=tokenizer->get_token_line();
completion_block=current_block;
+ completion_found=true;
tokenizer->advance();
if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) {
@@ -1414,6 +1416,24 @@ GDParser::Node* GDParser::_parse_and_reduce_expression(Node *p_parent,bool p_sta
return expr;
}
+bool GDParser::_recover_from_completion() {
+
+ if (!completion_found) {
+ return false; //can't recover if no completion
+ }
+ //skip stuff until newline
+ while(tokenizer->get_token()!=GDTokenizer::TK_NEWLINE && tokenizer->get_token()!=GDTokenizer::TK_EOF && tokenizer->get_token()!=GDTokenizer::TK_ERROR) {
+ tokenizer->advance();
+ }
+ completion_found=false;
+ error_set=false;
+ if(tokenizer->get_token() == GDTokenizer::TK_ERROR){
+ error_set = true;
+ }
+
+ return true;
+}
+
void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
int indent_level = tab_level.back()->get();
@@ -1511,8 +1531,14 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
Node *subexpr=NULL;
subexpr = _parse_and_reduce_expression(p_block,p_static);
- if (!subexpr)
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
+
+
lv->assign=subexpr;
assigned=subexpr;
@@ -1543,8 +1569,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
ControlFlowNode *cf_if = alloc_node<ControlFlowNode>();
@@ -1598,8 +1628,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
//condition
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
cf_else->arguments.push_back(condition);
cf_else->cf_type=ControlFlowNode::CF_IF;
@@ -1660,8 +1694,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
ControlFlowNode *cf_while = alloc_node<ControlFlowNode>();
@@ -1706,8 +1744,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *container = _parse_and_reduce_expression(p_block,p_static);
- if (!container)
+ if (!container) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
ControlFlowNode *cf_for = alloc_node<ControlFlowNode>();
@@ -1771,8 +1813,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
} else {
//expect expression
Node *retexpr = _parse_and_reduce_expression(p_block,p_static);
- if (!retexpr)
+ if (!retexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
cf_return->arguments.push_back(retexpr);
p_block->statements.push_back(cf_return);
if (!_end_statement()) {
@@ -1787,8 +1833,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
tokenizer->advance();
Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
+ if (!condition) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
AssertNode *an = alloc_node<AssertNode>();
an->condition=condition;
p_block->statements.push_back(an);
@@ -1801,8 +1851,12 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
default: {
Node *expression = _parse_and_reduce_expression(p_block,p_static,false,true);
- if (!expression)
+ if (!expression) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
p_block->statements.push_back(expression);
if (!_end_statement()) {
_set_error("Expected end of statement after expression.");
@@ -2625,14 +2679,18 @@ void GDParser::_parse_class(ClassNode *p_class) {
Node *subexpr=NULL;
- subexpr = _parse_and_reduce_expression(p_class,false);
- if (!subexpr)
+ subexpr = _parse_and_reduce_expression(p_class,false,autoexport);
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
member.expression=subexpr;
if (autoexport) {
- if (subexpr->type==Node::TYPE_ARRAY) {
+ if (1)/*(subexpr->type==Node::TYPE_ARRAY) {
member._export.type=Variant::ARRAY;
@@ -2640,7 +2698,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
member._export.type=Variant::DICTIONARY;
- } else {
+ } else*/ {
if (subexpr->type!=Node::TYPE_CONSTANT) {
@@ -2756,8 +2814,12 @@ void GDParser::_parse_class(ClassNode *p_class) {
Node *subexpr=NULL;
subexpr = _parse_and_reduce_expression(p_class,true,true);
- if (!subexpr)
+ if (!subexpr) {
+ if (_recover_from_completion()) {
+ break;
+ }
return;
+ }
if (subexpr->type!=Node::TYPE_CONSTANT) {
_set_error("Expected constant expression");
@@ -2852,6 +2914,7 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p
completion_class=NULL;
completion_function=NULL;
completion_block=NULL;
+ completion_found=false;
current_block=NULL;
current_class=NULL;
current_function=NULL;
@@ -2874,6 +2937,7 @@ Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_ju
completion_class=NULL;
completion_function=NULL;
completion_block=NULL;
+ completion_found=false;
current_block=NULL;
current_class=NULL;
@@ -2917,6 +2981,8 @@ void GDParser::clear() {
current_block=NULL;
current_class=NULL;
+ completion_found=false;
+
current_function=NULL;
validating=false;
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index fd8a2576fa..134279b6d8 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -419,10 +419,12 @@ private:
BlockNode *completion_block;
int completion_line;
int completion_argument;
+ bool completion_found;
PropertyInfo current_export;
void _set_error(const String& p_error, int p_line=-1, int p_column=-1);
+ bool _recover_from_completion();
bool _parse_arguments(Node* p_parent, Vector<Node*>& p_args, bool p_static, bool p_can_codecomplete=false);
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 53ae0c8702..99ddc74bb4 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -2710,7 +2710,10 @@ GDScriptLanguage::~GDScriptLanguage() {
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderGDScript::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
GDScript *script = memnew( GDScript );
@@ -2742,6 +2745,8 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_orig
script->reload();
}
+ if (r_error)
+ *r_error=OK;
return scriptres;
}
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index fe325ff71e..37ef47af6c 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -557,7 +557,7 @@ public:
class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 76575a1ec6..fce1fe3ed6 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -173,8 +173,7 @@ def configure(env):
env.Append(LDPATH=[ld_path])
env.Append(LIBS=['OpenSLES'])
# env.Append(LIBS=['c','m','stdc++','log','EGL','GLESv1_CM','GLESv2','OpenSLES','supc++','android'])
- if (env["ndk_platform"]!="2.2"):
- env.Append(LIBS=['EGL','OpenSLES','android'])
+ env.Append(LIBS=['EGL','OpenSLES','android'])
env.Append(LIBS=['c','m','stdc++','log','GLESv1_CM','GLESv2', 'z'])
env["LINKFLAGS"]= string.split(" -g --sysroot="+ld_sysroot+" -Wl,--no-undefined -Wl,-z,noexecstack ")
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index da3a37fb42..ff70d5ae76 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -29,16 +29,16 @@
#include "file_access_android.h"
#include "print_string.h"
-#ifdef ANDROID_NATIVE_ACTIVITY
+
AAssetManager *FileAccessAndroid::asset_manager=NULL;
-void FileAccessAndroid::make_default() {
+/*void FileAccessAndroid::make_default() {
create_func=create_android;
-}
+}*/
FileAccess* FileAccessAndroid::create_android() {
@@ -46,7 +46,7 @@ FileAccess* FileAccessAndroid::create_android() {
}
-Error FileAccessAndroid::open(const String& p_path, int p_mode_flags) {
+Error FileAccessAndroid::_open(const String& p_path, int p_mode_flags) {
String path=fix_path(p_path).simplify_path();
if (path.begins_with("/"))
@@ -55,7 +55,6 @@ Error FileAccessAndroid::open(const String& p_path, int p_mode_flags) {
path=path.substr(6,path.length());
-
ERR_FAIL_COND_V(p_mode_flags&FileAccess::WRITE,ERR_UNAVAILABLE); //can't write on android..
a=AAssetManager_open(asset_manager,path.utf8().get_data(),AASSET_MODE_STREAMING);
if (!a)
@@ -184,4 +183,4 @@ FileAccessAndroid::~FileAccessAndroid()
{
close();
}
-#endif
+
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index f477920ae9..506c2c023f 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -29,14 +29,13 @@
#ifndef FILE_ACCESS_ANDROID_H
#define FILE_ACCESS_ANDROID_H
-#ifdef ANDROID_NATIVE_ACTIVITY
#include "os/file_access.h"
#include <stdio.h>
#include <android/asset_manager.h>
#include <android/log.h>
-#include <android_native_app_glue.h>
+//#include <android_native_app_glue.h>
class FileAccessAndroid : public FileAccess {
@@ -51,7 +50,7 @@ public:
static AAssetManager *asset_manager;
- virtual Error open(const String& p_path, int p_mode_flags); ///< open a file
+ virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
@@ -71,12 +70,13 @@ public:
virtual bool file_exists(const String& p_path); ///< return true if a file exists
+ virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
- static void make_default();
+ //static void make_default();
FileAccessAndroid();
~FileAccessAndroid();
};
#endif // FILE_ACCESS_ANDROID_H
-#endif
+
diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp
index 971d4f84ab..be38d806b2 100644
--- a/platform/android/file_access_jandroid.cpp
+++ b/platform/android/file_access_jandroid.cpp
@@ -62,13 +62,15 @@ Error FileAccessJAndroid::_open(const String& p_path, int p_mode_flags) {
JNIEnv *env = ThreadAndroid::get_env();
- //OS::get_singleton()->print("env: %p, io %p, fo: %p\n",env,io,_file_open);
jstring js = env->NewStringUTF(path.utf8().get_data());
int res = env->CallIntMethod(io,_file_open,js,p_mode_flags&WRITE?true:false);
env->DeleteLocalRef(js);
+ OS::get_singleton()->print("fopen: '%s' ret %i\n",path.utf8().get_data(),res);
+
+
if (res<=0)
return ERR_FILE_CANT_OPEN;
id=res;
diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java
index 9b9b1ab2ad..4c5a313576 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/com/android/godot/Godot.java
@@ -357,7 +357,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
Log.d("GODOT"," " + command_line[w]);
}
}*/
- GodotLib.initialize(this,io.needsReloadHooks(),command_line);
+ GodotLib.initialize(this,io.needsReloadHooks(),command_line,getAssets());
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
diff --git a/platform/android/java/src/com/android/godot/GodotIO.java b/platform/android/java/src/com/android/godot/GodotIO.java
index addceb1528..a7dc0c2f75 100644
--- a/platform/android/java/src/com/android/godot/GodotIO.java
+++ b/platform/android/java/src/com/android/godot/GodotIO.java
@@ -94,6 +94,7 @@ public class GodotIO {
//System.out.printf("file_open: Attempt to Open %s\n",path);
+ //Log.v("MyApp", "TRYING TO OPEN FILE: " + path);
if (write)
return -1;
@@ -105,7 +106,7 @@ public class GodotIO {
} catch (Exception e) {
- //System.out.printf("Exception on file_open: %s\n",e);
+ //System.out.printf("Exception on file_open: %s\n",path);
return -1;
}
@@ -113,7 +114,7 @@ public class GodotIO {
ad.len=ad.is.available();
} catch (Exception e) {
- System.out.printf("Exception availabling on file_open: %s\n",e);
+ System.out.printf("Exception availabling on file_open: %s\n",path);
return -1;
}
diff --git a/platform/android/java/src/com/android/godot/GodotLib.java b/platform/android/java/src/com/android/godot/GodotLib.java
index 71c31e9f83..f099e0feff 100644
--- a/platform/android/java/src/com/android/godot/GodotLib.java
+++ b/platform/android/java/src/com/android/godot/GodotLib.java
@@ -44,7 +44,7 @@ public class GodotLib {
* @param height the current view height
*/
- public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline);
+ public static native void initialize(Godot p_instance,boolean need_reload_hook,String[] p_cmdline,Object p_asset_manager);
public static native void resize(int width, int height,boolean reload);
public static native void newcontext();
public static native void quit();
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 3158254781..d001cface2 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -33,13 +33,14 @@
#include "main/main.h"
#include <unistd.h>
#include "file_access_jandroid.h"
+#include "file_access_android.h"
#include "dir_access_jandroid.h"
#include "audio_driver_jandroid.h"
#include "globals.h"
#include "thread_jandroid.h"
#include "core/os/keyboard.h"
#include "java_class_wrapper.h"
-
+#include "android/asset_manager_jni.h"
static JavaClassWrapper *java_class_wrapper=NULL;
static OS_Android *os_android=NULL;
@@ -764,7 +765,7 @@ static void _stop_video() {
env->CallVoidMethod(godot_io, _stopVideo);
}
-JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline) {
+JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager) {
__android_log_print(ANDROID_LOG_INFO,"godot","**INIT EVENT! - %p\n",env);
@@ -820,7 +821,14 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
}
ThreadAndroid::make_default(jvm);
+#ifdef USE_JAVA_FILE_ACCESS
FileAccessJAndroid::setup(gob);
+#else
+
+ jobject amgr = env->NewGlobalRef(p_asset_manager);
+
+ FileAccessAndroid::asset_manager=AAssetManager_fromJava(env,amgr);
+#endif
DirAccessJAndroid::setup(gob);
AudioDriverAndroid::setup(gob);
}
diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h
index 57a4cc8651..9410fe7132 100644
--- a/platform/android/java_glue.h
+++ b/platform/android/java_glue.h
@@ -36,7 +36,7 @@
extern "C" {
- JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline);
+ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, jobject obj, jobject activity,jboolean p_need_reload_hook, jobjectArray p_cmdline,jobject p_asset_manager);
JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_resize(JNIEnv * env, jobject obj, jint width, jint height, jboolean reload);
JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_newcontext(JNIEnv * env, jobject obj);
JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobject obj);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 612148418b..e2ff128f0d 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -37,6 +37,8 @@
#include "servers/visual/visual_server_wrap_mt.h"
#include "main/main.h"
+#include "file_access_android.h"
+
#include "core/globals.h"
#ifdef ANDROID_NATIVE_ACTIVITY
@@ -89,8 +91,14 @@ void OS_Android::initialize_core() {
if (use_apk_expansion)
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
- else
+ else {
+#ifdef USE_JAVA_FILE_ACCESS
FileAccess::make_default<FileAccessBufferedFA<FileAccessJAndroid> >(FileAccess::ACCESS_RESOURCES);
+#else
+ //FileAccess::make_default<FileAccessBufferedFA<FileAccessAndroid> >(FileAccess::ACCESS_RESOURCES);
+ FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
+#endif
+ }
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
//FileAccessBufferedFA<FileAccessUnix>::make_default();
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 7a5a55653f..e9b0d00196 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -41,6 +41,9 @@
#include "servers/visual/rasterizer.h"
+//#ifdef USE_JAVA_FILE_ACCESS
+
+
#ifdef ANDROID_NATIVE_ACTIVITY
#include <android/sensor.h>
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index d495e3b5fc..d755b3dba0 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -34,5 +34,5 @@ obj = env_ios.Object('godot_iphone.cpp')
prog = None
prog = env_ios.Program('#bin/godot', [obj] + iphone_lib)
-action = "dsymutil "+File(prog)[0].path+" -o " + File(prog)[0].path + ".dSYM"
+action = "$IPHONEPATH/usr/bin/dsymutil "+File(prog)[0].path+" -o " + File(prog)[0].path + ".dSYM"
env.AddPostAction(prog, action)
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index 3c79137171..d5764b2b5c 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -43,6 +43,11 @@
#import <AdSupport/AdSupport.h>
#endif
+#ifdef MODULE_PARSE_ENABLED
+#import <Parse/Parse.h>
+#import "FBSDKCoreKit/FBSDKCoreKit.h"
+#endif
+
#define kFilteringFactor 0.1
#define kRenderingFrequency 60
#define kAccelerometerFrequency 100.0 // Hz
@@ -139,8 +144,9 @@ static int frame_count = 0;
++frame_count;
// this might be necessary before here
- for (NSString* key in [[NSBundle mainBundle] infoDictionary]) {
- NSObject* value = [[[NSBundle mainBundle] infoDictionary] objectForKey:key];
+ NSDictionary* dict = [[NSBundle mainBundle] infoDictionary];
+ for (NSString* key in dict) {
+ NSObject* value = [dict objectForKey:key];
String ukey = String::utf8([key UTF8String]);
// we need a NSObject to Variant conversor
@@ -341,6 +347,15 @@ static int frame_count = 0;
// For 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
+#ifdef MODULE_PARSE_ENABLED
+ NSLog(@"Handling application openURL");
+ return [[FBSDKApplicationDelegate sharedInstance] application:application
+ openURL:url
+ sourceApplication:sourceApplication
+ annotation:annotation];
+#endif
+
+
#ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED
return [[[FacebookScorer sharedInstance] facebook] handleOpenURL:url];
#else
@@ -348,6 +363,32 @@ static int frame_count = 0;
#endif
}
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
+#ifdef MODULE_PARSE_ENABLED
+ // Store the deviceToken in the current installation and save it to Parse.
+ PFInstallation *currentInstallation = [PFInstallation currentInstallation];
+ //NSString* token = [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding];
+ NSLog(@"Device Token : %@ ", deviceToken);
+ [currentInstallation setDeviceTokenFromData:deviceToken];
+ [currentInstallation saveInBackground];
+#endif
+}
+
+- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
+#ifdef MODULE_PARSE_ENABLED
+ [PFPush handlePush:userInfo];
+ NSDictionary *aps = [userInfo objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+
+ NSLog(@"Push Notification Payload (app active) %@", aps);
+ [defaults setObject:aps forKey:@"notificationInfo"];
+ [defaults synchronize];
+ if (application.applicationState == UIApplicationStateInactive) {
+ [PFAnalytics trackAppOpenedWithRemoteNotificationPayload:userInfo];
+ }
+#endif
+}
+
- (void)dealloc
{
[window release];
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index fb57876a83..3864968d94 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -11,7 +11,8 @@ def get_name():
def can_build():
import sys
- if sys.platform == 'darwin':
+ import os
+ if sys.platform == 'darwin' or os.environ.has_key("OSXCROSS_IOS"):
return True
return False
@@ -28,6 +29,7 @@ def get_opts():
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
('ios_appirater', 'Enable Appirater', 'no'),
('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'),
+ ('ios_triple', 'Triple for ios toolchain', ''),
]
def get_flags():
@@ -35,6 +37,7 @@ def get_flags():
return [
('tools', 'no'),
('webp', 'yes'),
+ ("theora","no"),
('openssl','builtin'), #use builtin openssl
]
@@ -48,9 +51,10 @@ def configure(env):
# env['CC'] = '$IPHONEPATH/Developer/usr/bin/gcc'
# env['CXX'] = '$IPHONEPATH/Developer/usr/bin/g++'
- env['CC'] = '$IPHONEPATH/usr/bin/clang'
- env['CXX'] = '$IPHONEPATH/usr/bin/clang++'
- env['AR'] = 'ar'
+ env['CC'] = '$IPHONEPATH/usr/bin/${ios_triple}clang'
+ env['CXX'] = '$IPHONEPATH/usr/bin/${ios_triple}clang++'
+ env['AR'] = '$IPHONEPATH/usr/bin/${ios_triple}ar'
+ env['RANLIB'] = '$IPHONEPATH/usr/bin/${ios_triple}ranlib'
import string
if (env["bits"]=="64"):
@@ -59,7 +63,7 @@ def configure(env):
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
else:
- env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -isysroot $IPHONESDK')
+ env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=5.1.1 -MMD -MT dependencies -isysroot $IPHONESDK')
if (env["bits"]=="64"):
env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1',
@@ -80,7 +84,7 @@ def configure(env):
'-framework', 'CoreMedia',
])
else:
- env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3',
+ env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1',
'-isysroot', '$IPHONESDK',
'-framework', 'Foundation',
'-framework', 'UIKit',
diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h
index c58c863510..cda75394db 100755
--- a/platform/iphone/gl_view.h
+++ b/platform/iphone/gl_view.h
@@ -34,7 +34,7 @@
#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>
-#define USE_CADISPLAYLINK 1 //iOS version 3.1+ is required
+#define USE_CADISPLAYLINK 0 //iOS version 3.1+ is required
@protocol GLViewDelegate;
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index 3309fd0820..4d5d1b81e3 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -345,6 +345,8 @@ static void clear_touches() {
[self destroyFramebuffer];
[self createFramebuffer];
[self drawView];
+ [self drawView];
+
}
- (BOOL)createFramebuffer
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm
index e3ba6bbd73..f689123c81 100644
--- a/platform/iphone/in_app_store.mm
+++ b/platform/iphone/in_app_store.mm
@@ -28,6 +28,10 @@
/*************************************************************************/
#ifdef STOREKIT_ENABLED
+#ifdef MODULE_FUSEBOXX_ENABLED
+#import "modules/fuseboxx/ios/FuseSDK.h"
+#endif
+
#include "in_app_store.h"
extern "C" {
@@ -222,6 +226,11 @@ Error InAppStore::request_product_info(Variant p_params) {
else{
[pending_transactions setObject:transaction forKey:transaction.payment.productIdentifier];
}
+
+ #ifdef MODULE_FUSEBOXX_ENABLED
+ printf("Registering transaction on Fuseboxx!\n");
+ [FuseSDK registerInAppPurchase: transaction];
+ #endif
} break;
case SKPaymentTransactionStateFailed: {
printf("status transaction failed!\n");
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index c1ba0c2283..cd96cf4f31 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -3,7 +3,8 @@ Import('env')
javascript_files = [
"os_javascript.cpp",
"audio_driver_javascript.cpp",
- "javascript_main.cpp"
+ "javascript_main.cpp",
+ "audio_server_javascript.cpp"
]
#obj = env.SharedObject('godot_javascript.cpp')
@@ -16,6 +17,8 @@ javascript_objects=[]
for x in javascript_files:
javascript_objects.append( env_javascript.Object( x ) )
+env.Append(LINKFLAGS=["-s","EXPORTED_FUNCTIONS=\"['_main','_audio_server_mix_function','_main_after_fs_sync']\""])
+
prog = None
#env_javascript.SharedLibrary("#platform/javascript/libgodot_javascript.so",[javascript_objects])
diff --git a/platform/javascript/audio_server_javascript.cpp b/platform/javascript/audio_server_javascript.cpp
new file mode 100644
index 0000000000..fd505b8a8f
--- /dev/null
+++ b/platform/javascript/audio_server_javascript.cpp
@@ -0,0 +1,805 @@
+#include "audio_server_javascript.h"
+
+#include "emscripten.h"
+
+AudioMixer *AudioServerJavascript::get_mixer() {
+
+ return NULL;
+}
+
+void AudioServerJavascript::audio_mixer_chunk_callback(int p_frames){
+
+
+}
+
+
+RID AudioServerJavascript::sample_create(SampleFormat p_format, bool p_stereo, int p_length) {
+
+ Sample *sample = memnew( Sample );
+ sample->format=p_format;
+ sample->stereo=p_stereo;
+ sample->length=p_length;
+ sample->loop_begin=0;
+ sample->loop_end=p_length;
+ sample->loop_format=SAMPLE_LOOP_NONE;
+ sample->mix_rate=44100;
+ sample->index=-1;
+
+ return sample_owner.make_rid(sample);
+
+}
+
+void AudioServerJavascript::sample_set_description(RID p_sample, const String& p_description){
+
+
+}
+String AudioServerJavascript::sample_get_description(RID p_sample, const String& p_description) const{
+
+ return String();
+}
+
+AudioServerJavascript::SampleFormat AudioServerJavascript::sample_get_format(RID p_sample) const{
+
+ return SAMPLE_FORMAT_PCM8;
+}
+bool AudioServerJavascript::sample_is_stereo(RID p_sample) const{
+
+ const Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND_V(!sample,false);
+ return sample->stereo;
+
+}
+int AudioServerJavascript::sample_get_length(RID p_sample) const{
+ const Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND_V(!sample,0);
+ return sample->length;
+}
+const void* AudioServerJavascript::sample_get_data_ptr(RID p_sample) const{
+
+ return NULL;
+}
+
+void AudioServerJavascript::sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer){
+
+ Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND(!sample);
+ int chans = sample->stereo?2:1;
+
+ Vector<float> buffer;
+ buffer.resize(sample->length*chans);
+ DVector<uint8_t>::Read r=p_buffer.read();
+ if (sample->format==SAMPLE_FORMAT_PCM8) {
+ const int8_t*ptr = (const int8_t*)r.ptr();
+ for(int i=0;i<sample->length*chans;i++) {
+ buffer[i]=ptr[i]/128.0;
+ }
+ } else if (sample->format==SAMPLE_FORMAT_PCM16){
+ const int16_t*ptr = (const int16_t*)r.ptr();
+ for(int i=0;i<sample->length*chans;i++) {
+ buffer[i]=ptr[i]/32768.0;
+ }
+ } else {
+ ERR_EXPLAIN("Unsupported for now");
+ ERR_FAIL();
+ }
+
+ sample->tmp_data=buffer;
+
+
+
+}
+const DVector<uint8_t> AudioServerJavascript::sample_get_data(RID p_sample) const{
+
+
+ return DVector<uint8_t>();
+}
+
+void AudioServerJavascript::sample_set_mix_rate(RID p_sample,int p_rate){
+ Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND(!sample);
+ sample->mix_rate=p_rate;
+
+}
+
+int AudioServerJavascript::sample_get_mix_rate(RID p_sample) const{
+ const Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND_V(!sample,0);
+ return sample->mix_rate;
+}
+
+
+void AudioServerJavascript::sample_set_loop_format(RID p_sample,SampleLoopFormat p_format){
+
+ Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND(!sample);
+ sample->loop_format=p_format;
+
+}
+
+AudioServerJavascript::SampleLoopFormat AudioServerJavascript::sample_get_loop_format(RID p_sample) const {
+
+ const Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND_V(!sample,SAMPLE_LOOP_NONE);
+ return sample->loop_format;
+}
+
+void AudioServerJavascript::sample_set_loop_begin(RID p_sample,int p_pos){
+
+ Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND(!sample);
+ sample->loop_begin=p_pos;
+
+}
+int AudioServerJavascript::sample_get_loop_begin(RID p_sample) const{
+
+ const Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND_V(!sample,0);
+ return sample->loop_begin;
+}
+
+void AudioServerJavascript::sample_set_loop_end(RID p_sample,int p_pos){
+
+ Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND(!sample);
+ sample->loop_end=p_pos;
+
+}
+int AudioServerJavascript::sample_get_loop_end(RID p_sample) const{
+
+ const Sample *sample = sample_owner.get(p_sample);
+ ERR_FAIL_COND_V(!sample,0);
+ return sample->loop_end;
+}
+
+
+/* VOICE API */
+
+RID AudioServerJavascript::voice_create(){
+
+ Voice *voice = memnew( Voice );
+
+ voice->index=voice_base;
+ voice->volume=1.0;
+ voice->pan=0.0;
+ voice->pan_depth=.0;
+ voice->pan_height=0.0;
+ voice->chorus=0;
+ voice->reverb_type=REVERB_SMALL;
+ voice->reverb=0;
+ voice->mix_rate=-1;
+ voice->positional=false;
+ voice->active=false;
+
+ EM_ASM_( {
+ _as_voices[$0]=null;
+ _as_voice_gain[$0]=_as_audioctx.createGain();
+ _as_voice_pan[$0]=_as_audioctx.createStereoPanner();
+ _as_voice_gain[$0].connect(_as_voice_pan[$0]);
+ _as_voice_pan[$0].connect(_as_audioctx.destination);
+
+ },voice_base);
+
+ voice_base++;
+
+ return voice_owner.make_rid( voice );
+}
+
+void AudioServerJavascript::voice_play(RID p_voice, RID p_sample){
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND(!voice);
+ Sample *sample=sample_owner.get(p_sample);
+ ERR_FAIL_COND(!sample);
+
+ // due to how webaudio works, sample cration is deferred until used
+ // sorry! WebAudio absolutely sucks
+
+
+ if (sample->index==-1) {
+ //create sample if not created
+ ERR_FAIL_COND(sample->tmp_data.size()==0);
+ sample->index=sample_base;
+ EM_ASM_( {
+ _as_samples[$0]=_as_audioctx.createBuffer($1,$2,$3);
+ },sample_base,sample->stereo?2:1,sample->length,sample->mix_rate);
+
+ sample_base++;
+ int chans = sample->stereo?2:1;
+
+
+ for(int i=0;i<chans;i++) {
+
+
+ EM_ASM_({
+ _as_edited_buffer=_as_samples[$0].getChannelData($1);
+ },sample->index,i);
+
+
+ for(int j=0;j<sample->length;j++) {
+
+ EM_ASM_({
+ _as_edited_buffer[$0]=$1;
+ },j,sample->tmp_data[j*chans+i]);
+ }
+ }
+
+ sample->tmp_data.clear();
+ }
+
+
+ voice->sample_mix_rate=sample->mix_rate;
+ if (voice->mix_rate==-1) {
+ voice->mix_rate=voice->sample_mix_rate;
+ }
+
+ float freq_diff = Math::log(float(voice->mix_rate)/float(voice->sample_mix_rate))/Math::log(2.0);
+ int detune = int(freq_diff*1200.0);
+
+ EM_ASM_( {
+ if (_as_voices[$0]!==null) {
+ _as_voices[$0].stop(); //stop and byebye
+ }
+ _as_voices[$0]=_as_audioctx.createBufferSource();
+ _as_voices[$0].connect(_as_voice_gain[$0]);
+ _as_voices[$0].buffer=_as_samples[$1];
+ _as_voices[$0].loopStart.value=$1;
+ _as_voices[$0].loopEnd.value=$2;
+ _as_voices[$0].loop.value=$3;
+ _as_voices[$0].detune.value=$6;
+ _as_voice_pan[$0].pan.value=$4;
+ _as_voice_gain[$0].gain.value=$5;
+ _as_voices[$0].start();
+ _as_voices[$0].onended=function() {
+ _as_voices[$0].disconnect(_as_voice_gain[$0]);
+ _as_voices[$0]=null;
+ }
+
+ },voice->index,sample->index,sample->mix_rate*sample->loop_begin,sample->mix_rate*sample->loop_end,sample->loop_format!=SAMPLE_LOOP_NONE,voice->pan,voice->volume*fx_volume_scale,detune);
+
+ voice->active=true;
+}
+
+void AudioServerJavascript::voice_set_volume(RID p_voice, float p_gain){
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND(!voice);
+
+ voice->volume=p_gain;
+
+ if (voice->active) {
+ EM_ASM_( {
+
+ _as_voice_gain[$0].gain.value=$1;
+
+ },voice->index,voice->volume*fx_volume_scale);
+ }
+
+}
+void AudioServerJavascript::voice_set_pan(RID p_voice, float p_pan, float p_depth,float height){
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND(!voice);
+
+ voice->pan=p_pan;
+ voice->pan_depth=p_depth;
+ voice->pan_height=height;
+
+ if (voice->active) {
+ EM_ASM_( {
+
+ _as_voice_pan[$0].pan.value=$1;
+
+ },voice->index,voice->pan);
+ }
+}
+void AudioServerJavascript::voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain){
+
+}
+void AudioServerJavascript::voice_set_chorus(RID p_voice, float p_chorus ){
+
+}
+void AudioServerJavascript::voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb){
+
+}
+void AudioServerJavascript::voice_set_mix_rate(RID p_voice, int p_mix_rate){
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND(!voice);
+
+ voice->mix_rate=p_mix_rate;
+
+ if (voice->active) {
+
+ float freq_diff = Math::log(float(voice->mix_rate)/float(voice->sample_mix_rate))/Math::log(2.0);
+ int detune = int(freq_diff*1200.0);
+ EM_ASM_( {
+
+ _as_voices[$0].detune.value=$1;
+
+ },voice->index,detune);
+ }
+}
+void AudioServerJavascript::voice_set_positional(RID p_voice, bool p_positional){
+
+}
+
+float AudioServerJavascript::voice_get_volume(RID p_voice) const{
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND_V(!voice,0);
+
+ return voice->volume;
+}
+float AudioServerJavascript::voice_get_pan(RID p_voice) const{
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND_V(!voice,0);
+
+ return voice->pan;
+}
+float AudioServerJavascript::voice_get_pan_depth(RID p_voice) const{
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND_V(!voice,0);
+
+ return voice->pan_depth;
+}
+float AudioServerJavascript::voice_get_pan_height(RID p_voice) const{
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND_V(!voice,0);
+
+ return voice->pan_height;
+}
+AudioServerJavascript::FilterType AudioServerJavascript::voice_get_filter_type(RID p_voice) const{
+
+ return FILTER_NONE;
+}
+float AudioServerJavascript::voice_get_filter_cutoff(RID p_voice) const{
+
+ return 0;
+}
+float AudioServerJavascript::voice_get_filter_resonance(RID p_voice) const{
+
+ return 0;
+}
+float AudioServerJavascript::voice_get_chorus(RID p_voice) const{
+
+ return 0;
+}
+AudioServerJavascript::ReverbRoomType AudioServerJavascript::voice_get_reverb_type(RID p_voice) const{
+
+ return REVERB_SMALL;
+}
+float AudioServerJavascript::voice_get_reverb(RID p_voice) const{
+
+ return 0;
+}
+
+int AudioServerJavascript::voice_get_mix_rate(RID p_voice) const{
+
+ return 44100;
+}
+
+bool AudioServerJavascript::voice_is_positional(RID p_voice) const{
+
+ return false;
+}
+
+void AudioServerJavascript::voice_stop(RID p_voice){
+
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND(!voice);
+
+ if (voice->active) {
+
+ EM_ASM_( {
+ if (_as_voices[$0]!==null) {
+ _as_voices[$0].stop();
+ _as_voices[$0].disconnect(_as_voice_gain[$0]);
+ _as_voices[$0]=null;
+ }
+ },voice->index);
+
+ voice->active=false;
+ }
+
+
+}
+bool AudioServerJavascript::voice_is_active(RID p_voice) const{
+ Voice* voice=voice_owner.get(p_voice);
+ ERR_FAIL_COND_V(!voice,false);
+
+ return voice->active;
+}
+
+/* STREAM API */
+
+RID AudioServerJavascript::audio_stream_create(AudioStream *p_stream) {
+
+
+ Stream *s = memnew(Stream);
+ s->audio_stream=p_stream;
+ s->event_stream=NULL;
+ s->active=false;
+ s->E=NULL;
+ s->volume_scale=1.0;
+ p_stream->set_mix_rate(webaudio_mix_rate);
+
+ return stream_owner.make_rid(s);
+}
+
+RID AudioServerJavascript::event_stream_create(EventStream *p_stream) {
+
+
+ Stream *s = memnew(Stream);
+ s->audio_stream=NULL;
+ s->event_stream=p_stream;
+ s->active=false;
+ s->E=NULL;
+ s->volume_scale=1.0;
+ //p_stream->set_mix_rate(AudioDriverJavascript::get_singleton()->get_mix_rate());
+
+ return stream_owner.make_rid(s);
+
+
+}
+
+
+void AudioServerJavascript::stream_set_active(RID p_stream, bool p_active) {
+
+
+ Stream *s = stream_owner.get(p_stream);
+ ERR_FAIL_COND(!s);
+
+ if (s->active==p_active)
+ return;
+
+ s->active=p_active;
+ if (p_active)
+ s->E=active_audio_streams.push_back(s);
+ else {
+ active_audio_streams.erase(s->E);
+ s->E=NULL;
+ }
+}
+
+bool AudioServerJavascript::stream_is_active(RID p_stream) const {
+
+ Stream *s = stream_owner.get(p_stream);
+ ERR_FAIL_COND_V(!s,false);
+ return s->active;
+}
+
+void AudioServerJavascript::stream_set_volume_scale(RID p_stream, float p_scale) {
+
+ Stream *s = stream_owner.get(p_stream);
+ ERR_FAIL_COND(!s);
+ s->volume_scale=p_scale;
+
+}
+
+float AudioServerJavascript::stream_set_volume_scale(RID p_stream) const {
+
+ Stream *s = stream_owner.get(p_stream);
+ ERR_FAIL_COND_V(!s,0);
+ return s->volume_scale;
+
+}
+
+
+/* Audio Physics API */
+
+void AudioServerJavascript::free(RID p_id){
+
+ if (voice_owner.owns(p_id)) {
+ Voice* voice=voice_owner.get(p_id);
+ ERR_FAIL_COND(!voice);
+
+ if (voice->active) {
+ EM_ASM_( {
+ if (_as_voices[$0]!==null) {
+ _as_voices[$0].stop();
+ _as_voices[$0].disconnect(_as_voice_gain[$0]);
+ }
+ },voice->index);
+ }
+
+ EM_ASM_( {
+ delete _as_voices[$0];
+ _as_voice_gain[$0].disconnect(_as_voice_pan[$0]);
+ delete _as_voice_gain[$0];
+ _as_voice_pan[$0].disconnect(_as_audioctx.destination);
+ delete _as_voice_pan[$0];
+
+ },voice->index);
+
+ voice_owner.free(p_id);
+ memdelete(voice);
+
+ } else if (sample_owner.owns(p_id)) {
+
+ Sample *sample = sample_owner.get(p_id);
+ ERR_FAIL_COND(!sample);
+
+ EM_ASM_( {
+ delete _as_samples[$0];
+
+ },sample->index);
+
+ sample_owner.free(p_id);
+ memdelete(sample);
+
+ } else if (stream_owner.owns(p_id)) {
+
+
+ Stream *s=stream_owner.get(p_id);
+
+ if (s->active) {
+ stream_set_active(p_id,false);
+ }
+
+ memdelete(s);
+ stream_owner.free(p_id);
+ }
+}
+
+extern "C" {
+
+
+void audio_server_mix_function(int p_frames) {
+
+ //print_line("MIXI! "+itos(p_frames));
+ static_cast<AudioServerJavascript*>(AudioServerJavascript::get_singleton())->mix_to_js(p_frames);
+}
+
+}
+
+void AudioServerJavascript::mix_to_js(int p_frames) {
+
+
+ //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
+ int todo=p_frames;
+ int offset=0;
+
+ while(todo) {
+
+ int tomix=MIN(todo,INTERNAL_BUFFER_SIZE);
+ driver_process_chunk(tomix);
+
+
+ EM_ASM_({
+
+ var data = HEAPF32.subarray($0/4, $0/4 + $2*2);
+
+ for (var channel = 0; channel < _as_output_buffer.numberOfChannels; channel++) {
+ var outputData = _as_output_buffer.getChannelData(channel);
+ // Loop through samples
+ for (var sample = 0; sample < $2; sample++) {
+ // make output equal to the same as the input
+ outputData[sample+$1] = data[sample*2+channel];
+ }
+ }
+
+ },internal_buffer,offset,tomix);
+
+ todo-=tomix;
+ offset+=tomix;
+ }
+}
+
+void AudioServerJavascript::init(){
+
+ //EM_ASM(
+// console.log('server is '+audio_server);
+// );
+
+
+ //int latency = GLOBAL_DEF("javascript/audio_latency",16384);
+
+ internal_buffer_channels=2;
+ internal_buffer = memnew_arr(float,INTERNAL_BUFFER_SIZE*internal_buffer_channels);
+ stream_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*4); //max 4 channels
+
+ stream_volume=0.3;
+
+ int buffer_latency=16384;
+
+ EM_ASM_( {
+
+ _as_script_node = _as_audioctx.createScriptProcessor($0, 0, 2);
+ _as_script_node.connect(_as_audioctx.destination);
+ console.log(_as_script_node.bufferSize);
+
+
+ _as_script_node.onaudioprocess = function(audioProcessingEvent) {
+ // The output buffer contains the samples that will be modified and played
+ _as_output_buffer = audioProcessingEvent.outputBuffer;
+ audio_server_mix_function(_as_output_buffer.getChannelData(0).length);
+ }
+ },buffer_latency);
+
+
+}
+
+void AudioServerJavascript::finish(){
+
+}
+void AudioServerJavascript::update(){
+
+ for(List<Stream*>::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback
+
+ List<Stream*>::Element *N=E->next();
+
+ if (E->get()->audio_stream)
+ E->get()->audio_stream->update();
+
+ E=N;
+ }
+}
+
+/* MISC config */
+
+void AudioServerJavascript::lock(){
+
+}
+void AudioServerJavascript::unlock(){
+
+}
+int AudioServerJavascript::get_default_channel_count() const{
+
+ return 1;
+}
+int AudioServerJavascript::get_default_mix_rate() const{
+
+ return 44100;
+}
+
+void AudioServerJavascript::set_stream_global_volume_scale(float p_volume){
+
+ stream_volume_scale=p_volume;
+}
+void AudioServerJavascript::set_fx_global_volume_scale(float p_volume){
+
+ fx_volume_scale=p_volume;
+}
+void AudioServerJavascript::set_event_voice_global_volume_scale(float p_volume){
+
+}
+
+float AudioServerJavascript::get_stream_global_volume_scale() const{
+ return 1;
+}
+float AudioServerJavascript::get_fx_global_volume_scale() const{
+
+ return 1;
+}
+float AudioServerJavascript::get_event_voice_global_volume_scale() const{
+
+ return 1;
+}
+
+uint32_t AudioServerJavascript::read_output_peak() const{
+
+ return 0;
+}
+
+AudioServerJavascript *AudioServerJavascript::singleton=NULL;
+
+AudioServer *AudioServerJavascript::get_singleton() {
+ return singleton;
+}
+
+double AudioServerJavascript::get_mix_time() const{
+
+ return 0;
+}
+double AudioServerJavascript::get_output_delay() const {
+
+ return 0;
+}
+
+
+void AudioServerJavascript::driver_process_chunk(int p_frames) {
+
+
+
+ int samples=p_frames*internal_buffer_channels;
+
+ for(int i=0;i<samples;i++) {
+ internal_buffer[i]=0;
+ }
+
+
+ for(List<Stream*>::Element *E=active_audio_streams.front();E;E=E->next()) {
+
+ ERR_CONTINUE(!E->get()->active); // bug?
+
+
+ AudioStream *as=E->get()->audio_stream;
+ if (!as)
+ continue;
+
+ int channels=as->get_channel_count();
+ if (channels==0)
+ continue; // does not want mix
+ if (!as->mix(stream_buffer,p_frames))
+ continue; //nothing was mixed!!
+
+ int32_t stream_vol_scale=(stream_volume*stream_volume_scale*E->get()->volume_scale)*(1<<STREAM_SCALE_BITS);
+
+#define STRSCALE(m_val) ((((m_val>>STREAM_SCALE_BITS)*stream_vol_scale)>>8)/8388608.0)
+ switch(channels) {
+ case 1: {
+
+ for(int i=0;i<p_frames;i++) {
+
+ internal_buffer[(i<<1)+0]+=STRSCALE(stream_buffer[i]);
+ internal_buffer[(i<<1)+1]+=STRSCALE(stream_buffer[i]);
+ }
+ } break;
+ case 2: {
+
+ for(int i=0;i<p_frames*2;i++) {
+
+ internal_buffer[i]+=STRSCALE(stream_buffer[i]);
+ }
+ } break;
+ case 4: {
+
+ for(int i=0;i<p_frames;i++) {
+
+ internal_buffer[(i<<2)+0]+=STRSCALE((stream_buffer[(i<<2)+0]+stream_buffer[(i<<2)+2])>>1);
+ internal_buffer[(i<<2)+1]+=STRSCALE((stream_buffer[(i<<2)+1]+stream_buffer[(i<<2)+3])>>1);
+ }
+ } break;
+
+
+ }
+
+#undef STRSCALE
+ }
+}
+
+
+/*void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) {
+
+
+ _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate());
+ //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
+ int todo=p_frames;
+ while(todo) {
+
+ int tomix=MIN(todo,INTERNAL_BUFFER_SIZE);
+ driver_process_chunk(tomix,p_buffer);
+ p_buffer+=tomix;
+ todo-=tomix;
+ }
+
+
+}*/
+
+AudioServerJavascript::AudioServerJavascript() {
+
+ singleton=this;
+ sample_base=1;
+ voice_base=1;
+ EM_ASM(
+ _as_samples={};
+ _as_voices={};
+ _as_voice_pan={};
+ _as_voice_gain={};
+
+ _as_audioctx = new (window.AudioContext || window.webkitAudioContext)();
+
+ audio_server_mix_function = Module.cwrap('audio_server_mix_function', 'void', ['number']);
+ );
+
+ webaudio_mix_rate = EM_ASM_INT_V(
+ return _as_audioctx.sampleRate;
+ );
+ print_line("WEBAUDIO MIX RATE: "+itos(webaudio_mix_rate));
+ event_voice_scale=1.0;
+ fx_volume_scale=1.0;
+ stream_volume_scale=1.0;
+
+}
diff --git a/platform/javascript/audio_server_javascript.h b/platform/javascript/audio_server_javascript.h
new file mode 100644
index 0000000000..bdab171b45
--- /dev/null
+++ b/platform/javascript/audio_server_javascript.h
@@ -0,0 +1,198 @@
+#ifndef AUDIO_SERVER_JAVASCRIPT_H
+#define AUDIO_SERVER_JAVASCRIPT_H
+
+
+#include "servers/audio_server.h"
+
+class AudioServerJavascript : public AudioServer {
+
+ OBJ_TYPE(AudioServerJavascript,AudioServer);
+
+ enum {
+ INTERNAL_BUFFER_SIZE=4096,
+ STREAM_SCALE_BITS=12
+
+ };
+
+ AudioMixer *get_mixer();
+ void audio_mixer_chunk_callback(int p_frames);
+
+ struct Sample {
+ SampleFormat format;
+ SampleLoopFormat loop_format;
+ int loop_begin;
+ int loop_end;
+ int length;
+ int index;
+ int mix_rate;
+ bool stereo;
+
+ Vector<float> tmp_data;
+ };
+
+ mutable RID_Owner<Sample> sample_owner;
+ int sample_base;
+
+ struct Voice {
+ int index;
+ float volume;
+ float pan;
+ float pan_depth;
+ float pan_height;
+
+ float chorus;
+ ReverbRoomType reverb_type;
+ float reverb;
+
+ int mix_rate;
+ int sample_mix_rate;
+ bool positional;
+
+ bool active;
+
+ };
+
+ mutable RID_Owner<Voice> voice_owner;
+
+ int voice_base;
+
+ struct Stream {
+ bool active;
+ List<Stream*>::Element *E;
+ AudioStream *audio_stream;
+ EventStream *event_stream;
+ float volume_scale;
+ };
+
+ List<Stream*> active_audio_streams;
+
+ //List<Stream*> event_streams;
+
+ float * internal_buffer;
+ int internal_buffer_channels;
+ int32_t * stream_buffer;
+
+ mutable RID_Owner<Stream> stream_owner;
+
+ float stream_volume;
+ float stream_volume_scale;
+
+ float event_voice_scale;
+ float fx_volume_scale;
+
+
+ void driver_process_chunk(int p_frames);
+
+ int webaudio_mix_rate;
+
+
+ static AudioServerJavascript *singleton;
+public:
+
+ void mix_to_js(int p_frames);
+ /* SAMPLE API */
+
+ virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length);
+
+ virtual void sample_set_description(RID p_sample, const String& p_description);
+ virtual String sample_get_description(RID p_sample, const String& p_description) const;
+
+ virtual SampleFormat sample_get_format(RID p_sample) const;
+ virtual bool sample_is_stereo(RID p_sample) const;
+ virtual int sample_get_length(RID p_sample) const;
+ virtual const void* sample_get_data_ptr(RID p_sample) const;
+
+
+ virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer);
+ virtual const DVector<uint8_t> sample_get_data(RID p_sample) const;
+
+ virtual void sample_set_mix_rate(RID p_sample,int p_rate);
+ virtual int sample_get_mix_rate(RID p_sample) const;
+
+ virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format);
+ virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const;
+
+ virtual void sample_set_loop_begin(RID p_sample,int p_pos);
+ virtual int sample_get_loop_begin(RID p_sample) const;
+
+ virtual void sample_set_loop_end(RID p_sample,int p_pos);
+ virtual int sample_get_loop_end(RID p_sample) const;
+
+
+ /* VOICE API */
+
+ virtual RID voice_create();
+
+ virtual void voice_play(RID p_voice, RID p_sample);
+
+ virtual void voice_set_volume(RID p_voice, float p_gain);
+ virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1
+ virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=0);
+ virtual void voice_set_chorus(RID p_voice, float p_chorus );
+ virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb);
+ virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate);
+ virtual void voice_set_positional(RID p_voice, bool p_positional);
+
+ virtual float voice_get_volume(RID p_voice) const;
+ virtual float voice_get_pan(RID p_voice) const; //pan and depth go from -1 to 1
+ virtual float voice_get_pan_depth(RID p_voice) const; //pan and depth go from -1 to 1
+ virtual float voice_get_pan_height(RID p_voice) const; //pan and depth go from -1 to 1
+ virtual FilterType voice_get_filter_type(RID p_voice) const;
+ virtual float voice_get_filter_cutoff(RID p_voice) const;
+ virtual float voice_get_filter_resonance(RID p_voice) const;
+ virtual float voice_get_chorus(RID p_voice) const;
+ virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const;
+ virtual float voice_get_reverb(RID p_voice) const;
+
+ virtual int voice_get_mix_rate(RID p_voice) const;
+ virtual bool voice_is_positional(RID p_voice) const;
+
+ virtual void voice_stop(RID p_voice);
+ virtual bool voice_is_active(RID p_voice) const;
+
+ /* STREAM API */
+
+ virtual RID audio_stream_create(AudioStream *p_stream);
+ virtual RID event_stream_create(EventStream *p_stream);
+
+ virtual void stream_set_active(RID p_stream, bool p_active);
+ virtual bool stream_is_active(RID p_stream) const;
+
+ virtual void stream_set_volume_scale(RID p_stream, float p_scale);
+ virtual float stream_set_volume_scale(RID p_stream) const;
+
+ /* Audio Physics API */
+
+ virtual void free(RID p_id);
+
+ virtual void init();
+ virtual void finish();
+ virtual void update();
+
+ /* MISC config */
+
+ virtual void lock();
+ virtual void unlock();
+ virtual int get_default_channel_count() const;
+ virtual int get_default_mix_rate() const;
+
+ virtual void set_stream_global_volume_scale(float p_volume);
+ virtual void set_fx_global_volume_scale(float p_volume);
+ virtual void set_event_voice_global_volume_scale(float p_volume);
+
+ virtual float get_stream_global_volume_scale() const;
+ virtual float get_fx_global_volume_scale() const;
+ virtual float get_event_voice_global_volume_scale() const;
+
+ virtual uint32_t read_output_peak() const;
+
+ static AudioServer *get_singleton();
+
+ virtual double get_mix_time() const; //useful for video -> audio sync
+ virtual double get_output_delay() const;
+
+
+ AudioServerJavascript();
+};
+
+#endif // AUDIO_SERVER_JAVASCRIPT_H
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 947a637fb9..104cede3f1 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -30,7 +30,6 @@ def get_flags():
('theora', 'no'),
('tools', 'no'),
('nedmalloc', 'no'),
- ('vorbis', 'no'),
('musepack', 'no'),
('squirrel', 'no'),
('squish', 'no'),
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index b262684a59..c38035e64a 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -144,12 +144,16 @@ static void _fix_html(Vector<uint8_t>& html,const String& name,int max_memory) {
str.parse_utf8((const char*)html.ptr(),html.size());
Vector<String> lines=str.split("\n");
for(int i=0;i<lines.size();i++) {
- if (lines[i].find("godot.js")!=-1) {
- strnew+="<script type=\"text/javascript\" src=\""+name+"_filesystem.js\"></script>\n";
- strnew+="<script async type=\"text/javascript\" src=\""+name+".js\"></script>\n";
- } else if (lines[i].find("var Module")!=-1) {
- strnew+=lines[i];
- strnew+="TOTAL_MEMORY:"+itos(max_memory*1024*1024)+",";
+
+ if (lines[i].find("$GODOTTMEM")!=-1) {
+
+ strnew+=lines[i].replace("$GODOTTMEM",itos(max_memory*1024*1024))+"\n";
+ } else if (lines[i].find("$GODOTFS")!=-1) {
+ strnew+=lines[i].replace("$GODOTFS",name+"fs.js")+"\n";
+ } else if (lines[i].find("$GODOTMEM")!=-1) {
+ strnew+=lines[i].replace("$GODOTMEM",name+".mem")+"\n";
+ } else if (lines[i].find("$GODOTJS")!=-1) {
+ strnew+=lines[i].replace("$GODOTJS",name+".js")+"\n";
} else {
strnew+=lines[i]+"\n";
}
@@ -267,10 +271,10 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool
_fix_html(data,p_path.get_file().basename(),1<<(max_memory+5));
file=p_path.get_file();
}
- if (file=="filesystem.js") {
+ if (file=="godotfs.js") {
_fix_files(data,len);
- file=p_path.get_file().basename()+"_filesystem.js";
+ file=p_path.get_file().basename()+"fs.js";
}
if (file=="godot.js") {
@@ -278,6 +282,12 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool
file=p_path.get_file().basename()+".js";
}
+ if (file=="godot.mem") {
+
+ //_fix_godot(data);
+ file=p_path.get_file().basename()+".mem";
+ }
+
String dst = p_path.get_base_dir().plus_file(file);
FileAccess *f=FileAccess::open(dst,FileAccess::WRITE);
if (!f) {
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index 5be6c5b647..fb87dc848e 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -31,6 +31,9 @@
#include "main/main.h"
#include "io/resource_loader.h"
#include "os/keyboard.h"
+#include "emscripten.h"
+#include <string.h>
+
OS_JavaScript *os=NULL;
static void _gfx_init(void *ud,bool gl2,int w, int h,bool fs) {
@@ -196,15 +199,39 @@ static void _gfx_idle() {
glutPostRedisplay();
}
+int start_step=0;
+
static void _godot_draw(void) {
- os->main_loop_iterate();
+ if (start_step==1) {
+ start_step=2;
+ Main::start();
+ os->main_loop_begin();
+ }
+
+ if (start_step==2) {
+ os->main_loop_iterate();
+ }
+
glutSwapBuffers();
}
+
+
+extern "C" {
+
+void main_after_fs_sync(int value) {
+
+ start_step=1;
+ printf("FS SYNCHED!\n");
+}
+
+}
+
int main(int argc, char *argv[]) {
- /* Initialize the window */
+
+ /* Initialize the window */
printf("let it go!\n");
glutInit(&argc, argv);
os = new OS_JavaScript(_gfx_init,NULL,NULL,NULL,NULL);
@@ -218,7 +245,7 @@ int main(int argc, char *argv[]) {
#endif
ResourceLoader::set_abort_on_missing_resources(false); //ease up compatibility
- Main::start();
+
glutSpecialUpFunc(_glut_skey_up);
glutSpecialFunc(_glut_skey_down);
@@ -236,10 +263,32 @@ int main(int argc, char *argv[]) {
// glutReshapeFunc(gears_reshape);
glutDisplayFunc(_godot_draw);
//glutSpecialFunc(gears_special);
- os->main_loop_begin();
+
+
+
+ //mount persistent filesystem
+ EM_ASM(
+ FS.mkdir('/userfs');
+ FS.mount(IDBFS, {}, '/userfs');
+
+
+
+ // sync from persisted state into memory and then
+ // run the 'test' function
+ FS.syncfs(true, function (err) {
+ assert(!err);
+ console.log("done syncinc!");
+ _after_sync_cb = Module.cwrap('main_after_fs_sync', 'void',['number']);
+ _after_sync_cb(0);
+
+ });
+
+ );
glutMainLoop();
+
+
return 0;
}
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index a422f77b4b..ae97bf990b 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -37,6 +37,7 @@
#include "main/main.h"
#include "core/globals.h"
+#include "emscripten.h"
int OS_JavaScript::get_video_driver_count() const {
@@ -104,21 +105,21 @@ void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int
visual_server->init();
visual_server->cursor_set_visible(false, 0);
- AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
+ /*AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
ERR_PRINT("Initializing audio failed.");
- }
+ }*/
print_line("Init SM");
- sample_manager = memnew( SampleManagerMallocSW );
- audio_server = memnew( AudioServerSW(sample_manager) );
+ //sample_manager = memnew( SampleManagerMallocSW );
+ audio_server = memnew( AudioServerJavascript );
print_line("Init Mixer");
- audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
+ //audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false);
audio_server->init();
print_line("Init SoundServer");
@@ -270,6 +271,32 @@ bool OS_JavaScript::main_loop_iterate() {
if (!main_loop)
return false;
+
+ if (time_to_save_sync>=0) {
+ int64_t newtime = get_ticks_msec();
+ int64_t elapsed = newtime - last_sync_time;
+ last_sync_time=newtime;
+
+ time_to_save_sync-=elapsed;
+
+ print_line("elapsed "+itos(elapsed)+" tts "+itos(time_to_save_sync));
+
+ if (time_to_save_sync<0) {
+ //time to sync, for real
+ // run 'success'
+ print_line("DOING SYNCH!");
+ EM_ASM(
+ FS.syncfs(function (err) {
+ assert(!err);
+ console.log("Synched!");
+ //ccall('success', 'v');
+ });
+ );
+ }
+
+
+ }
+
return Main::iteration();
}
@@ -562,14 +589,21 @@ String OS_JavaScript::get_locale() const {
String OS_JavaScript::get_data_dir() const {
- if (get_data_dir_func)
- return get_data_dir_func();
- return "/";
+ //if (get_data_dir_func)
+ // return get_data_dir_func();
+ return "/userfs";
//return Globals::get_singleton()->get_singleton_object("GodotOS")->call("get_data_dir");
};
+void OS_JavaScript::_close_notification_funcs(const String& p_file,int p_flags) {
+ print_line("close "+p_file+" flags "+itos(p_flags));
+ if (p_file.begins_with("/userfs") && p_flags&FileAccess::WRITE) {
+ static_cast<OS_JavaScript*>(get_singleton())->last_sync_time=OS::get_singleton()->get_ticks_msec();
+ static_cast<OS_JavaScript*>(get_singleton())->time_to_save_sync=5000; //five seconds since last save
+ }
+}
OS_JavaScript::OS_JavaScript(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func) {
@@ -589,6 +623,9 @@ OS_JavaScript::OS_JavaScript(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, Ope
open_uri_func=p_open_uri_func;
get_data_dir_func=p_get_data_dir_func;
get_locale_func=p_get_locale_func;
+ FileAccessUnix::close_notification_func=_close_notification_funcs;
+
+ time_to_save_sync=-1;
}
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 81bb474401..55ac7cdae4 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -38,7 +38,7 @@
#include "servers/audio/audio_server_sw.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/visual/rasterizer.h"
-
+#include "audio_server_javascript.h"
#include "audio_driver_javascript.h"
typedef void (*GFXInitFunc)(void *ud,bool gl2,int w, int h, bool fs);
@@ -65,10 +65,13 @@ private:
bool use_gl2;
+ int64_t time_to_save_sync;
+ int64_t last_sync_time;
+
Rasterizer *rasterizer;
VisualServer *visual_server;
- AudioServerSW *audio_server;
- SampleManagerMallocSW *sample_manager;
+ AudioServerJavascript *audio_server;
+ //SampleManagerMallocSW *sample_manager;
SpatialSoundServerSW *spatial_sound_server;
SpatialSound2DServerSW *spatial_sound_2d_server;
PhysicsServer *physics_server;
@@ -84,6 +87,8 @@ private:
GetDataDirFunc get_data_dir_func;
GetLocaleFunc get_locale_func;
+ static void _close_notification_funcs(const String& p_file,int p_flags);
+
public:
// functions used by main to initialize/deintialize the OS
@@ -106,7 +111,7 @@ public:
typedef int64_t ProcessID;
- static OS* get_singleton();
+ //static OS* get_singleton();
virtual void vprint(const char* p_format, va_list p_list, bool p_stderr=false);
virtual void print(const char *p_format, ... );
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 5703cbc546..4a20ca80c1 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -11,15 +11,17 @@ def get_name():
def can_build():
- if (sys.platform != "darwin"):
- return False
+ if (sys.platform == "darwin" or os.environ.has_key("OSXCROSS_ROOT")):
+ return True
- return True # osx enabled
+
+ return False
def get_opts():
return [
('force_64_bits','Force 64 bits binary','no'),
+ ('osxcross_sdk','OSXCross SDK version','darwin14'),
]
@@ -29,6 +31,7 @@ def get_flags():
('opengl', 'no'),
('legacygl', 'yes'),
('builtin_zlib', 'no'),
+ ("theora","no"),
('freetype','builtin'), #use builtin freetype
]
@@ -59,12 +62,31 @@ def configure(env):
env.Append(CPPPATH=['#tools/freetype'])
env.Append(CPPPATH=['#tools/freetype/freetype/include'])
- if (env["bits"]=="64"):
- env.Append(CCFLAGS=['-arch', 'x86_64'])
- env.Append(LINKFLAGS=['-arch', 'x86_64'])
+
+
+ if (not os.environ.has_key("OSXCROSS_ROOT")):
+ #regular native build
+ if (env["bits"]=="64"):
+ env.Append(CCFLAGS=['-arch', 'x86_64'])
+ env.Append(LINKFLAGS=['-arch', 'x86_64'])
+ else:
+ env.Append(CCFLAGS=['-arch', 'i386'])
+ env.Append(LINKFLAGS=['-arch', 'i386'])
else:
- env.Append(CCFLAGS=['-arch', 'i386'])
- env.Append(LINKFLAGS=['-arch', 'i386'])
+ #osxcross build
+ root=os.environ.get("OSXCROSS_ROOT",0)
+ if env["bits"]=="64":
+ basecmd=root+"/target/bin/x86_64-apple-"+env["osxcross_sdk"]+"-"
+ else:
+ basecmd=root+"/target/bin/i386-apple-"+env["osxcross_sdk"]+"-"
+
+
+ env['CC'] = basecmd+"cc"
+ env['CXX'] = basecmd+"c++"
+ env['AR'] = basecmd+"ar"
+ env['RANLIB'] = basecmd+"ranlib"
+ env['AS'] = basecmd+"as"
+
# env.Append(CPPPATH=['#platform/osx/include/freetype2', '#platform/osx/include'])
# env.Append(LIBPATH=['#platform/osx/lib'])
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 144037b1cb..869997f190 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -170,7 +170,7 @@ public:
virtual int get_screen_count() const;
virtual int get_current_screen() const;
virtual void set_current_screen(int p_screen);
- virtual Point2 get_screen_position(int p_screen=0);
+ virtual Point2 get_screen_position(int p_screen=0) const;
virtual Point2 get_window_position() const;
virtual void set_window_position(const Point2& p_position);
virtual void set_window_size(const Size2 p_size);
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 72699366c4..abfe42beda 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1279,7 +1279,7 @@ void OS_OSX::set_current_screen(int p_screen) {
current_screen = p_screen;
};
-Point2 OS_OSX::get_screen_position(int p_screen) {
+Point2 OS_OSX::get_screen_position(int p_screen) const {
ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2());
return screens[p_screen].pos;
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index ff85e286db..33e8fd03e2 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -126,11 +126,22 @@ def configure(env):
env.ParseConfig('pkg-config x11 --cflags --libs')
env.ParseConfig('pkg-config xinerama --cflags --libs')
env.ParseConfig('pkg-config xcursor --cflags --libs')
- env.ParseConfig('pkg-config openssl --cflags --libs')
+
+ if (env["openssl"]=="yes"):
+ env.ParseConfig('pkg-config openssl --cflags --libs')
+
+
+ if (env["freetype"]=="yes"):
+ env.ParseConfig('pkg-config freetype2 --cflags --libs')
+
+
+ if (env["freetype"]!="no"):
+ env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
+ if (env["freetype"]=="builtin"):
+ env.Append(CPPPATH=['#tools/freetype'])
+ env.Append(CPPPATH=['#tools/freetype/freetype/include'])
- env.ParseConfig('pkg-config freetype2 --cflags --libs')
- env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
env.Append(CPPFLAGS=['-DOPENGL_ENABLED','-DGLEW_ENABLED'])
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index b34d1ba7c8..51f4392eb4 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -441,6 +441,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False);
+
//printf("got map notify\n");
}
@@ -504,6 +505,23 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
mouse_mode=p_mode;
if (mouse_mode==MOUSE_MODE_CAPTURED) {
+
+ while(true) {
+ //flush pending motion events
+
+ if (XPending(x11_display) > 0) {
+ XEvent event;
+ XPeekEvent(x11_display, &event);
+ if (event.type==MotionNotify) {
+ XNextEvent(x11_display,&event);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
if (XGrabPointer(x11_display, x11_window, True,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync, GrabModeAsync,
@@ -518,6 +536,8 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
0,0,0,0, (int)center.x, (int)center.y);
input->set_mouse_pos(center);
+ } else {
+ do_mouse_warp=false;
}
}
@@ -652,17 +672,24 @@ void OS_X11::set_current_screen(int p_screen) {
}
Point2 OS_X11::get_screen_position(int p_screen) const {
+
// Using Xinerama Extension
int event_base, error_base;
const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
- if( !ext_okay ) return Point2i(0,0);
+ if( !ext_okay ) {
+ return Point2i(0,0);
+ }
int count;
XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count);
- if( p_screen >= count ) return Point2i(0,0);
+ if( p_screen >= count ) {
+ return Point2i(0,0);
+ }
Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org);
+
XFree(xsi);
+
return position;
}
@@ -696,6 +723,7 @@ Point2 OS_X11::get_window_position() const {
void OS_X11::set_window_position(const Point2& p_position) {
// Using EWMH -- Extended Window Manager Hints
// to get the size of the decoration
+#if 0
Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True);
Atom type;
int format;
@@ -738,6 +766,9 @@ void OS_X11::set_window_position(const Point2& p_position) {
top -= screen_position.y;
XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top);
+#else
+ XMoveWindow(x11_display,x11_window,p_position.x,p_position.y);
+#endif
}
Size2 OS_X11::get_window_size() const {
@@ -1131,7 +1162,7 @@ void OS_X11::process_xevents() {
//printf("checking events %i\n", XPending(x11_display));
- bool do_mouse_warp=false;
+ do_mouse_warp=false;
while (XPending(x11_display) > 0) {
XEvent event;
@@ -1244,8 +1275,38 @@ void OS_X11::process_xevents() {
} break;
case MotionNotify: {
-
+
+ // FUCK YOU X11 API YOU SERIOUSLY GROSS ME OUT
+ // YOU ARE AS GROSS AS LOOKING AT A PUTRID PILE
+ // OF POOP STICKING OUT OF A CLOGGED TOILET
+ // HOW THE FUCK I AM SUPPOSED TO KNOW WHICH ONE
+ // OF THE MOTION NOTIFY EVENTS IS THE ONE GENERATED
+ // BY WARPING THE MOUSE POINTER?
+ // YOU ARE FORCING ME TO FILTER ONE BY ONE TO FIND IT
+ // PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL
+ // MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.
+
+ while(true) {
+ if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) {
+ //this is likely the warp event since it was warped here
+ center=Vector2(event.xmotion.x,event.xmotion.y);
+ break;
+ }
+
+ if (XPending(x11_display) > 0) {
+ XEvent tevent;
+ XPeekEvent(x11_display, &tevent);
+ if (tevent.type==MotionNotify) {
+ XNextEvent(x11_display,&event);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
last_timestamp=event.xmotion.time;
// Motion is also simple.
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 261a54dd25..12f0aec611 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -114,6 +114,7 @@ class OS_X11 : public OS_Unix {
bool minimized;
int dpad_last[2];
+ bool do_mouse_warp;
const char *cursor_theme;
int cursor_size;
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 92d5088b81..49229ba500 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -1172,6 +1172,14 @@ Matrix32 CanvasItem::get_viewport_transform() const {
}
+void CanvasItem::set_notify_local_transform(bool p_enable) {
+ notify_local_transform=p_enable;
+}
+
+bool CanvasItem::is_local_transform_notification_enabled() const {
+ return notify_local_transform;
+}
+
CanvasItem::CanvasItem() : xform_change(this) {
@@ -1191,6 +1199,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
canvas_layer=NULL;
use_parent_material=false;
global_invalid=true;
+ notify_local_transform=false;
light_mask=1;
C=NULL;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 6d8308dbe4..4885256c64 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -126,6 +126,7 @@ private:
bool block_transform_notify;
bool behind;
bool use_parent_material;
+ bool notify_local_transform;
Ref<CanvasItemMaterial> material;
@@ -155,7 +156,7 @@ private:
protected:
- _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
+ _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify && notify_local_transform) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
void item_rect_changed();
@@ -263,6 +264,10 @@ public:
Vector2 get_global_mouse_pos() const;
Vector2 get_local_mouse_pos() const;
+ void set_notify_local_transform(bool p_enable);
+ bool is_local_transform_notification_enabled() const;
+
+
CanvasItem();
~CanvasItem();
};
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index ceea41d1c8..8a5e2f51d1 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -33,7 +33,7 @@
void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
- if (unparenting)
+ if (unparenting || !can_update_body)
return;
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
@@ -49,6 +49,7 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
+ shape_from=co->get_shape_count();
for(int i=0;i<decomp.size();i++) {
Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D );
convex->set_points(decomp[i]);
@@ -57,6 +58,11 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
co->set_shape_as_trigger(co->get_shape_count()-1,true);
}
+ shape_to=co->get_shape_count()-1;
+ if (shape_to<shape_from) {
+ shape_from=-1;
+ shape_to=-1;
+ }
} else {
@@ -78,6 +84,9 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
if (trigger)
co->set_shape_as_trigger(co->get_shape_count()-1,true);
+ shape_from=co->get_shape_count()-1;
+ shape_to=co->get_shape_count()-1;
+
}
@@ -86,6 +95,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
void CollisionPolygon2D::_update_parent() {
+ if (!can_update_body)
+ return;
Node *parent = get_parent();
if (!parent)
return;
@@ -101,12 +112,24 @@ void CollisionPolygon2D::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting=false;
+ can_update_body=get_tree()->is_editor_hint();
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ can_update_body=false;
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (!is_inside_tree())
break;
- _update_parent();
+ if (can_update_body) {
+ _update_parent();
+ } else if (shape_from>=0 && shape_to>=0) {
+ CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
+ for(int i=shape_from;i<=shape_to;i++) {
+ co->set_shape_transform(i,get_transform());
+ }
+ }
+
} break;
@@ -141,20 +164,22 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2>& p_polygon) {
polygon=p_polygon;
- for(int i=0;i<polygon.size();i++) {
- if (i==0)
- aabb=Rect2(polygon[i],Size2());
- else
- aabb.expand_to(polygon[i]);
- }
- if (aabb==Rect2()) {
+ if (can_update_body) {
+ for(int i=0;i<polygon.size();i++) {
+ if (i==0)
+ aabb=Rect2(polygon[i],Size2());
+ else
+ aabb.expand_to(polygon[i]);
+ }
+ if (aabb==Rect2()) {
- aabb=Rect2(-10,-10,20,20);
- } else {
- aabb.pos-=aabb.size*0.3;
- aabb.size+=aabb.size*0.6;
+ aabb=Rect2(-10,-10,20,20);
+ } else {
+ aabb.pos-=aabb.size*0.3;
+ aabb.size+=aabb.size*0.6;
+ }
+ _update_parent();
}
- _update_parent();
update();
}
@@ -184,6 +209,13 @@ void CollisionPolygon2D::set_trigger(bool p_trigger) {
trigger=p_trigger;
_update_parent();
+ if (!can_update_body && is_inside_tree() && shape_from>=0 && shape_to>=0) {
+ CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
+ for(int i=shape_from;i<=shape_to;i++) {
+ co->set_shape_as_trigger(i,p_trigger);
+ }
+
+ }
}
bool CollisionPolygon2D::is_trigger() const{
@@ -192,6 +224,17 @@ bool CollisionPolygon2D::is_trigger() const{
}
+void CollisionPolygon2D::_set_shape_range(const Vector2& p_range) {
+
+ shape_from=p_range.x;
+ shape_to=p_range.y;
+}
+
+Vector2 CollisionPolygon2D::_get_shape_range() const {
+
+ return Vector2(shape_from,shape_to);
+}
+
void CollisionPolygon2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object);
@@ -204,9 +247,17 @@ void CollisionPolygon2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger);
ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger);
+ ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon2D::_set_shape_range);
+ ObjectTypeDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon2D::_get_shape_range);
+
+ ObjectTypeDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon2D::get_collision_object_first_shape);
+ ObjectTypeDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon2D::get_collision_object_last_shape);
+
ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
+
}
CollisionPolygon2D::CollisionPolygon2D() {
@@ -215,6 +266,9 @@ CollisionPolygon2D::CollisionPolygon2D() {
build_mode=BUILD_SOLIDS;
trigger=false;
unparenting=false;
-
+ shape_from=-1;
+ shape_to=-1;
+ can_update_body=false;
+ set_notify_local_transform(true);
}
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index 4e78868082..4bc9713c8a 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -56,6 +56,14 @@ protected:
void _add_to_collision_object(Object *p_obj);
void _update_parent();
+ bool can_update_body;
+ int shape_from;
+ int shape_to;
+
+ void _set_shape_range(const Vector2& p_range);
+ Vector2 _get_shape_range() const;
+
+
protected:
void _notification(int p_what);
@@ -72,6 +80,10 @@ public:
Vector<Point2> get_polygon() const;
virtual Rect2 get_item_rect() const;
+
+ int get_collision_object_first_shape() const { return shape_from; }
+ int get_collision_object_last_shape() const { return shape_to; }
+
CollisionPolygon2D();
};
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 5012c54b17..a0a015a99e 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -44,10 +44,12 @@ void CollisionShape2D::_add_to_collision_object(Object *p_obj) {
CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
ERR_FAIL_COND(!co);
+ update_shape_index=co->get_shape_count();
co->add_shape(shape,get_transform());
if (trigger)
co->set_shape_as_trigger(co->get_shape_count()-1,true);
+
}
void CollisionShape2D::_shape_changed() {
@@ -74,12 +76,27 @@ void CollisionShape2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting=false;
+ can_update_body=get_tree()->is_editor_hint();
+
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
if (!is_inside_tree())
break;
- _update_parent();
+ if (can_update_body) {
+ _update_parent();
+ } else if (update_shape_index>=0){
+
+ CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
+ if (co) {
+ co->set_shape_transform(update_shape_index,get_transform());
+ }
+
+ }
+
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ can_update_body=false;
} break;
/*
@@ -92,6 +109,9 @@ void CollisionShape2D::_notification(int p_what) {
} break;*/
case NOTIFICATION_DRAW: {
+ if (!get_tree()->is_editor_hint())
+ return;
+
rect=Rect2();
Color draw_col=Color(0,0.6,0.7,0.5);
@@ -209,7 +229,14 @@ void CollisionShape2D::set_shape(const Ref<Shape2D>& p_shape) {
shape->disconnect("changed",this,"_shape_changed");
shape=p_shape;
update();
- _update_parent();
+ if (is_inside_tree() && can_update_body)
+ _update_parent();
+ if (is_inside_tree() && !can_update_body && update_shape_index>=0) {
+ CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
+ if (co) {
+ co->set_shape(update_shape_index,p_shape);
+ }
+ }
if (shape.is_valid())
shape->connect("changed",this,"_shape_changed");
@@ -228,7 +255,14 @@ Rect2 CollisionShape2D::get_item_rect() const {
void CollisionShape2D::set_trigger(bool p_trigger) {
trigger=p_trigger;
- _update_parent();
+ if (can_update_body) {
+ _update_parent();
+ } else if (is_inside_tree() && update_shape_index>=0){
+ CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>();
+ if (co) {
+ co->set_shape_as_trigger(update_shape_index,p_trigger);
+ }
+ }
}
bool CollisionShape2D::is_trigger() const{
@@ -236,6 +270,19 @@ bool CollisionShape2D::is_trigger() const{
return trigger;
}
+
+void CollisionShape2D::_set_update_shape_index(int p_index) {
+
+
+ update_shape_index=p_index;
+}
+
+int CollisionShape2D::_get_update_shape_index() const{
+
+ return update_shape_index;
+}
+
+
void CollisionShape2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape);
@@ -245,14 +292,23 @@ void CollisionShape2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger);
ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape2D::is_trigger);
+ ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape2D::_set_update_shape_index);
+ ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape2D::_get_update_shape_index);
+
+ ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape2D::get_collision_object_shape_index);
+
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),_SCS("set_shape"),_SCS("get_shape"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index"));
+
}
CollisionShape2D::CollisionShape2D() {
rect=Rect2(-Point2(10,10),Point2(20,20));
-
+ set_notify_local_transform(true);
trigger=false;
unparenting = false;
+ can_update_body = false;
+ update_shape_index=-1;
}
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 507912d31e..82e1137174 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -39,7 +39,13 @@ class CollisionShape2D : public Node2D {
Rect2 rect;
bool trigger;
bool unparenting;
+ bool can_update_body;
void _shape_changed();
+ int update_shape_index;
+
+ void _set_update_shape_index(int p_index);
+ int _get_update_shape_index() const;
+
protected:
void _update_parent();
@@ -55,6 +61,8 @@ public:
void set_trigger(bool p_trigger);
bool is_trigger() const;
+ int get_collision_object_shape_index() const { return _get_update_shape_index(); }
+
CollisionShape2D();
};
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index c521952f9b..6705cebf37 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -322,8 +322,8 @@ void Sprite::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes"));
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 58cbbdba22..ff35837bc0 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -83,15 +83,25 @@ real_t Area::get_gravity() const{
return gravity;
}
+void Area::set_linear_damp(real_t p_linear_damp){
-void Area::set_density(real_t p_density){
+ linear_damp=p_linear_damp;
+ PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_LINEAR_DAMP,p_linear_damp);
+}
+real_t Area::get_linear_damp() const{
+
+ return linear_damp;
+}
- density=p_density;
- PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_DENSITY,p_density);
+void Area::set_angular_damp(real_t p_angular_damp){
+
+ angular_damp=p_angular_damp;
+ PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_ANGULAR_DAMP,p_angular_damp);
}
-real_t Area::get_density() const{
- return density;
+real_t Area::get_angular_damp() const{
+
+ return angular_damp;
}
void Area::set_priority(real_t p_priority){
@@ -533,8 +543,11 @@ void Area::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_gravity","gravity"),&Area::set_gravity);
ObjectTypeDB::bind_method(_MD("get_gravity"),&Area::get_gravity);
- ObjectTypeDB::bind_method(_MD("set_density","density"),&Area::set_density);
- ObjectTypeDB::bind_method(_MD("get_density"),&Area::get_density);
+ ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&Area::set_angular_damp);
+ ObjectTypeDB::bind_method(_MD("get_angular_damp"),&Area::get_angular_damp);
+
+ ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&Area::set_linear_damp);
+ ObjectTypeDB::bind_method(_MD("get_linear_damp"),&Area::get_linear_damp);
ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority);
@@ -571,7 +584,8 @@ void Area::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
@@ -586,7 +600,8 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru
set_gravity_vector(Vector3(0,-1,0));
gravity_is_point=false;
gravity_distance_scale=0;
- density=0.1;
+ linear_damp=0.1;
+ angular_damp=1;
priority=0;
monitoring=false;
set_ray_pickable(false);
diff --git a/scene/3d/area.h b/scene/3d/area.h
index fa7500c47c..f03955d1e7 100644
--- a/scene/3d/area.h
+++ b/scene/3d/area.h
@@ -50,7 +50,8 @@ private:
real_t gravity;
bool gravity_is_point;
real_t gravity_distance_scale;
- real_t density;
+ real_t angular_damp;
+ real_t linear_damp;
int priority;
bool monitoring;
bool monitorable;
@@ -139,8 +140,11 @@ public:
void set_gravity(real_t p_gravity);
real_t get_gravity() const;
- void set_density(real_t p_density);
- real_t get_density() const;
+ void set_angular_damp(real_t p_angular_damp);
+ real_t get_angular_damp() const;
+
+ void set_linear_damp(real_t p_linear_damp);
+ real_t get_linear_damp() const;
void set_priority(real_t p_priority);
real_t get_priority() const;
diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp
index c49d1b028c..709a79a5f4 100644
--- a/scene/3d/body_shape.cpp
+++ b/scene/3d/body_shape.cpp
@@ -43,7 +43,10 @@
void CollisionShape::_update_body() {
-
+ if (!get_tree() || !can_update_body)
+ return;
+ if (!get_tree()->is_editor_hint())
+ return;
if (get_parent() && get_parent()->cast_to<CollisionObject>())
get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
@@ -310,10 +313,13 @@ void CollisionShape::_add_to_collision_object(Object* p_cshape) {
if (shape.is_valid()) {
+ update_shape_index=co->get_shape_count();
co->add_shape(shape,get_transform());
- if (trigger)
- co->set_shape_as_trigger( co->get_shape_count() -1, true );
- }
+ if (trigger)
+ co->set_shape_as_trigger( co->get_shape_count() -1, true );
+ } else {
+ update_shape_index=-1;
+ }
}
void CollisionShape::_notification(int p_what) {
@@ -322,12 +328,14 @@ void CollisionShape::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
unparenting=false;
+ can_update_body=get_tree()->is_editor_hint();
+ set_notify_local_transform(!can_update_body);
//indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
// VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
- if (updating_body) {
+ if (can_update_body && updating_body) {
_update_body();
}
} break;
@@ -336,16 +344,30 @@ void CollisionShape::_notification(int p_what) {
VisualServer::get_singleton()->free(indicator_instance);
indicator_instance=RID();
}*/
+ can_update_body=false;
+ set_notify_local_transform(false);
} break;
case NOTIFICATION_UNPARENTED: {
unparenting=true;
- if (updating_body)
+ if (can_update_body && updating_body)
_update_body();
} break;
case NOTIFICATION_PARENTED: {
- if (updating_body)
+ if (can_update_body && updating_body)
_update_body();
} break;
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+
+ if (!can_update_body && update_shape_index>=0) {
+
+ CollisionObject *co = get_parent()->cast_to<CollisionObject>();
+ if (co) {
+ co->set_shape_transform(update_shape_index,get_transform());
+ }
+ }
+
+ } break;
+
}
}
@@ -357,6 +379,18 @@ void CollisionShape::resource_changed(RES res) {
}
+void CollisionShape::_set_update_shape_index(int p_index) {
+
+
+ update_shape_index=p_index;
+}
+
+int CollisionShape::_get_update_shape_index() const{
+
+ return update_shape_index;
+}
+
+
void CollisionShape::_bind_methods() {
//not sure if this should do anything
@@ -368,10 +402,14 @@ void CollisionShape::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger);
ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers);
ObjectTypeDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index);
+ ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index);
+ ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index);
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index"));
}
@@ -383,8 +421,15 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
if (!shape.is_null())
shape->register_owner(this);
update_gizmo();
- if (updating_body)
+ if (updating_body) {
_update_body();
+ } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){
+ CollisionObject *co = get_parent()->cast_to<CollisionObject>();
+ if (co) {
+ co->set_shape(update_shape_index,p_shape);
+ }
+
+ }
}
Ref<Shape> CollisionShape::get_shape() const {
@@ -405,8 +450,14 @@ bool CollisionShape::is_updating_body() const {
void CollisionShape::set_trigger(bool p_trigger) {
trigger=p_trigger;
- if (updating_body)
+ if (updating_body) {
_update_body();
+ } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){
+ CollisionObject *co = get_parent()->cast_to<CollisionObject>();
+ if (co) {
+ co->set_shape_as_trigger(update_shape_index,p_trigger);
+ }
+ }
}
bool CollisionShape::is_trigger() const{
@@ -419,7 +470,9 @@ CollisionShape::CollisionShape() {
//indicator = VisualServer::get_singleton()->mesh_create();
updating_body=true;
unparenting=false;
- trigger=false;
+ update_shape_index=-1;
+ trigger=false;
+ can_update_body=false;
}
CollisionShape::~CollisionShape() {
diff --git a/scene/3d/body_shape.h b/scene/3d/body_shape.h
index b3c0006d79..c1ebf806a9 100644
--- a/scene/3d/body_shape.h
+++ b/scene/3d/body_shape.h
@@ -56,8 +56,16 @@ class CollisionShape : public Spatial {
bool unparenting;
bool trigger;
+ bool can_update_body;
+
+ int update_shape_index;
+
void _update_body();
void _add_to_collision_object(Object* p_cshape);
+
+ void _set_update_shape_index(int p_index);
+ int _get_update_shape_index() const;
+
protected:
void _notification(int p_what);
@@ -73,8 +81,10 @@ public:
void set_updating_body(bool p_update);
bool is_updating_body() const;
- void set_trigger(bool p_trigger);
- bool is_trigger() const;
+ void set_trigger(bool p_trigger);
+ bool is_trigger() const;
+
+ int get_collision_object_shape_index() const { return _get_update_shape_index(); }
CollisionShape();
~CollisionShape();
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index 4ab1a1a1ab..c857b4851a 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -6,6 +6,8 @@
void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
+ if (!can_update_body)
+ return;
CollisionObject *co = p_obj->cast_to<CollisionObject>();
ERR_FAIL_COND(!co);
@@ -23,6 +25,7 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
+ shape_from=co->get_shape_count();
for(int i=0;i<decomp.size();i++) {
Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape );
DVector<Vector3> cp;
@@ -43,6 +46,11 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
co->add_shape(convex,get_transform());
}
+ shape_to=co->get_shape_count()-1;
+ if (shape_to<shape_from) {
+ shape_from=-1;
+ shape_to=-1;
+ }
} else {
#if 0
@@ -71,6 +79,9 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
void CollisionPolygon::_update_parent() {
+ if (!can_update_body)
+ return;
+
Node *parent = get_parent();
if (!parent)
return;
@@ -80,15 +91,50 @@ void CollisionPolygon::_update_parent() {
co->_update_shapes_from_children();
}
+void CollisionPolygon::_set_shape_range(const Vector2& p_range) {
+
+ shape_from=p_range.x;
+ shape_to=p_range.y;
+}
+
+Vector2 CollisionPolygon::_get_shape_range() const {
+
+ return Vector2(shape_from,shape_to);
+}
+
void CollisionPolygon::_notification(int p_what) {
switch(p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ can_update_body=get_tree()->is_editor_hint();
+ set_notify_local_transform(!can_update_body);
+
+ //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ can_update_body=false;
+ set_notify_local_transform(false);
+ } break;
case NOTIFICATION_TRANSFORM_CHANGED: {
if (!is_inside_tree())
break;
- _update_parent();
+ if (can_update_body) {
+ _update_parent();
+ }
+
+ } break;
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ if (!can_update_body && shape_from>=0 && shape_from>=0) {
+
+ CollisionObject *co = get_parent()->cast_to<CollisionObject>();
+ if (co) {
+ for(int i=shape_from;i<=shape_to;i++) {
+ co->set_shape_transform(i,get_transform());
+ }
+ }
+ }
} break;
#if 0
@@ -119,29 +165,31 @@ void CollisionPolygon::_notification(int p_what) {
void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) {
polygon=p_polygon;
+ if (can_update_body) {
- for(int i=0;i<polygon.size();i++) {
+ for(int i=0;i<polygon.size();i++) {
- Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5);
+ Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5);
- if (i==0)
- aabb=AABB(p1,Vector3());
- else
- aabb.expand_to(p1);
+ if (i==0)
+ aabb=AABB(p1,Vector3());
+ else
+ aabb.expand_to(p1);
- Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5);
- aabb.expand_to(p2);
+ Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5);
+ aabb.expand_to(p2);
- }
- if (aabb==AABB()) {
+ }
+ if (aabb==AABB()) {
- aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
- } else {
- aabb.pos-=aabb.size*0.3;
- aabb.size+=aabb.size*0.6;
+ aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+ } else {
+ aabb.pos-=aabb.size*0.3;
+ aabb.size+=aabb.size*0.6;
+ }
+ _update_parent();
}
- _update_parent();
update_gizmo();
}
@@ -154,6 +202,8 @@ void CollisionPolygon::set_build_mode(BuildMode p_mode) {
ERR_FAIL_INDEX(p_mode,2);
build_mode=p_mode;
+ if (!can_update_body)
+ return;
_update_parent();
}
@@ -170,6 +220,8 @@ AABB CollisionPolygon::get_item_rect() const {
void CollisionPolygon::set_depth(float p_depth) {
depth=p_depth;
+ if (!can_update_body)
+ return;
_update_parent();
update_gizmo();
}
@@ -183,22 +235,34 @@ float CollisionPolygon::get_depth() const {
void CollisionPolygon::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object);
- ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon);
- ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon);
+
+ ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode);
+ ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode);
ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth);
ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth);
- ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode);
- ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode);
+ ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon);
+ ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon);
+
+ ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon::_set_shape_range);
+ ObjectTypeDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon::_get_shape_range);
+
+ ObjectTypeDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon::get_collision_object_first_shape);
+ ObjectTypeDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon::get_collision_object_last_shape);
ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range"));
}
CollisionPolygon::CollisionPolygon() {
+ shape_from=-1;
+ shape_to=-1;
+ can_update_body=false;
+
aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
build_mode=BUILD_SOLIDS;
depth=1.0;
diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h
index efb3666778..9b9afea34f 100644
--- a/scene/3d/collision_polygon.h
+++ b/scene/3d/collision_polygon.h
@@ -24,9 +24,17 @@ protected:
BuildMode build_mode;
Vector<Point2> polygon;
+
void _add_to_collision_object(Object *p_obj);
void _update_parent();
+ bool can_update_body;
+ int shape_from;
+ int shape_to;
+
+ void _set_shape_range(const Vector2& p_range);
+ Vector2 _get_shape_range() const;
+
protected:
void _notification(int p_what);
@@ -43,6 +51,10 @@ public:
Vector<Point2> get_polygon() const;
virtual AABB get_item_rect() const;
+
+ int get_collision_object_first_shape() const { return shape_from; }
+ int get_collision_object_last_shape() const { return shape_to; }
+
CollisionPolygon();
};
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 3d5091f667..d61859a3d0 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -133,6 +133,8 @@ real_t StaticBody::get_bounce() const{
return bounce;
}
+
+
void StaticBody::set_constant_linear_velocity(const Vector3& p_vel) {
constant_linear_velocity=p_vel;
@@ -494,6 +496,42 @@ real_t RigidBody::get_bounce() const{
return bounce;
}
+
+void RigidBody::set_gravity_scale(real_t p_gravity_scale){
+
+ gravity_scale=p_gravity_scale;
+ PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_GRAVITY_SCALE,gravity_scale);
+
+}
+real_t RigidBody::get_gravity_scale() const{
+
+ return gravity_scale;
+}
+
+void RigidBody::set_linear_damp(real_t p_linear_damp){
+
+ ERR_FAIL_COND(p_linear_damp<-1);
+ linear_damp=p_linear_damp;
+ PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_LINEAR_DAMP,linear_damp);
+
+}
+real_t RigidBody::get_linear_damp() const{
+
+ return linear_damp;
+}
+
+void RigidBody::set_angular_damp(real_t p_angular_damp){
+
+ ERR_FAIL_COND(p_angular_damp<-1);
+ angular_damp=p_angular_damp;
+ PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_ANGULAR_DAMP,angular_damp);
+
+}
+real_t RigidBody::get_angular_damp() const{
+
+ return angular_damp;
+}
+
void RigidBody::set_axis_velocity(const Vector3& p_axis) {
Vector3 v = state? state->get_linear_velocity() : linear_velocity;
@@ -685,6 +723,16 @@ void RigidBody::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody::set_angular_velocity);
ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&RigidBody::get_angular_velocity);
+ ObjectTypeDB::bind_method(_MD("set_gravity_scale","gravity_scale"),&RigidBody::set_gravity_scale);
+ ObjectTypeDB::bind_method(_MD("get_gravity_scale"),&RigidBody::get_gravity_scale);
+
+ ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&RigidBody::set_linear_damp);
+ ObjectTypeDB::bind_method(_MD("get_linear_damp"),&RigidBody::get_linear_damp);
+
+ ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&RigidBody::set_angular_damp);
+ ObjectTypeDB::bind_method(_MD("get_angular_damp"),&RigidBody::get_angular_damp);
+
+
ObjectTypeDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody::set_max_contacts_reported);
ObjectTypeDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody::get_max_contacts_reported);
@@ -722,6 +770,7 @@ void RigidBody::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),_SCS("set_gravity_scale"),_SCS("get_gravity_scale"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
@@ -731,6 +780,8 @@ void RigidBody::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),_SCS("set_axis_lock"),_SCS("get_axis_lock"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/linear",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/angular",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
@@ -753,6 +804,10 @@ RigidBody::RigidBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
max_contacts_reported=0;
state=NULL;
+ gravity_scale=1;
+ linear_damp=-1;
+ angular_damp=-1;
+
//angular_velocity=0;
sleeping=false;
ccd=false;
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 0ff3b360af..66490ba925 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -129,6 +129,10 @@ private:
Vector3 linear_velocity;
Vector3 angular_velocity;
+ real_t gravity_scale;
+ real_t linear_damp;
+ real_t angular_damp;
+
bool sleeping;
bool ccd;
@@ -217,6 +221,16 @@ public:
void set_angular_velocity(const Vector3&p_velocity);
Vector3 get_angular_velocity() const;
+ void set_gravity_scale(real_t p_gravity_scale);
+ real_t get_gravity_scale() const;
+
+ void set_linear_damp(real_t p_linear_damp);
+ real_t get_linear_damp() const;
+
+ void set_angular_damp(real_t p_angular_damp);
+ real_t get_angular_damp() const;
+
+
void set_use_custom_integrator(bool p_enable);
bool is_using_custom_integrator();
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 7117c59176..a65f68ed2c 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -231,6 +231,11 @@ void Spatial::set_transform(const Transform& p_transform) {
_change_notify("transform/rotation");
_change_notify("transform/scale");
_propagate_transform_changed(this);
+ if (data.notify_local_transform) {
+ notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
+ }
+
+
}
@@ -335,6 +340,9 @@ void Spatial::set_translation(const Vector3& p_translation) {
data.local_transform.origin=p_translation;
_propagate_transform_changed(this);
+ if (data.notify_local_transform) {
+ notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
+ }
}
@@ -348,6 +356,9 @@ void Spatial::set_rotation(const Vector3& p_euler){
data.rotation=p_euler;
data.dirty|=DIRTY_LOCAL;
_propagate_transform_changed(this);
+ if (data.notify_local_transform) {
+ notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
+ }
}
void Spatial::set_scale(const Vector3& p_scale){
@@ -360,6 +371,9 @@ void Spatial::set_scale(const Vector3& p_scale){
data.scale=p_scale;
data.dirty|=DIRTY_LOCAL;
_propagate_transform_changed(this);
+ if (data.notify_local_transform) {
+ notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
+ }
}
@@ -685,6 +699,13 @@ void Spatial::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, con
}
+void Spatial::set_notify_local_transform(bool p_enable) {
+ data.notify_local_transform=p_enable;
+}
+
+bool Spatial::is_local_transform_notification_enabled() const {
+ return data.notify_local_transform;
+}
void Spatial::_bind_methods() {
@@ -725,6 +746,9 @@ void Spatial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_);
ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_);
+ ObjectTypeDB::bind_method(_MD("set_notify_local_transform","enable"), &Spatial::set_notify_local_transform);
+ ObjectTypeDB::bind_method(_MD("is_local_transform_notification_enabled"), &Spatial::is_local_transform_notification_enabled);
+
void rotate(const Vector3& p_normal,float p_radians);
void rotate_x(float p_radians);
void rotate_y(float p_radians);
@@ -783,6 +807,7 @@ Spatial::Spatial() : xform_change(this)
data.gizmo_disabled=false;
data.gizmo_dirty=false;
#endif
+ data.notify_local_transform=false;
data.parent=NULL;
data.C=NULL;
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 8b40786fb8..7fa6099d7a 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -91,6 +91,7 @@ class Spatial : public Node {
List<Spatial*>::Element *C;
bool ignore_notification;
+ bool notify_local_transform;
bool visible;
@@ -134,6 +135,7 @@ public:
NOTIFICATION_ENTER_WORLD=41,
NOTIFICATION_EXIT_WORLD=42,
NOTIFICATION_VISIBILITY_CHANGED=43,
+ NOTIFICATION_LOCAL_TRANSFORM_CHANGED=44,
};
Spatial *get_parent_spatial() const;
@@ -179,6 +181,9 @@ public:
void look_at(const Vector3& p_target, const Vector3& p_up_normal);
void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal);
+ void set_notify_local_transform(bool p_enable);
+ bool is_local_transform_notification_enabled() const;
+
void orthonormalize();
void set_identity();
diff --git a/scene/3d/spatial_stream_player.cpp b/scene/3d/spatial_stream_player.cpp
index 84e68bf418..b81d98e8bf 100644
--- a/scene/3d/spatial_stream_player.cpp
+++ b/scene/3d/spatial_stream_player.cpp
@@ -30,21 +30,79 @@
-void SpatialStreamPlayer::_notification(int p_what) {
+int SpatialStreamPlayer::InternalStream::get_channel_count() const {
- switch(p_what) {
+ return player->sp_get_channel_count();
+}
+void SpatialStreamPlayer::InternalStream::set_mix_rate(int p_rate){
- case NOTIFICATION_ENTER_WORLD: {
+ return player->sp_set_mix_rate(p_rate);
+}
+bool SpatialStreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){
+
+ return player->sp_mix(p_buffer,p_frames);
+}
+void SpatialStreamPlayer::InternalStream::update(){
+
+ player->sp_update();
+}
+
+
+int SpatialStreamPlayer::sp_get_channel_count() const {
+
+ return playback->get_channels();
+}
+
+void SpatialStreamPlayer::sp_set_mix_rate(int p_rate){
+
+ server_mix_rate=p_rate;
+}
+
+bool SpatialStreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) {
+
+ if (resampler.is_ready()) {
+ return resampler.mix(p_buffer,p_frames);
+ }
+
+ return false;
+}
+
+void SpatialStreamPlayer::sp_update() {
+
+ _THREAD_SAFE_METHOD_
+ if (!paused && resampler.is_ready() && playback.is_valid()) {
+
+ if (!playback->is_playing()) {
+ //stream depleted data, but there's still audio in the ringbuffer
+ //check that all this audio has been flushed before stopping the stream
+ int to_mix = resampler.get_total() - resampler.get_todo();
+ if (to_mix==0) {
+ stop();
+ return;
+ }
+
+ return;
+ }
+
+ int todo =resampler.get_todo();
+ int wrote = playback->mix(resampler.get_write_buffer(),todo);
+ resampler.write(wrote);
+ }
+}
-// set_idle_process(false); //don't annoy
- } break;
- case NOTIFICATION_PROCESS: {
-// if (!stream.is_null())
-// stream->update();
+void SpatialStreamPlayer::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ //set_idle_process(false); //don't annoy
+ if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint())
+ play();
} break;
- case NOTIFICATION_EXIT_WORLD: {
+ case NOTIFICATION_EXIT_TREE: {
stop(); //wathever it may be doing, stop
} break;
@@ -58,12 +116,20 @@ void SpatialStreamPlayer::set_stream(const Ref<AudioStream> &p_stream) {
stop();
stream=p_stream;
- if (!stream.is_null()) {
- stream->set_loop(loops);
+ if (!stream.is_null()) {
+ playback=stream->instance_playback();
+ playback->set_loop(loops);
+ playback->set_loop_restart_time(loop_point);
+ AudioServer::get_singleton()->lock();
+ resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size());
+ AudioServer::get_singleton()->unlock();
+ } else {
+ AudioServer::get_singleton()->lock();
+ resampler.clear();
+ playback.unref();
+ AudioServer::get_singleton()->unlock();
}
-
-
}
Ref<AudioStream> SpatialStreamPlayer::get_stream() const {
@@ -72,18 +138,25 @@ Ref<AudioStream> SpatialStreamPlayer::get_stream() const {
}
-void SpatialStreamPlayer::play() {
+void SpatialStreamPlayer::play(float p_from_offset) {
- if (!is_inside_tree())
+ ERR_FAIL_COND(!is_inside_tree());
+ if (playback.is_null())
return;
- if (stream.is_null())
- return;
- if (stream->is_playing())
+ if (playback->is_playing())
stop();
- stream->play();
- SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),stream->get_audio_stream());
- //if (stream->get_update_mode()!=AudioStream::UPDATE_NONE)
- // set_idle_process(true);
+
+ _THREAD_SAFE_METHOD_
+ playback->play(p_from_offset);
+ //feed the ringbuffer as long as no update callback is going on
+ sp_update();
+
+ SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),&internal_stream);
+
+// AudioServer::get_singleton()->stream_set_active(stream_rid,true);
+// AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume);
+// if (stream->get_update_mode()!=AudioStream::UPDATE_NONE)
+// set_idle_process(true);
}
@@ -91,28 +164,30 @@ void SpatialStreamPlayer::stop() {
if (!is_inside_tree())
return;
- if (stream.is_null())
+ if (playback.is_null())
return;
+ _THREAD_SAFE_METHOD_
+ //AudioServer::get_singleton()->stream_set_active(stream_rid,false);
SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),NULL);
- stream->stop();
+ playback->stop();
//set_idle_process(false);
}
bool SpatialStreamPlayer::is_playing() const {
- if (stream.is_null())
+ if (playback.is_null())
return false;
- return stream->is_playing();
+ return playback->is_playing();
}
void SpatialStreamPlayer::set_loop(bool p_enable) {
loops=p_enable;
- if (stream.is_null())
+ if (playback.is_null())
return;
- stream->set_loop(loops);
+ playback->set_loop(loops);
}
bool SpatialStreamPlayer::has_loop() const {
@@ -120,6 +195,46 @@ bool SpatialStreamPlayer::has_loop() const {
return loops;
}
+void SpatialStreamPlayer::set_volume(float p_vol) {
+
+ volume=p_vol;
+ if (stream_rid.is_valid())
+ AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume);
+}
+
+float SpatialStreamPlayer::get_volume() const {
+
+ return volume;
+}
+
+void SpatialStreamPlayer::set_loop_restart_time(float p_secs) {
+
+ loop_point=p_secs;
+ if (playback.is_valid())
+ playback->set_loop_restart_time(p_secs);
+}
+
+float SpatialStreamPlayer::get_loop_restart_time() const {
+
+ return loop_point;
+}
+
+
+void SpatialStreamPlayer::set_volume_db(float p_db) {
+
+ if (p_db<-79)
+ set_volume(0);
+ else
+ set_volume(Math::db2linear(p_db));
+}
+
+float SpatialStreamPlayer::get_volume_db() const {
+
+ if (volume==0)
+ return -80;
+ else
+ return Math::linear2db(volume);
+}
String SpatialStreamPlayer::get_stream_name() const {
@@ -132,27 +247,85 @@ String SpatialStreamPlayer::get_stream_name() const {
int SpatialStreamPlayer::get_loop_count() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_loop_count();
+ return playback->get_loop_count();
}
float SpatialStreamPlayer::get_pos() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_pos();
+ return playback->get_pos();
+
+}
+
+float SpatialStreamPlayer::get_length() const {
+ if (playback.is_null())
+ return 0;
+ return playback->get_length();
}
void SpatialStreamPlayer::seek_pos(float p_time) {
- if (stream.is_null())
+ if (playback.is_null())
return;
- return stream->seek_pos(p_time);
+ return playback->seek_pos(p_time);
+
+}
+
+void SpatialStreamPlayer::set_autoplay(bool p_enable) {
+
+ autoplay=p_enable;
+}
+
+bool SpatialStreamPlayer::has_autoplay() const {
+
+ return autoplay;
+}
+
+void SpatialStreamPlayer::set_paused(bool p_paused) {
+
+ paused=p_paused;
+ //if (stream.is_valid())
+ // stream->set_paused(p_paused);
+}
+
+bool SpatialStreamPlayer::is_paused() const {
+ return paused;
}
+void SpatialStreamPlayer::_set_play(bool p_play) {
+
+ _play=p_play;
+ if (is_inside_tree()) {
+ if(_play)
+ play();
+ else
+ stop();
+ }
+
+}
+
+bool SpatialStreamPlayer::_get_play() const{
+
+ return _play;
+}
+
+void SpatialStreamPlayer::set_buffering_msec(int p_msec) {
+
+ buffering_ms=p_msec;
+}
+
+int SpatialStreamPlayer::get_buffering_msec() const{
+
+ return buffering_ms;
+}
+
+
+
void SpatialStreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&SpatialStreamPlayer::set_stream);
@@ -163,28 +336,67 @@ void SpatialStreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_playing"),&SpatialStreamPlayer::is_playing);
+ ObjectTypeDB::bind_method(_MD("set_paused","paused"),&SpatialStreamPlayer::set_paused);
+ ObjectTypeDB::bind_method(_MD("is_paused"),&SpatialStreamPlayer::is_paused);
+
ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&SpatialStreamPlayer::set_loop);
ObjectTypeDB::bind_method(_MD("has_loop"),&SpatialStreamPlayer::has_loop);
+ ObjectTypeDB::bind_method(_MD("set_volume","volume"),&SpatialStreamPlayer::set_volume);
+ ObjectTypeDB::bind_method(_MD("get_volume"),&SpatialStreamPlayer::get_volume);
+
+ ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&SpatialStreamPlayer::set_volume_db);
+ ObjectTypeDB::bind_method(_MD("get_volume_db"),&SpatialStreamPlayer::get_volume_db);
+
+ ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&SpatialStreamPlayer::set_buffering_msec);
+ ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&SpatialStreamPlayer::get_buffering_msec);
+
+ ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&SpatialStreamPlayer::set_loop_restart_time);
+ ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&SpatialStreamPlayer::get_loop_restart_time);
+
ObjectTypeDB::bind_method(_MD("get_stream_name"),&SpatialStreamPlayer::get_stream_name);
ObjectTypeDB::bind_method(_MD("get_loop_count"),&SpatialStreamPlayer::get_loop_count);
ObjectTypeDB::bind_method(_MD("get_pos"),&SpatialStreamPlayer::get_pos);
ObjectTypeDB::bind_method(_MD("seek_pos","time"),&SpatialStreamPlayer::seek_pos);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"),_SCS("get_stream") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"),_SCS("has_loop") );
+ ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&SpatialStreamPlayer::set_autoplay);
+ ObjectTypeDB::bind_method(_MD("has_autoplay"),&SpatialStreamPlayer::has_autoplay);
+ ObjectTypeDB::bind_method(_MD("get_length"),&SpatialStreamPlayer::get_length);
+
+ ObjectTypeDB::bind_method(_MD("_set_play","play"),&SpatialStreamPlayer::_set_play);
+ ObjectTypeDB::bind_method(_MD("_get_play"),&SpatialStreamPlayer::_get_play);
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"), _SCS("get_stream") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/play"), _SCS("_set_play"), _SCS("_get_play") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") );
}
SpatialStreamPlayer::SpatialStreamPlayer() {
+ volume=1;
loops=false;
+ paused=false;
+ autoplay=false;
+ _play=false;
+ server_mix_rate=1;
+ internal_stream.player=this;
+ stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream);
+ buffering_ms=500;
+ loop_point=0;
+
}
SpatialStreamPlayer::~SpatialStreamPlayer() {
-
-}
+ AudioServer::get_singleton()->free(stream_rid);
+ resampler.clear();
+}
diff --git a/scene/3d/spatial_stream_player.h b/scene/3d/spatial_stream_player.h
index 7e639a7232..f2775a4982 100644
--- a/scene/3d/spatial_stream_player.h
+++ b/scene/3d/spatial_stream_player.h
@@ -31,16 +31,48 @@
#include "scene/resources/audio_stream.h"
#include "scene/3d/spatial_player.h"
-
+#include "servers/audio/audio_rb_resampler.h"
class SpatialStreamPlayer : public SpatialPlayer {
OBJ_TYPE(SpatialStreamPlayer,SpatialPlayer);
+ _THREAD_SAFE_CLASS_
+
+ struct InternalStream : public AudioServer::AudioStream {
+ SpatialStreamPlayer *player;
+ virtual int get_channel_count() const;
+ virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
+ virtual bool mix(int32_t *p_buffer,int p_frames);
+ virtual void update();
+ };
+
+
+ InternalStream internal_stream;
+ Ref<AudioStreamPlayback> playback;
Ref<AudioStream> stream;
+
+ int sp_get_channel_count() const;
+ void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate
+ bool sp_mix(int32_t *p_buffer,int p_frames);
+ void sp_update();
+
+ int server_mix_rate;
+
+ RID stream_rid;
+ bool paused;
+ bool autoplay;
bool loops;
-protected:
+ float volume;
+ float loop_point;
+ int buffering_ms;
+ AudioRBResampler resampler;
+
+ bool _play;
+ void _set_play(bool p_play);
+ bool _get_play() const;
+protected:
void _notification(int p_what);
static void _bind_methods();
@@ -49,21 +81,37 @@ public:
void set_stream(const Ref<AudioStream> &p_stream);
Ref<AudioStream> get_stream() const;
- void play();
+ void play(float p_from_offset=0);
void stop();
bool is_playing() const;
+ void set_paused(bool p_paused);
+ bool is_paused() const;
+
void set_loop(bool p_enable);
bool has_loop() const;
+ void set_volume(float p_vol);
+ float get_volume() const;
+
+ void set_loop_restart_time(float p_secs);
+ float get_loop_restart_time() const;
+
+ void set_volume_db(float p_db);
+ float get_volume_db() const;
String get_stream_name() const;
- int get_loop_count() const;
+ int get_loop_count() const;
float get_pos() const;
void seek_pos(float p_time);
+ float get_length() const;
+ void set_autoplay(bool p_vol);
+ bool has_autoplay() const;
+ void set_buffering_msec(int p_msec);
+ int get_buffering_msec() const;
SpatialStreamPlayer();
~SpatialStreamPlayer();
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index e9da95f3fb..c7d1249a07 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -578,8 +578,8 @@ void Sprite3D::_bind_methods() {
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, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_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"));
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index f8b58b5cb5..c2ea1c8bb6 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -857,6 +857,11 @@ void AnimationPlayer::clear_queue() {
queued.clear();
};
+void AnimationPlayer::play_backwards(const StringName& p_name,float p_custom_blend) {
+
+ play(p_name,p_custom_blend,-1,true);
+}
+
void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float p_custom_scale,bool p_from_end) {
//printf("animation is %ls\n", String(p_name).c_str());
@@ -1216,6 +1221,7 @@ void AnimationPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time);
ObjectTypeDB::bind_method(_MD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("play_backwards","name","custom_blend"),&AnimationPlayer::play_backwards,DEFVAL(""),DEFVAL(-1));
ObjectTypeDB::bind_method(_MD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true));
ObjectTypeDB::bind_method(_MD("stop_all"),&AnimationPlayer::stop_all);
ObjectTypeDB::bind_method(_MD("is_playing"),&AnimationPlayer::is_playing);
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 3fddc283ae..1e3c37c4d6 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -258,6 +258,7 @@ public:
float get_default_blend_time() const;
void play(const StringName& p_name=StringName(),float p_custom_blend=-1,float p_custom_scale=1.0,bool p_from_end=false);
+ void play_backwards(const StringName& p_name=StringName(),float p_custom_blend=-1);
void queue(const StringName& p_name);
void clear_queue();
void stop(bool p_reset=true);
diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp
index a097aacf19..699d068287 100644
--- a/scene/audio/stream_player.cpp
+++ b/scene/audio/stream_player.cpp
@@ -28,6 +28,67 @@
/*************************************************************************/
#include "stream_player.h"
+int StreamPlayer::InternalStream::get_channel_count() const {
+
+ return player->sp_get_channel_count();
+}
+void StreamPlayer::InternalStream::set_mix_rate(int p_rate){
+
+ return player->sp_set_mix_rate(p_rate);
+}
+bool StreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){
+
+ return player->sp_mix(p_buffer,p_frames);
+}
+void StreamPlayer::InternalStream::update(){
+
+ player->sp_update();
+}
+
+
+int StreamPlayer::sp_get_channel_count() const {
+
+ return playback->get_channels();
+}
+
+void StreamPlayer::sp_set_mix_rate(int p_rate){
+
+ server_mix_rate=p_rate;
+}
+
+bool StreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) {
+
+ if (resampler.is_ready()) {
+ return resampler.mix(p_buffer,p_frames);
+ }
+
+ return false;
+}
+
+void StreamPlayer::sp_update() {
+
+ _THREAD_SAFE_METHOD_
+ if (!paused && resampler.is_ready() && playback.is_valid()) {
+
+ if (!playback->is_playing()) {
+ //stream depleted data, but there's still audio in the ringbuffer
+ //check that all this audio has been flushed before stopping the stream
+ int to_mix = resampler.get_total() - resampler.get_todo();
+ if (to_mix==0) {
+ stop();
+ return;
+ }
+
+ return;
+ }
+
+ int todo =resampler.get_todo();
+ int wrote = playback->mix(resampler.get_write_buffer(),todo);
+ resampler.write(wrote);
+ }
+}
+
+
void StreamPlayer::_notification(int p_what) {
@@ -52,19 +113,21 @@ void StreamPlayer::set_stream(const Ref<AudioStream> &p_stream) {
stop();
- if (stream_rid.is_valid())
- AudioServer::get_singleton()->free(stream_rid);
- stream_rid=RID();
-
stream=p_stream;
- if (!stream.is_null()) {
- stream->set_loop(loops);
- stream->set_paused(paused);
- stream_rid=AudioServer::get_singleton()->audio_stream_create(stream->get_audio_stream());
+ if (!stream.is_null()) {
+ playback=stream->instance_playback();
+ playback->set_loop(loops);
+ playback->set_loop_restart_time(loop_point);
+ AudioServer::get_singleton()->lock();
+ resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size());
+ AudioServer::get_singleton()->unlock();
+ } else {
+ AudioServer::get_singleton()->lock();
+ resampler.clear();
+ playback.unref();
+ AudioServer::get_singleton()->unlock();
}
-
-
}
Ref<AudioStream> StreamPlayer::get_stream() const {
@@ -73,15 +136,18 @@ Ref<AudioStream> StreamPlayer::get_stream() const {
}
-void StreamPlayer::play() {
+void StreamPlayer::play(float p_from_offset) {
ERR_FAIL_COND(!is_inside_tree());
- if (stream.is_null())
+ if (playback.is_null())
return;
- if (stream->is_playing())
+ if (playback->is_playing())
stop();
- stream->play();
+ _THREAD_SAFE_METHOD_
+ playback->play(p_from_offset);
+ //feed the ringbuffer as long as no update callback is going on
+ sp_update();
AudioServer::get_singleton()->stream_set_active(stream_rid,true);
AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume);
// if (stream->get_update_mode()!=AudioStream::UPDATE_NONE)
@@ -93,28 +159,29 @@ void StreamPlayer::stop() {
if (!is_inside_tree())
return;
- if (stream.is_null())
+ if (playback.is_null())
return;
+ _THREAD_SAFE_METHOD_
AudioServer::get_singleton()->stream_set_active(stream_rid,false);
- stream->stop();
+ playback->stop();
//set_idle_process(false);
}
bool StreamPlayer::is_playing() const {
- if (stream.is_null())
+ if (playback.is_null())
return false;
- return stream->is_playing();
+ return playback->is_playing();
}
void StreamPlayer::set_loop(bool p_enable) {
loops=p_enable;
- if (stream.is_null())
+ if (playback.is_null())
return;
- stream->set_loop(loops);
+ playback->set_loop(loops);
}
bool StreamPlayer::has_loop() const {
@@ -134,6 +201,19 @@ float StreamPlayer::get_volume() const {
return volume;
}
+void StreamPlayer::set_loop_restart_time(float p_secs) {
+
+ loop_point=p_secs;
+ if (playback.is_valid())
+ playback->set_loop_restart_time(p_secs);
+}
+
+float StreamPlayer::get_loop_restart_time() const {
+
+ return loop_point;
+}
+
+
void StreamPlayer::set_volume_db(float p_db) {
if (p_db<-79)
@@ -161,31 +241,31 @@ String StreamPlayer::get_stream_name() const {
int StreamPlayer::get_loop_count() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_loop_count();
+ return playback->get_loop_count();
}
float StreamPlayer::get_pos() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_pos();
+ return playback->get_pos();
}
float StreamPlayer::get_length() const {
- if (stream.is_null())
+ if (playback.is_null())
return 0;
- return stream->get_length();
+ return playback->get_length();
}
void StreamPlayer::seek_pos(float p_time) {
- if (stream.is_null())
+ if (playback.is_null())
return;
- return stream->seek_pos(p_time);
+ return playback->seek_pos(p_time);
}
@@ -202,8 +282,8 @@ bool StreamPlayer::has_autoplay() const {
void StreamPlayer::set_paused(bool p_paused) {
paused=p_paused;
- if (stream.is_valid())
- stream->set_paused(p_paused);
+ //if (stream.is_valid())
+ // stream->set_paused(p_paused);
}
bool StreamPlayer::is_paused() const {
@@ -228,6 +308,17 @@ bool StreamPlayer::_get_play() const{
return _play;
}
+void StreamPlayer::set_buffering_msec(int p_msec) {
+
+ buffering_ms=p_msec;
+}
+
+int StreamPlayer::get_buffering_msec() const{
+
+ return buffering_ms;
+}
+
+
void StreamPlayer::_bind_methods() {
@@ -251,6 +342,12 @@ void StreamPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&StreamPlayer::set_volume_db);
ObjectTypeDB::bind_method(_MD("get_volume_db"),&StreamPlayer::get_volume_db);
+ ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&StreamPlayer::set_buffering_msec);
+ ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&StreamPlayer::get_buffering_msec);
+
+ ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&StreamPlayer::set_loop_restart_time);
+ ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&StreamPlayer::get_loop_restart_time);
+
ObjectTypeDB::bind_method(_MD("get_stream_name"),&StreamPlayer::get_stream_name);
ObjectTypeDB::bind_method(_MD("get_loop_count"),&StreamPlayer::get_loop_count);
@@ -271,6 +368,8 @@ void StreamPlayer::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") );
}
@@ -281,10 +380,17 @@ StreamPlayer::StreamPlayer() {
paused=false;
autoplay=false;
_play=false;
+ server_mix_rate=1;
+ internal_stream.player=this;
+ stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream);
+ buffering_ms=500;
+ loop_point=0;
+
}
StreamPlayer::~StreamPlayer() {
- if (stream_rid.is_valid())
- AudioServer::get_singleton()->free(stream_rid);
+ AudioServer::get_singleton()->free(stream_rid);
+ resampler.clear();
+
}
diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h
index 21e2162188..b5aa943067 100644
--- a/scene/audio/stream_player.h
+++ b/scene/audio/stream_player.h
@@ -31,17 +31,43 @@
#include "scene/resources/audio_stream.h"
#include "scene/main/node.h"
+#include "servers/audio/audio_rb_resampler.h"
class StreamPlayer : public Node {
OBJ_TYPE(StreamPlayer,Node);
+ _THREAD_SAFE_CLASS_
+
+ struct InternalStream : public AudioServer::AudioStream {
+ StreamPlayer *player;
+ virtual int get_channel_count() const;
+ virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
+ virtual bool mix(int32_t *p_buffer,int p_frames);
+ virtual void update();
+ };
+
+
+ InternalStream internal_stream;
+ Ref<AudioStreamPlayback> playback;
Ref<AudioStream> stream;
+
+ int sp_get_channel_count() const;
+ void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate
+ bool sp_mix(int32_t *p_buffer,int p_frames);
+ void sp_update();
+
+ int server_mix_rate;
+
RID stream_rid;
bool paused;
bool autoplay;
bool loops;
float volume;
+ float loop_point;
+ int buffering_ms;
+
+ AudioRBResampler resampler;
bool _play;
void _set_play(bool p_play);
@@ -55,7 +81,7 @@ public:
void set_stream(const Ref<AudioStream> &p_stream);
Ref<AudioStream> get_stream() const;
- void play();
+ void play(float p_from_offset=0);
void stop();
bool is_playing() const;
@@ -68,6 +94,9 @@ public:
void set_volume(float p_vol);
float get_volume() const;
+ void set_loop_restart_time(float p_secs);
+ float get_loop_restart_time() const;
+
void set_volume_db(float p_db);
float get_volume_db() const;
@@ -81,6 +110,8 @@ public:
void set_autoplay(bool p_vol);
bool has_autoplay() const;
+ void set_buffering_msec(int p_msec);
+ int get_buffering_msec() const;
StreamPlayer();
~StreamPlayer();
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 3ddf23fc4a..0c0f924f52 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -274,7 +274,7 @@ Button* AcceptDialog::add_button(const String& p_text,bool p_right,const String&
}
if (p_action!="") {
- button->connect("pressed",this,"_custom_action",make_binds(p_action));
+ button->connect("pressed",this,"_custom_action",varray(p_action));
}
return button;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index c29f6625d3..b7b2f061ea 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -187,6 +187,7 @@ void ItemList::select(int p_idx,bool p_single){
}
current=p_idx;
+ ensure_selected_visible=false;
} else {
if (items[p_idx].selectable) {
@@ -195,6 +196,7 @@ void ItemList::select(int p_idx,bool p_single){
}
update();
+
}
void ItemList::unselect(int p_idx){
@@ -246,12 +248,14 @@ void ItemList::remove_item(int p_idx){
update();
shape_changed=true;
+
}
void ItemList::clear(){
items.clear();
current=-1;
+ ensure_selected_visible=false;
update();
}
@@ -602,18 +606,8 @@ void ItemList::_input_event(const InputEvent& p_event) {
void ItemList::ensure_current_is_visible() {
- if (current>=0 && current <=items.size()) {
-
- Rect2 r = items[current].rect_cache;
- int from = scroll_bar->get_val();
- int to = from + scroll_bar->get_page();
-
- if (r.pos.y < from) {
- scroll_bar->set_val(r.pos.y);
- } else if (r.pos.y+r.size.y > to) {
- scroll_bar->set_val(r.pos.y+r.size.y - (to-from));
- }
- }
+ ensure_selected_visible=true;
+ update();
}
void ItemList::_notification(int p_what) {
@@ -928,6 +922,24 @@ void ItemList::_notification(int p_what) {
draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color);
}
+
+ if (ensure_selected_visible && current>=0 && current <=items.size()) {
+
+ Rect2 r = items[current].rect_cache;
+ int from = scroll_bar->get_val();
+ int to = from + scroll_bar->get_page();
+
+ if (r.pos.y < from) {
+ scroll_bar->set_val(r.pos.y);
+ } else if (r.pos.y+r.size.y > to) {
+ scroll_bar->set_val(r.pos.y+r.size.y - (to-from));
+ }
+
+
+ }
+
+ ensure_selected_visible=false;
+
}
}
@@ -1095,6 +1107,7 @@ ItemList::ItemList() {
set_focus_mode(FOCUS_ALL);
current_columns=1;
search_time_msec=0;
+ ensure_selected_visible=false;
}
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 237079c428..7cf58a6426 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -41,6 +41,8 @@ private:
bool shape_changed;
+ bool ensure_selected_visible;
+
Vector<Item> items;
Vector<int> separators;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 68fcb4bda8..13ff7074ea 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -124,7 +124,7 @@ void MenuButton::_set_items(const Array& p_items) {
void MenuButton::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("get_popup"),&MenuButton::get_popup);
+ ObjectTypeDB::bind_method(_MD("get_popup:PopupMenu"),&MenuButton::get_popup);
ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&MenuButton::_unhandled_key_input);
ObjectTypeDB::bind_method(_MD("_set_items"),&MenuButton::_set_items);
ObjectTypeDB::bind_method(_MD("_get_items"),&MenuButton::_get_items);
diff --git a/scene/gui/patch_9_frame.cpp b/scene/gui/patch_9_frame.cpp
new file mode 100644
index 0000000000..b6e261714c
--- /dev/null
+++ b/scene/gui/patch_9_frame.cpp
@@ -0,0 +1,132 @@
+#include "patch_9_frame.h"
+
+#include "servers/visual_server.h"
+
+void Patch9Frame::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ if (texture.is_null())
+ return;
+
+
+ Size2 s=get_size();
+ RID ci = get_canvas_item();
+ VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate);
+// draw_texture_rect(texture,Rect2(Point2(),s),false,modulate);
+
+/*
+ Vector<Point2> points;
+ points.resize(4);
+ points[0]=Point2(0,0);
+ points[1]=Point2(s.x,0);
+ points[2]=Point2(s.x,s.y);
+ points[3]=Point2(0,s.y);
+ Vector<Point2> uvs;
+ uvs.resize(4);
+ uvs[0]=Point2(0,0);
+ uvs[1]=Point2(1,0);
+ uvs[2]=Point2(1,1);
+ uvs[3]=Point2(0,1);
+
+ VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid());
+*/
+ }
+}
+
+Size2 Patch9Frame::get_minimum_size() const {
+
+ return Size2(margin[MARGIN_LEFT]+margin[MARGIN_RIGHT],margin[MARGIN_TOP]+margin[MARGIN_BOTTOM]);
+}
+void Patch9Frame::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method(_MD("set_texture","texture"), & Patch9Frame::set_texture );
+ ObjectTypeDB::bind_method(_MD("get_texture"), & Patch9Frame::get_texture );
+ ObjectTypeDB::bind_method(_MD("set_modulate","modulate"), & Patch9Frame::set_modulate );
+ ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate );
+ ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin );
+ ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin );
+ ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center );
+ ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center );
+
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
+ ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") );
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM );
+
+}
+
+
+void Patch9Frame::set_texture(const Ref<Texture>& p_tex) {
+
+ texture=p_tex;
+ update();
+ //if (texture.is_valid())
+ // texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites
+ minimum_size_changed();
+}
+
+Ref<Texture> Patch9Frame::get_texture() const {
+
+ return texture;
+}
+
+void Patch9Frame::set_modulate(const Color& p_tex) {
+
+ modulate=p_tex;
+ update();
+}
+
+Color Patch9Frame::get_modulate() const{
+
+ return modulate;
+}
+
+
+void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) {
+
+ ERR_FAIL_INDEX(p_margin,4);
+ margin[p_margin]=p_size;
+ update();
+ minimum_size_changed();
+}
+
+int Patch9Frame::get_patch_margin(Margin p_margin) const{
+
+ ERR_FAIL_INDEX_V(p_margin,4,0);
+ return margin[p_margin];
+}
+
+void Patch9Frame::set_draw_center(bool p_draw) {
+
+ draw_center=p_draw;
+ update();
+}
+
+bool Patch9Frame::get_draw_center() const{
+
+ return draw_center;
+}
+
+Patch9Frame::Patch9Frame() {
+
+
+ margin[MARGIN_LEFT]=0;
+ margin[MARGIN_RIGHT]=0;
+ margin[MARGIN_BOTTOM]=0;
+ margin[MARGIN_TOP]=0;
+ modulate=Color(1,1,1,1);
+ set_ignore_mouse(true);
+ draw_center=true;
+}
+
+
+Patch9Frame::~Patch9Frame()
+{
+}
+
+
diff --git a/scene/gui/patch_9_frame.h b/scene/gui/patch_9_frame.h
new file mode 100644
index 0000000000..562a5b1d77
--- /dev/null
+++ b/scene/gui/patch_9_frame.h
@@ -0,0 +1,40 @@
+#ifndef PATCH_9_FRAME_H
+#define PATCH_9_FRAME_H
+
+#include "scene/gui/control.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class Patch9Frame : public Control {
+
+ OBJ_TYPE(Patch9Frame,Control);
+
+ bool draw_center;
+ int margin[4];
+ Color modulate;
+ Ref<Texture> texture;
+protected:
+
+ void _notification(int p_what);
+ virtual Size2 get_minimum_size() const;
+ static void _bind_methods();
+
+public:
+
+ void set_texture(const Ref<Texture>& p_tex);
+ Ref<Texture> get_texture() const;
+
+ void set_modulate(const Color& p_tex);
+ Color get_modulate() const;
+
+ void set_patch_margin(Margin p_margin,int p_size);
+ int get_patch_margin(Margin p_margin) const;
+
+ void set_draw_center(bool p_enable);
+ bool get_draw_center() const;
+
+ Patch9Frame();
+ ~Patch9Frame();
+
+};
+#endif // PATCH_9_FRAME_H
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 41e775bbff..a48136f541 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "spin_box.h"
-
+#include "os/input.h"
Size2 SpinBox::get_minimum_size() const {
@@ -62,6 +62,13 @@ LineEdit *SpinBox::get_line_edit() {
}
+void SpinBox::_line_edit_input(const InputEvent& p_event) {
+
+
+
+}
+
+
void SpinBox::_input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) {
@@ -94,6 +101,48 @@ void SpinBox::_input_event(const InputEvent& p_event) {
} break;
}
}
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
+
+ //set_default_cursor_shape(CURSOR_VSIZE);
+ Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
+ drag.mouse_pos=cpos;
+ }
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
+
+ //set_default_cursor_shape(CURSOR_ARROW);
+ if (drag.enabled) {
+ drag.enabled=false;
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ warp_mouse(drag.capture_pos);
+ }
+ }
+
+ if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) {
+
+ Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y);
+ if (drag.enabled) {
+
+ float diff_y = drag.mouse_pos.y - cpos.y;
+ diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
+ diff_y*=0.1;
+
+ drag.mouse_pos=cpos;
+ drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max());
+
+ set_val( drag.base_val);
+
+ } else if (drag.mouse_pos.distance_to(cpos)>2) {
+
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+ drag.enabled=true;
+ drag.base_val=get_val();
+ drag.mouse_pos=cpos;
+ drag.capture_pos=cpos;
+
+ }
+ }
}
@@ -177,6 +226,7 @@ void SpinBox::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable);
ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
+ ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
@@ -196,4 +246,6 @@ SpinBox::SpinBox() {
//connect("value_changed",this,"_value_changed");
line_edit->connect("text_entered",this,"_text_entered",Vector<Variant>(),CONNECT_DEFERRED);
line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
+ line_edit->connect("input_event",this,"_line_edit_input");
+ drag.enabled=false;
}
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 6ebe14631e..4c8cb8432a 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -44,6 +44,18 @@ class SpinBox : public Range {
String prefix;
String suffix;
+ void _line_edit_input(const InputEvent& p_event);
+
+
+ struct Drag {
+ float base_val;
+ bool enabled;
+ Vector2 from;
+ Vector2 mouse_pos;
+ Vector2 capture_pos;
+ } drag;
+
+
void _line_edit_focus_exit();
protected:
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 6c15f1cae4..e639b5cb05 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -31,7 +31,7 @@
#include "os/os.h"
#include "os/keyboard.h"
#include "globals.h"
-
+#include "os/input.h"
@@ -70,6 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const {
else
return icon_region.size;
}
+
void TreeItem::Cell::draw_icon(const RID& p_where, const Point2& p_pos, const Size2& p_size) const{
if (icon.is_null())
@@ -728,14 +729,20 @@ TreeItem::~TreeItem() {
tree->root=0;
}
- if (tree && tree->popup_edited_item==this)
+ if (tree && tree->popup_edited_item==this) {
tree->popup_edited_item=NULL;
+ tree->pressing_for_editor=false;
+
+ }
if (tree && tree->selected_item==this)
tree->selected_item=NULL;
- if (tree && tree->edited_item==this)
+ if (tree && tree->edited_item==this) {
tree->edited_item=NULL;
+ tree->pressing_for_editor=false;
+ }
+
}
@@ -1292,7 +1299,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col
} else if (select_mode==SELECT_SINGLE || select_mode==SELECT_MULTI) {
- if (&selected_cell==&c) {
+ if (!r_in_range && &selected_cell==&c) {
if (!selected_cell.selected) {
@@ -1301,6 +1308,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col
selected_item=p_selected;
selected_col=i;
+
emit_signal("cell_selected");
if (select_mode==SELECT_MULTI)
emit_signal("multi_selected",p_current,i,true);
@@ -1317,6 +1325,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col
if (r_in_range && *r_in_range) {
+
if (!c.selected && c.selectable) {
c.selected=true;
emit_signal("multi_selected",p_current,i,true);
@@ -1467,7 +1476,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
if (select_mode==SELECT_MULTI && p_mod.shift && selected_item && selected_item!=p_item) {
bool inrange=false;
- print_line("SELECT MULTI AND SHIFT AND ALL");
+
select_single_item( p_item, root, col,selected_item,&inrange );
} else {
select_single_item( p_item, root, col );
@@ -1490,7 +1499,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
/* editing */
- bool bring_up_editor=c.selected && already_selected;
+ bool bring_up_editor=c.selected;// && already_selected;
bool bring_up_value_editor=false;
String editor_text=c.text;
@@ -1605,31 +1614,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
return -1;
- click_handled=true;
+
+ click_handled=true;
popup_edited_item=p_item;
popup_edited_item_col=col;
- text_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset );
- text_editor->set_size( Size2(col_width,item_h));
- text_editor->clear();
- text_editor->set_text( editor_text );
- text_editor->select_all();
- if (bring_up_value_editor) {
-
- value_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset+Point2i(0,text_editor->get_size().height) );
- value_editor->set_size( Size2(col_width,1));
- value_editor->show_modal();
- updating_value_editor=true;
- value_editor->set_min( c.min );
- value_editor->set_max( c.max );
- value_editor->set_step( c.step );
- value_editor->set_val( c.val );
- value_editor->set_exp_unit_value( c.expr );
- updating_value_editor=false;
- }
-
- text_editor->show_modal();
- text_editor->grab_focus();
+ pressing_item_rect=Rect2(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset,Size2(col_width,item_h));
+ pressing_for_editor_text=editor_text;
+ pressing_for_editor=true;
return -1; //select
} else {
@@ -2062,6 +2054,33 @@ void Tree::_input_event(InputEvent p_event) {
update();
}
+ if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) {
+ //range drag
+
+ if (!range_drag_enabled) {
+
+ Vector2 cpos = Vector2(b.x,b.y);
+ if (cpos.distance_to(pressing_pos)>2) {
+ range_drag_enabled=true;
+ range_drag_capture_pos=cpos;
+ range_drag_base=popup_edited_item->get_range(popup_edited_item_col);
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+ }
+ } else {
+
+ TreeItem::Cell &c=popup_edited_item->cells[popup_edited_item_col];
+ float diff_y = -b.relative_y;
+ diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y);
+ diff_y*=0.1;
+ range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max);
+
+ popup_edited_item->set_range(popup_edited_item_col,range_drag_base);
+ item_edited(popup_edited_item_col,popup_edited_item);
+
+ }
+
+ }
+
if (drag_touching && ! drag_touching_deaccel) {
@@ -2084,6 +2103,31 @@ void Tree::_input_event(InputEvent p_event) {
if (b.button_index==BUTTON_LEFT) {
+ if (pressing_for_editor) {
+
+ if (range_drag_enabled) {
+
+ range_drag_enabled=false;
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ warp_mouse(range_drag_capture_pos);
+ } else {
+ text_editor->set_pos(pressing_item_rect.pos);
+ text_editor->set_size(pressing_item_rect.size);
+
+ text_editor->clear();
+ text_editor->set_text( pressing_for_editor_text );
+ text_editor->select_all();
+
+ text_editor->show_modal();
+ text_editor->grab_focus();
+
+ }
+ pressing_for_editor=false;
+
+ }
+
+
+
if (cache.click_type==Cache::CLICK_BUTTON) {
emit_signal("button_pressed",cache.click_item,cache.click_column,cache.click_id);
@@ -2145,11 +2189,15 @@ void Tree::_input_event(InputEvent p_event) {
break;
click_handled=false;
+ pressing_for_editor=false;
blocked++;
bool handled = propagate_mouse_event(pos+cache.offset,0,0,b.doubleclick,root,b.button_index,b.mod);
blocked--;
+ if (pressing_for_editor) {
+ pressing_pos=Point2(b.x,b.y);
+ }
if (drag_touching) {
@@ -2360,6 +2408,11 @@ void Tree::_notification(int p_what) {
}
}
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ drag_touching=false;
+ }
+
if (p_what==NOTIFICATION_ENTER_TREE) {
update_cache();;
@@ -2610,6 +2663,8 @@ void Tree::clear() {
selected_item=NULL;
edited_item=NULL;
popup_edited_item=NULL;
+ selected_item=NULL;
+ pressing_for_editor=false;
update();
};
@@ -3184,6 +3239,8 @@ Tree::Tree() {
drag_speed=0;
drag_touching=false;
drag_touching_deaccel=false;
+ pressing_for_editor=false;
+ range_drag_enabled=false;
}
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 8ddddd0630..3fbd7c95d9 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -258,7 +258,18 @@ friend class TreeItem;
TreeItem *popup_edited_item;
TreeItem *selected_item;
TreeItem *edited_item;
+
+
int pressed_button;
+ bool pressing_for_editor;
+ String pressing_for_editor_text;
+ Vector2 pressing_pos;
+ Rect2 pressing_item_rect;
+
+ float range_drag_base;
+ bool range_drag_enabled;
+ Vector2 range_drag_capture_pos;
+
//TreeItem *cursor_item;
//int cursor_column;
diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp
index 8527498fc2..f67d50b56c 100644
--- a/scene/io/resource_format_image.cpp
+++ b/scene/io/resource_format_image.cpp
@@ -31,9 +31,11 @@
#include "io/image_loader.h"
#include "globals.h"
#include "os/os.h"
-RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_original_path) {
-
+RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
+
if (p_path.extension()=="cube") {
// open as cubemap txture
@@ -83,6 +85,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
memdelete(f);
cubemap->set_name(p_path.get_file());
+ if (r_error)
+ *r_error=OK;
return cubemap;
@@ -112,6 +116,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
ERR_EXPLAIN("Failed loading image: "+p_path);
ERR_FAIL_COND_V(err, RES());
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
#ifdef DEBUG_ENABLED
#ifdef TOOLS_ENABLED
@@ -199,6 +205,9 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
print_line(" -make texture: "+rtos(total));
}
+ if (r_error)
+ *r_error=OK;
+
return RES( texture );
}
diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h
index 1af65870f8..b5ec5a1200 100644
--- a/scene/io/resource_format_image.h
+++ b/scene/io/resource_format_image.h
@@ -40,7 +40,7 @@ class ResourceFormatLoaderImage : public ResourceFormatLoader {
int max_texture_size;
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp
index 7c90a4b3cd..090348c933 100644
--- a/scene/io/resource_format_wav.cpp
+++ b/scene/io/resource_format_wav.cpp
@@ -31,13 +31,18 @@
#include "scene/resources/sample.h"
-RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderWAV::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
Error err;
FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err);
ERR_FAIL_COND_V( err!=OK, RES() );
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
+
/* CHECK RIFF */
char riff[5];
riff[4]=0;
@@ -244,6 +249,9 @@ RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_
file->close();
memdelete(file);
+ if (r_error)
+ *r_error=OK;
+
return sample;
}
diff --git a/scene/io/resource_format_wav.h b/scene/io/resource_format_wav.h
index 081a563d03..a74da041c1 100644
--- a/scene/io/resource_format_wav.h
+++ b/scene/io/resource_format_wav.h
@@ -33,7 +33,7 @@
class ResourceFormatLoaderWAV : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 717ed93b16..851de4a89f 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -52,6 +52,7 @@
#include "scene/gui/option_button.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/texture_frame.h"
+#include "scene/gui/patch_9_frame.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
@@ -302,6 +303,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); //may take time to init
ObjectTypeDB::register_type<TextureFrame>();
+ ObjectTypeDB::register_type<Patch9Frame>();
ObjectTypeDB::register_type<TabContainer>();
ObjectTypeDB::register_type<Tabs>();
ObjectTypeDB::register_virtual_type<Separator>();
@@ -456,7 +458,6 @@ void register_scene_types() {
/* disable types by default, only editors should enable them */
- ObjectTypeDB::set_type_enabled("CollisionShape",false);
//ObjectTypeDB::set_type_enabled("BodyVolumeSphere",false);
//ObjectTypeDB::set_type_enabled("BodyVolumeBox",false);
//ObjectTypeDB::set_type_enabled("BodyVolumeCapsule",false);
@@ -490,9 +491,12 @@ void register_scene_types() {
ObjectTypeDB::register_type<OccluderPolygon2D>();
ObjectTypeDB::register_type<YSort>();
ObjectTypeDB::register_type<BackBufferCopy>();
-
- ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
- ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);
+ if (bool(GLOBAL_DEF("physics/remove_collision_helpers_at_runtime",false))) {
+ ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
+ ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);
+ ObjectTypeDB::set_type_enabled("CollisionShape",false);
+ ObjectTypeDB::set_type_enabled("CollisionPolygon",false);
+ }
OS::get_singleton()->yield(); //may take time to init
@@ -576,7 +580,8 @@ void register_scene_types() {
ObjectTypeDB::register_type<Sample>();
ObjectTypeDB::register_type<SampleLibrary>();
ObjectTypeDB::register_virtual_type<AudioStream>();
- ObjectTypeDB::register_type<AudioStreamGibberish>();
+ ObjectTypeDB::register_virtual_type<AudioStreamPlayback>();
+// ObjectTypeDB::register_type<AudioStreamGibberish>();
ObjectTypeDB::register_virtual_type<VideoStream>();
OS::get_singleton()->yield(); //may take time to init
diff --git a/scene/resources/audio_stream.cpp b/scene/resources/audio_stream.cpp
index 7694b8ef79..569ed8620d 100644
--- a/scene/resources/audio_stream.cpp
+++ b/scene/resources/audio_stream.cpp
@@ -28,76 +28,34 @@
/*************************************************************************/
#include "audio_stream.h"
+//////////////////////////////
-int AudioStream::InternalAudioStream::get_channel_count() const {
+void AudioStreamPlayback::_bind_methods() {
- return owner->get_channel_count();
+ ObjectTypeDB::bind_method(_MD("play","from_pos_sec"),&AudioStreamPlayback::play,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("stop"),&AudioStreamPlayback::stop);
+ ObjectTypeDB::bind_method(_MD("is_playing"),&AudioStreamPlayback::is_playing);
-}
-
-void AudioStream::InternalAudioStream::set_mix_rate(int p_rate) {
-
- owner->_mix_rate=p_rate;
-}
-
-bool AudioStream::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) {
-
- return owner->mix(p_buffer,p_frames);
-}
-
-bool AudioStream::InternalAudioStream::can_update_mt() const {
+ ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&AudioStreamPlayback::set_loop);
+ ObjectTypeDB::bind_method(_MD("has_loop"),&AudioStreamPlayback::has_loop);
- return owner->get_update_mode()==UPDATE_THREAD;
-}
+ ObjectTypeDB::bind_method(_MD("get_loop_count"),&AudioStreamPlayback::get_loop_count);
-void AudioStream::InternalAudioStream::update() {
+ ObjectTypeDB::bind_method(_MD("seek_pos","pos"),&AudioStreamPlayback::seek_pos);
+ ObjectTypeDB::bind_method(_MD("get_pos"),&AudioStreamPlayback::get_pos);
- owner->update();
-}
+ ObjectTypeDB::bind_method(_MD("get_length"),&AudioStreamPlayback::get_length);
+ ObjectTypeDB::bind_method(_MD("get_channels"),&AudioStreamPlayback::get_channels);
+ ObjectTypeDB::bind_method(_MD("get_mix_rate"),&AudioStreamPlayback::get_mix_rate);
+ ObjectTypeDB::bind_method(_MD("get_minimum_buffer_size"),&AudioStreamPlayback::get_minimum_buffer_size);
-AudioServer::AudioStream *AudioStream::get_audio_stream() {
- return internal_audio_stream;
}
void AudioStream::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("play"),&AudioStream::play);
- ObjectTypeDB::bind_method(_MD("stop"),&AudioStream::stop);
- ObjectTypeDB::bind_method(_MD("is_playing"),&AudioStream::is_playing);
-
- ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&AudioStream::set_loop);
- ObjectTypeDB::bind_method(_MD("has_loop"),&AudioStream::has_loop);
-
- ObjectTypeDB::bind_method(_MD("get_stream_name"),&AudioStream::get_stream_name);
- ObjectTypeDB::bind_method(_MD("get_loop_count"),&AudioStream::get_loop_count);
-
- ObjectTypeDB::bind_method(_MD("seek_pos","pos"),&AudioStream::seek_pos);
- ObjectTypeDB::bind_method(_MD("get_pos"),&AudioStream::get_pos);
-
- ObjectTypeDB::bind_method(_MD("get_length"),&AudioStream::get_length);
-
- ObjectTypeDB::bind_method(_MD("get_update_mode"),&AudioStream::get_update_mode);
-
- ObjectTypeDB::bind_method(_MD("update"),&AudioStream::update);
-
- BIND_CONSTANT( UPDATE_NONE );
- BIND_CONSTANT( UPDATE_IDLE );
- BIND_CONSTANT( UPDATE_THREAD );
}
-AudioStream::AudioStream() {
-
- _mix_rate=44100;
- internal_audio_stream = memnew( InternalAudioStream );
- internal_audio_stream->owner=this;
-}
-
-
-AudioStream::~AudioStream() {
-
- memdelete(internal_audio_stream);
-}
diff --git a/scene/resources/audio_stream.h b/scene/resources/audio_stream.h
index df33b64a4b..b16e62b8c7 100644
--- a/scene/resources/audio_stream.h
+++ b/scene/resources/audio_stream.h
@@ -31,72 +31,53 @@
#include "resource.h"
#include "servers/audio_server.h"
-#include "scene/resources/audio_stream.h"
-
-class AudioStream : public Resource {
-
- OBJ_TYPE( AudioStream, Resource );
- OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged
-
- friend class InternalAudioStream;
-
- struct InternalAudioStream : public AudioServer::AudioStream {
-
- ::AudioStream *owner;
- virtual int get_channel_count() const;
- virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
- virtual bool mix(int32_t *p_buffer,int p_frames);
- virtual bool can_update_mt() const;
- virtual void update();
- };
+class AudioStreamPlayback : public Reference {
- int _mix_rate;
- InternalAudioStream *internal_audio_stream;
+ OBJ_TYPE( AudioStreamPlayback, Reference );
protected:
-
- _FORCE_INLINE_ int get_mix_rate() const { return _mix_rate; }
- virtual int get_channel_count() const=0;
- virtual bool mix(int32_t *p_buffer, int p_frames)=0;
-
static void _bind_methods();
public:
- enum UpdateMode {
- UPDATE_NONE,
- UPDATE_IDLE,
- UPDATE_THREAD
- };
- AudioServer::AudioStream *get_audio_stream();
-
- virtual void play()=0;
+ virtual void play(float p_from_pos=0)=0;
virtual void stop()=0;
virtual bool is_playing() const=0;
- virtual void set_paused(bool p_paused)=0;
- virtual bool is_paused(bool p_paused) const=0;
-
virtual void set_loop(bool p_enable)=0;
virtual bool has_loop() const=0;
- virtual float get_length() const=0;
-
- virtual String get_stream_name() const=0;
+ virtual void set_loop_restart_time(float p_time)=0;
virtual int get_loop_count() const=0;
virtual float get_pos() const=0;
virtual void seek_pos(float p_time)=0;
- virtual UpdateMode get_update_mode() const=0;
- virtual void update()=0;
+ virtual int mix(int16_t* p_bufer,int p_frames)=0;
+
+ virtual float get_length() const=0;
+ virtual String get_stream_name() const=0;
+
+ virtual int get_channels() const=0;
+ virtual int get_mix_rate() const=0;
+ virtual int get_minimum_buffer_size() const=0;
- AudioStream();
- ~AudioStream();
};
+class AudioStream : public Resource {
+
+ OBJ_TYPE( AudioStream, Resource );
+ OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged
+
+protected:
+ static void _bind_methods();
+public:
+
+ virtual Ref<AudioStreamPlayback> instance_playback()=0;
+
+
+};
-VARIANT_ENUM_CAST( AudioStream::UpdateMode );
#endif // AUDIO_STREAM_H
diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp
index 6317780bd3..edbca60bd3 100644
--- a/scene/resources/audio_stream_resampled.cpp
+++ b/scene/resources/audio_stream_resampled.cpp
@@ -28,6 +28,9 @@
/*************************************************************************/
#include "audio_stream_resampled.h"
#include "globals.h"
+
+
+#if 0
int AudioStreamResampled::get_channel_count() const {
if (!rb)
@@ -382,3 +385,4 @@ AudioStreamResampled::~AudioStreamResampled() {
}
+#endif
diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h
index 33cfb17e3f..570c311878 100644
--- a/scene/resources/audio_stream_resampled.h
+++ b/scene/resources/audio_stream_resampled.h
@@ -31,6 +31,7 @@
#include "scene/resources/audio_stream.h"
+#if 0
class AudioStreamResampled : public AudioStream {
OBJ_TYPE(AudioStreamResampled,AudioStream);
@@ -160,5 +161,5 @@ public:
AudioStreamResampled();
~AudioStreamResampled();
};
-
+#endif
#endif // AUDIO_STREAM_RESAMPLED_H
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index ef056a6230..9a6452797a 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -205,7 +205,10 @@ BitMap::BitMap() {
//////////////////////////////////////
-RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderBitMap::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
BitMap* ptr = memnew(BitMap);
Ref<BitMap> bitmap( ptr );
@@ -219,6 +222,8 @@ RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_origin
ERR_FAIL_COND_V(err, RES());
bitmap->create_from_image_alpha(image);
+ if (r_error)
+ *r_error=OK;
return bitmap;
diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h
index 29b7bc66f4..a6b29bb919 100644
--- a/scene/resources/bit_mask.h
+++ b/scene/resources/bit_mask.h
@@ -66,7 +66,7 @@ class ResourceFormatLoaderBitMap : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index cd0e67f04d..f1e97fd626 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -297,7 +297,7 @@ void make_default_theme() {
t->set_color("font_color_hover","MenuButton", control_font_color_hover );
t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) );
- t->set_constant("hseparation","MenuButton", 0 );
+ t->set_constant("hseparation","MenuButton", 3 );
// CheckBox
diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp
index 23b94c8f38..7af81bd992 100644
--- a/scene/resources/gibberish_stream.cpp
+++ b/scene/resources/gibberish_stream.cpp
@@ -29,6 +29,8 @@
#include "gibberish_stream.h"
#include "servers/audio_server.h"
+#if 0
+
int AudioStreamGibberish::get_channel_count() const {
return 1;
@@ -328,3 +330,4 @@ AudioStreamGibberish::AudioStreamGibberish() {
paused=false;
active_voices=0;
}
+#endif
diff --git a/scene/resources/gibberish_stream.h b/scene/resources/gibberish_stream.h
index a52e629f83..77393db9f4 100644
--- a/scene/resources/gibberish_stream.h
+++ b/scene/resources/gibberish_stream.h
@@ -29,7 +29,7 @@
#ifndef GIBBERISH_STREAM_H
#define GIBBERISH_STREAM_H
-
+#if 0
#include "scene/resources/audio_stream.h"
#include "scene/resources/sample_library.h"
class AudioStreamGibberish : public AudioStream {
@@ -109,4 +109,6 @@ public:
AudioStreamGibberish();
};
+#endif
+
#endif // GIBBERISH_STREAM_H
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 90598ee789..a9376faf62 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -219,7 +219,10 @@ Shader::~Shader() {
-RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderShader::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error=ERR_FILE_CANT_OPEN;
String fragment_code;
String vertex_code;
@@ -235,6 +238,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin
ERR_FAIL_COND_V(err,RES());
String base_path = p_path.get_base_dir();
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
Ref<Shader> shader;//( memnew( Shader ) );
@@ -435,6 +440,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin
f->close();
memdelete(f);
+ if (r_error)
+ *r_error=OK;
return shader;
}
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index b805cbec96..61a369c408 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -126,7 +126,7 @@ public:
class ResourceFormatLoaderShader : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 3060fe41b4..651e234b49 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -601,7 +601,9 @@ Theme::~Theme()
-RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderTheme::load(const String &p_path, const String& p_original_path, Error *r_error) {
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
Error err;
FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -611,6 +613,8 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina
String base_path = p_path.get_base_dir();
Ref<Theme> theme( memnew( Theme ) );
Map<StringName,Variant> library;
+ if (r_error)
+ *r_error=ERR_FILE_CORRUPT;
bool reading_library=false;
int line=0;
@@ -1003,6 +1007,9 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina
f->close();
memdelete(f);
+ if (r_error)
+ *r_error=OK;
+
return theme;
}
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index 802dcb099c..cfa0762595 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -124,7 +124,7 @@ public:
class ResourceFormatLoaderTheme : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path,const String& p_original_path="");
+ virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
new file mode 100644
index 0000000000..d07d55f1b5
--- /dev/null
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -0,0 +1,356 @@
+#include "audio_rb_resampler.h"
+
+
+int AudioRBResampler::get_channel_count() const {
+
+ if (!rb)
+ return 0;
+
+ return channels;
+}
+
+
+template<int C>
+uint32_t AudioRBResampler::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) {
+
+ uint32_t read=offset&MIX_FRAC_MASK;
+
+ for (int i=0;i<p_todo;i++) {
+
+ offset = (offset + p_increment)&(((1<<(rb_bits+MIX_FRAC_BITS))-1));
+ read+=p_increment;
+ uint32_t pos = offset >> MIX_FRAC_BITS;
+ uint32_t frac = offset & MIX_FRAC_MASK;
+#ifndef FAST_AUDIO
+ ERR_FAIL_COND_V(pos>=rb_len,0);
+#endif
+ uint32_t pos_next = (pos+1)&rb_mask;
+ //printf("rb pos %i\n",pos);
+
+ // since this is a template with a known compile time value (C), conditionals go away when compiling.
+ if (C==1) {
+
+ int32_t v0 = rb[pos];
+ int32_t v0n=rb[pos_next];
+#ifndef FAST_AUDIO
+ v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS;
+#endif
+ v0<<=16;
+ p_dest[i]=v0;
+
+ }
+ if (C==2) {
+
+ int32_t v0 = rb[(pos<<1)+0];
+ int32_t v1 = rb[(pos<<1)+1];
+ int32_t v0n=rb[(pos_next<<1)+0];
+ int32_t v1n=rb[(pos_next<<1)+1];
+
+#ifndef FAST_AUDIO
+ v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS;
+ v1+=(v1n-v1)*(int32_t)frac >> MIX_FRAC_BITS;
+#endif
+ v0<<=16;
+ v1<<=16;
+ p_dest[(i<<1)+0]=v0;
+ p_dest[(i<<1)+1]=v1;
+
+ }
+
+ if (C==4) {
+
+ int32_t v0 = rb[(pos<<2)+0];
+ int32_t v1 = rb[(pos<<2)+1];
+ int32_t v2 = rb[(pos<<2)+2];
+ int32_t v3 = rb[(pos<<2)+3];
+ int32_t v0n = rb[(pos_next<<2)+0];
+ int32_t v1n=rb[(pos_next<<2)+1];
+ int32_t v2n=rb[(pos_next<<2)+2];
+ int32_t v3n=rb[(pos_next<<2)+3];
+
+#ifndef FAST_AUDIO
+ v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS;
+ v1+=(v1n-v1)*(int32_t)frac >> MIX_FRAC_BITS;
+ v2+=(v2n-v2)*(int32_t)frac >> MIX_FRAC_BITS;
+ v3+=(v3n-v3)*(int32_t)frac >> MIX_FRAC_BITS;
+#endif
+ v0<<=16;
+ v1<<=16;
+ v2<<=16;
+ v3<<=16;
+ p_dest[(i<<2)+0]=v0;
+ p_dest[(i<<2)+1]=v1;
+ p_dest[(i<<2)+2]=v2;
+ p_dest[(i<<2)+3]=v3;
+
+ }
+
+ if (C==6) {
+
+ int32_t v0 = rb[(pos*6)+0];
+ int32_t v1 = rb[(pos*6)+1];
+ int32_t v2 = rb[(pos*6)+2];
+ int32_t v3 = rb[(pos*6)+3];
+ int32_t v4 = rb[(pos*6)+4];
+ int32_t v5 = rb[(pos*6)+5];
+ int32_t v0n = rb[(pos_next*6)+0];
+ int32_t v1n=rb[(pos_next*6)+1];
+ int32_t v2n=rb[(pos_next*6)+2];
+ int32_t v3n=rb[(pos_next*6)+3];
+ int32_t v4n=rb[(pos_next*6)+4];
+ int32_t v5n=rb[(pos_next*6)+5];
+
+#ifndef FAST_AUDIO
+ v0+=(v0n-v0)*(int32_t)frac >> MIX_FRAC_BITS;
+ v1+=(v1n-v1)*(int32_t)frac >> MIX_FRAC_BITS;
+ v2+=(v2n-v2)*(int32_t)frac >> MIX_FRAC_BITS;
+ v3+=(v3n-v3)*(int32_t)frac >> MIX_FRAC_BITS;
+ v4+=(v4n-v4)*(int32_t)frac >> MIX_FRAC_BITS;
+ v5+=(v5n-v5)*(int32_t)frac >> MIX_FRAC_BITS;
+#endif
+ v0<<=16;
+ v1<<=16;
+ v2<<=16;
+ v3<<=16;
+ v4<<=16;
+ v5<<=16;
+ p_dest[(i*6)+0]=v0;
+ p_dest[(i*6)+1]=v1;
+ p_dest[(i*6)+2]=v2;
+ p_dest[(i*6)+3]=v3;
+ p_dest[(i*6)+4]=v4;
+ p_dest[(i*6)+5]=v5;
+
+ }
+
+
+ }
+
+
+ return read>>MIX_FRAC_BITS;//rb_read_pos=offset>>MIX_FRAC_BITS;
+
+}
+
+
+bool AudioRBResampler::mix(int32_t *p_dest, int p_frames) {
+
+
+ if (!rb)
+ return false;
+
+ int write_pos_cache=rb_write_pos;
+
+ int32_t increment=(src_mix_rate*MIX_FRAC_LEN)/target_mix_rate;
+
+ int rb_todo;
+
+ if (write_pos_cache==rb_read_pos) {
+ return false; //out of buffer
+
+ } else if (rb_read_pos<write_pos_cache) {
+
+ rb_todo=write_pos_cache-rb_read_pos; //-1?
+ } else {
+
+ rb_todo=(rb_len-rb_read_pos)+write_pos_cache; //-1?
+ }
+
+ int todo = MIN( ((int64_t(rb_todo)<<MIX_FRAC_BITS)/increment)+1, p_frames );
+#if 0
+ if (int(src_mix_rate)==target_mix_rate) {
+
+
+ if (channels==6) {
+
+ for(int i=0;i<p_frames;i++) {
+
+ int from = ((rb_read_pos+i)&rb_mask)*6;
+ int to = i*6;
+
+ p_dest[from+0]=int32_t(rb[to+0])<<16;
+ p_dest[from+1]=int32_t(rb[to+1])<<16;
+ p_dest[from+2]=int32_t(rb[to+2])<<16;
+ p_dest[from+3]=int32_t(rb[to+3])<<16;
+ p_dest[from+4]=int32_t(rb[to+4])<<16;
+ p_dest[from+5]=int32_t(rb[to+5])<<16;
+ }
+
+ } else {
+ int len=p_frames*channels;
+ int from=rb_read_pos*channels;
+ int mask=0;
+ switch(channels) {
+ case 1: mask=rb_len-1; break;
+ case 2: mask=(rb_len*2)-1; break;
+ case 4: mask=(rb_len*4)-1; break;
+ }
+
+ for(int i=0;i<len;i++) {
+
+ p_dest[i]=int32_t(rb[(from+i)&mask])<<16;
+ }
+ }
+
+ rb_read_pos = (rb_read_pos+p_frames)&rb_mask;
+ } else
+#endif
+ {
+
+ uint32_t read=0;
+ switch(channels) {
+ case 1: read=_resample<1>(p_dest,todo,increment); break;
+ case 2: read=_resample<2>(p_dest,todo,increment); break;
+ case 4: read=_resample<4>(p_dest,todo,increment); break;
+ case 6: read=_resample<6>(p_dest,todo,increment); break;
+ }
+#if 1
+ //end of stream, fadeout
+ int remaining = p_frames-todo;
+ if (remaining && todo>0) {
+
+ //print_line("fadeout");
+ for(int c=0;c<channels;c++) {
+
+ for(int i=0;i<todo;i++) {
+
+ int32_t samp = p_dest[i*channels+c]>>8;
+ uint32_t mul = (todo-i) * 256 /todo;
+ //print_line("mul: "+itos(i)+" "+itos(mul));
+ p_dest[i*channels+c]=samp*mul;
+ }
+
+ }
+
+ }
+
+#else
+ int remaining = p_frames-todo;
+ if (remaining && todo>0) {
+
+
+ for(int c=0;c<channels;c++) {
+
+ int32_t from = p_dest[(todo-1)*channels+c]>>8;
+
+ for(int i=0;i<remaining;i++) {
+
+ uint32_t mul = (remaining-i) * 256 /remaining;
+ p_dest[(todo+i)*channels+c]=from*mul;
+ }
+
+ }
+
+ }
+#endif
+
+ //zero out what remains there to avoid glitches
+ for(int i=todo*channels;i<int(p_frames)*channels;i++) {
+
+ p_dest[i]=0;
+ }
+
+ if (read>rb_todo)
+ read=rb_todo;
+
+ rb_read_pos = (rb_read_pos+read)&rb_mask;
+
+
+
+
+ }
+
+ return true;
+}
+
+
+Error AudioRBResampler::setup(int p_channels,int p_src_mix_rate,int p_target_mix_rate,int p_buffer_msec,int p_minbuff_needed) {
+
+ ERR_FAIL_COND_V(p_channels!=1 && p_channels!=2 && p_channels!=4 && p_channels!=6,ERR_INVALID_PARAMETER);
+
+
+ //float buffering_sec = int(GLOBAL_DEF("audio/stream_buffering_ms",500))/1000.0;
+ int desired_rb_bits =nearest_shift(MAX((p_buffer_msec/1000.0)*p_src_mix_rate,p_minbuff_needed));
+
+ bool recreate=!rb;
+
+ if (rb && (uint32_t(desired_rb_bits)!=rb_bits || channels!=uint32_t(p_channels))) {
+ //recreate
+
+ memdelete_arr(rb);
+ memdelete_arr(read_buf);
+ recreate=true;
+
+ }
+
+ if (recreate) {
+
+ channels=p_channels;
+ rb_bits=desired_rb_bits;
+ rb_len=(1<<rb_bits);
+ rb_mask=rb_len-1;
+ rb = memnew_arr( int16_t, rb_len * p_channels );
+ read_buf = memnew_arr( int16_t, rb_len * p_channels );
+
+ }
+
+ src_mix_rate=p_src_mix_rate;
+ target_mix_rate=p_target_mix_rate;
+ offset=0;
+ rb_read_pos=0;
+ rb_write_pos=0;
+
+ //avoid maybe strange noises upon load
+ for (int i=0;i<(rb_len*channels);i++) {
+
+ rb[i]=0;
+ read_buf[i]=0;
+ }
+
+ return OK;
+
+}
+
+void AudioRBResampler::clear() {
+
+ if (!rb)
+ return;
+
+ //should be stopped at this point but just in case
+ if (rb) {
+ memdelete_arr(rb);
+ memdelete_arr(read_buf);
+ }
+ rb=NULL;
+ offset=0;
+ rb_read_pos=0;
+ rb_write_pos=0;
+ read_buf=NULL;
+}
+
+AudioRBResampler::AudioRBResampler() {
+
+ rb=NULL;
+ offset=0;
+ read_buf=NULL;
+ rb_read_pos=0;
+ rb_write_pos=0;
+
+ rb_bits=0;
+ rb_len=0;
+ rb_mask=0;
+ read_buff_len=0;
+ channels=0;
+ src_mix_rate=0;
+ target_mix_rate=0;
+
+}
+
+AudioRBResampler::~AudioRBResampler() {
+
+ if (rb) {
+ memdelete_arr(rb);
+ memdelete_arr(read_buf);
+ }
+
+}
+
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
new file mode 100644
index 0000000000..3c686374f4
--- /dev/null
+++ b/servers/audio/audio_rb_resampler.h
@@ -0,0 +1,133 @@
+#ifndef AUDIO_RB_RESAMPLER_H
+#define AUDIO_RB_RESAMPLER_H
+
+#include "typedefs.h"
+#include "os/memory.h"
+
+struct AudioRBResampler {
+
+ uint32_t rb_bits;
+ uint32_t rb_len;
+ uint32_t rb_mask;
+ uint32_t read_buff_len;
+ uint32_t channels;
+ uint32_t src_mix_rate;
+ uint32_t target_mix_rate;
+
+ volatile int rb_read_pos;
+ volatile int rb_write_pos;
+
+ int32_t offset; //contains the fractional remainder of the resampler
+ enum {
+ MIX_FRAC_BITS=13,
+ MIX_FRAC_LEN=(1<<MIX_FRAC_BITS),
+ MIX_FRAC_MASK=MIX_FRAC_LEN-1,
+ };
+
+ int16_t *read_buf;
+ int16_t *rb;
+
+
+ template<int C>
+ uint32_t _resample(int32_t *p_dest,int p_todo,int32_t p_increment);
+
+
+public:
+
+ _FORCE_INLINE_ void flush() {
+ rb_read_pos=0;
+ rb_write_pos=0;
+ }
+
+ _FORCE_INLINE_ bool is_ready() const{
+ return rb!=NULL;
+ }
+
+
+ _FORCE_INLINE_ int get_total() const {
+
+ return rb_len-1;
+ }
+
+ _FORCE_INLINE_ int get_todo() const { //return amount of frames to mix
+
+ int todo;
+ int read_pos_cache=rb_read_pos;
+
+ if (read_pos_cache==rb_write_pos) {
+ todo=rb_len-1;
+ } else if (read_pos_cache>rb_write_pos) {
+
+ todo=read_pos_cache-rb_write_pos-1;
+ } else {
+
+ todo=(rb_len-rb_write_pos)+read_pos_cache-1;
+ }
+
+ return todo;
+ }
+
+ _FORCE_INLINE_ int16_t *get_write_buffer() { return read_buf; }
+ _FORCE_INLINE_ void write(uint32_t p_frames) {
+
+ ERR_FAIL_COND(p_frames >= rb_len);
+
+ switch(channels) {
+ case 1: {
+
+ for(uint32_t i=0;i<p_frames;i++) {
+
+ rb[ rb_write_pos ] = read_buf[i];
+ rb_write_pos=(rb_write_pos+1)&rb_mask;
+ }
+ } break;
+ case 2: {
+
+ for(uint32_t i=0;i<p_frames;i++) {
+
+ rb[ (rb_write_pos<<1)+0 ] = read_buf[(i<<1)+0];
+ rb[ (rb_write_pos<<1)+1 ] = read_buf[(i<<1)+1];
+ rb_write_pos=(rb_write_pos+1)&rb_mask;
+ }
+ } break;
+ case 4: {
+
+ for(uint32_t i=0;i<p_frames;i++) {
+
+ rb[ (rb_write_pos<<2)+0 ] = read_buf[(i<<2)+0];
+ rb[ (rb_write_pos<<2)+1 ] = read_buf[(i<<2)+1];
+ rb[ (rb_write_pos<<2)+2 ] = read_buf[(i<<2)+2];
+ rb[ (rb_write_pos<<2)+3 ] = read_buf[(i<<2)+3];
+ rb_write_pos=(rb_write_pos+1)&rb_mask;
+ }
+ } break;
+ case 6: {
+
+ for(uint32_t i=0;i<p_frames;i++) {
+
+ rb[ (rb_write_pos*6)+0 ] = read_buf[(i*6)+0];
+ rb[ (rb_write_pos*6)+1 ] = read_buf[(i*6)+1];
+ rb[ (rb_write_pos*6)+2 ] = read_buf[(i*6)+2];
+ rb[ (rb_write_pos*6)+3 ] = read_buf[(i*6)+3];
+ rb[ (rb_write_pos*6)+4 ] = read_buf[(i*6)+4];
+ rb[ (rb_write_pos*6)+5 ] = read_buf[(i*6)+5];
+ rb_write_pos=(rb_write_pos+1)&rb_mask;
+ }
+ } break;
+
+
+ }
+
+ }
+
+ int get_channel_count() const;
+
+ Error setup(int p_channels, int p_src_mix_rate, int p_target_mix_rate, int p_buffer_msec, int p_minbuff_needed=-1);
+ void clear();
+ bool mix(int32_t *p_dest, int p_frames);
+
+ AudioRBResampler();
+ ~AudioRBResampler();
+};
+
+#endif // AUDIO_RB_RESAMPLER_H
diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp
index 8a3ab7ce70..09cb4eca5f 100644
--- a/servers/audio/audio_server_sw.cpp
+++ b/servers/audio/audio_server_sw.cpp
@@ -830,10 +830,14 @@ void AudioServerSW::finish() {
void AudioServerSW::_update_streams(bool p_thread) {
_THREAD_SAFE_METHOD_
- for(List<Stream*>::Element *E=active_audio_streams.front();E;E=E->next()) {
+ for(List<Stream*>::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback
+
+ List<Stream*>::Element *N=E->next();
if (E->get()->audio_stream && p_thread == E->get()->audio_stream->can_update_mt())
E->get()->audio_stream->update();
+
+ E=N;
}
}
diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp
index 83be80f816..e78f0699cb 100644
--- a/servers/physics/area_sw.cpp
+++ b/servers/physics/area_sw.cpp
@@ -83,6 +83,10 @@ void AreaSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) {
_shape_changed();
+ if (!moved_list.in_list() && get_space())
+ get_space()->area_add_to_moved_list(&moved_list);
+
+
}
void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) {
@@ -103,6 +107,10 @@ void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method
_shape_changed();
+ if (!moved_list.in_list() && get_space())
+ get_space()->area_add_to_moved_list(&moved_list);
+
+
}
@@ -123,7 +131,8 @@ void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant& p_va
case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break;
case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break;
case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break;
- case PhysicsServer::AREA_PARAM_DENSITY: density=p_value; ; break;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break;
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break;
case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; ; break;
}
@@ -139,7 +148,8 @@ Variant AreaSW::get_param(PhysicsServer::AreaParameter p_param) const {
case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point;
case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale;
case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation;
- case PhysicsServer::AREA_PARAM_DENSITY: return density;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP: return linear_damp;
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp;
case PhysicsServer::AREA_PARAM_PRIORITY: return priority;
}
@@ -248,7 +258,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move
gravity_is_point=false;
gravity_distance_scale=0;
point_attenuation=1;
- density=0.1;
+ angular_damp=1.0;
+ linear_damp=0.1;
priority=0;
set_ray_pickable(false);
monitor_callback_id=0;
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index 26d6a177db..40ccdaf370 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -47,7 +47,8 @@ class AreaSW : public CollisionObjectSW{
bool gravity_is_point;
float gravity_distance_scale;
float point_attenuation;
- float density;
+ float linear_damp;
+ float angular_damp;
int priority;
bool monitorable;
@@ -145,8 +146,11 @@ public:
_FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; }
_FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; }
- _FORCE_INLINE_ void set_density(float p_density) { density=p_density; }
- _FORCE_INLINE_ float get_density() const { return density; }
+ _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; }
+ _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; }
+
+ _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; }
+ _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
@@ -202,6 +206,7 @@ void AreaSW::remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape,uint32
monitored_areas[bk].dec();
if (!monitor_query_list.in_list())
_queue_monitor_update();
+
}
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 5a528ecf94..8edbaf0b89 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -159,6 +159,17 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) {
_update_inertia();
} break;
+ case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: {
+ gravity_scale=p_value;
+ } break;
+ case PhysicsServer::BODY_PARAM_LINEAR_DAMP: {
+
+ linear_damp=p_value;
+ } break;
+ case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: {
+
+ angular_damp=p_value;
+ } break;
default:{}
}
}
@@ -177,6 +188,18 @@ float BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
case PhysicsServer::BODY_PARAM_MASS: {
return mass;
} break;
+ case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: {
+ return gravity_scale;
+ } break;
+ case PhysicsServer::BODY_PARAM_LINEAR_DAMP: {
+
+ return linear_damp;
+ } break;
+ case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: {
+
+ return angular_damp;
+ } break;
+
default:{}
}
@@ -380,6 +403,8 @@ void BodySW::integrate_forces(real_t p_step) {
return;
AreaSW *def_area = get_space()->get_default_area();
+ AreaSW *damp_area = def_area;
+
ERR_FAIL_COND(!def_area);
int ac = areas.size();
@@ -388,7 +413,7 @@ void BodySW::integrate_forces(real_t p_step) {
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
- density = aa[ac-1].area->get_density();
+ damp_area = aa[ac-1].area;
for(int i=ac-1;i>=0;i--) {
_compute_area_gravity(aa[i].area);
if (aa[i].area->get_space_override_mode() == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE) {
@@ -396,13 +421,25 @@ void BodySW::integrate_forces(real_t p_step) {
break;
}
}
- } else {
- density=def_area->get_density();
}
+
if( !replace ) {
_compute_area_gravity(def_area);
}
+ gravity*=gravity_scale;
+
+ if (angular_damp>=0)
+ area_angular_damp=angular_damp;
+ else
+ area_angular_damp=damp_area->get_angular_damp();
+
+ if (linear_damp>=0)
+ area_linear_damp=linear_damp;
+ else
+ area_linear_damp=damp_area->get_linear_damp();
+
+
Vector3 motion;
bool do_motion=false;
@@ -431,12 +468,12 @@ void BodySW::integrate_forces(real_t p_step) {
force+=applied_force;
Vector3 torque=applied_torque;
- real_t damp = 1.0 - p_step * density;
+ real_t damp = 1.0 - p_step * area_linear_damp;
if (damp<0) // reached zero in the given time
damp=0;
- real_t angular_damp = 1.0 - p_step * density * get_space()->get_body_angular_velocity_damp_ratio();
+ real_t angular_damp = 1.0 - p_step * area_angular_damp;
if (angular_damp<0) // reached zero in the given time
angular_damp=0;
@@ -695,8 +732,12 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda
island_list_next=NULL;
first_time_kinematic=false;
_set_static(false);
- density=0;
+
contact_count=0;
+ gravity_scale=1.0;
+
+ area_angular_damp=0;
+ area_linear_damp=0;
still_time=0;
continuous_cd=false;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 6491ba8f18..66d814bfd1 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -50,6 +50,10 @@ class BodySW : public CollisionObjectSW {
real_t bounce;
real_t friction;
+ real_t linear_damp;
+ real_t angular_damp;
+ real_t gravity_scale;
+
PhysicsServer::BodyAxisLock axis_lock;
real_t _inv_mass;
@@ -57,13 +61,16 @@ class BodySW : public CollisionObjectSW {
Matrix3 _inv_inertia_tensor;
Vector3 gravity;
- real_t density;
real_t still_time;
Vector3 applied_force;
Vector3 applied_torque;
+ float area_angular_damp;
+ float area_linear_damp;
+
+
SelfList<BodySW> active_list;
SelfList<BodySW> inertia_update_list;
SelfList<BodySW> direct_state_query_list;
@@ -233,7 +240,6 @@ public:
_FORCE_INLINE_ Matrix3 get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
_FORCE_INLINE_ real_t get_friction() const { return friction; }
_FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
- _FORCE_INLINE_ real_t get_density() const { return density; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
_FORCE_INLINE_ void set_axis_lock(PhysicsServer::BodyAxisLock p_lock) { axis_lock=p_lock; }
@@ -335,8 +341,9 @@ public:
BodySW *body;
real_t step;
- virtual Vector3 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area
- virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area
+ virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area
+ virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
+ virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 1a41cda482..a5a132020a 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -82,6 +82,10 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) {
_shape_changed();
+ if (!moved_list.in_list() && get_space())
+ get_space()->area_add_to_moved_list(&moved_list);
+
+
}
void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) {
@@ -102,6 +106,10 @@ void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_meth
_shape_changed();
+ if (!moved_list.in_list() && get_space())
+ get_space()->area_add_to_moved_list(&moved_list);
+
+
}
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index c86bb51f1d..2fbfcaca60 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -337,9 +337,9 @@ public:
Body2DSW *body;
real_t step;
- virtual Vector2 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area
- virtual float get_total_angular_damp() const { return body->get_angular_damp(); } // get density of this body space/area
- virtual float get_total_linear_damp() const { return body->get_linear_damp(); } // get density of this body space/area
+ virtual Vector2 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area
+ virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
+ virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index e02601af41..53409acdfb 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -39,13 +39,18 @@ void PhysicsDirectBodyState::integrate_forces() {
Vector3 av = get_angular_velocity();
- float damp = 1.0 - step * get_total_density();
+ float linear_damp = 1.0 - step * get_total_linear_damp();
- if (damp<0) // reached zero in the given time
- damp=0;
+ if (linear_damp<0) // reached zero in the given time
+ linear_damp=0;
- lv*=damp;
- av*=damp;
+ float angular_damp = 1.0 - step * get_total_angular_damp();
+
+ if (angular_damp<0) // reached zero in the given time
+ angular_damp=0;
+
+ lv*=linear_damp;
+ av*=angular_damp;
set_linear_velocity(lv);
set_angular_velocity(av);
@@ -70,7 +75,8 @@ PhysicsServer * PhysicsServer::get_singleton() {
void PhysicsDirectBodyState::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity);
- ObjectTypeDB::bind_method(_MD("get_total_density"),&PhysicsDirectBodyState::get_total_density);
+ ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp);
+ ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp);
ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass);
ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia);
@@ -683,7 +689,8 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT );
BIND_CONSTANT( AREA_PARAM_GRAVITY_DISTANCE_SCALE );
BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION );
- BIND_CONSTANT( AREA_PARAM_DENSITY );
+ BIND_CONSTANT( AREA_PARAM_LINEAR_DAMP );
+ BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP );
BIND_CONSTANT( AREA_PARAM_PRIORITY );
BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE );
@@ -698,6 +705,9 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( BODY_PARAM_BOUNCE );
BIND_CONSTANT( BODY_PARAM_FRICTION );
BIND_CONSTANT( BODY_PARAM_MASS );
+ BIND_CONSTANT( BODY_PARAM_GRAVITY_SCALE );
+ BIND_CONSTANT( BODY_PARAM_ANGULAR_DAMP );
+ BIND_CONSTANT( BODY_PARAM_LINEAR_DAMP );
BIND_CONSTANT( BODY_PARAM_MAX );
BIND_CONSTANT( BODY_STATE_TRANSFORM );
diff --git a/servers/physics_server.h b/servers/physics_server.h
index f66ea590b8..b82d4cf5da 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -41,8 +41,9 @@ protected:
static void _bind_methods();
public:
- virtual Vector3 get_total_gravity() const=0; // get gravity vector working on this body space/area
- virtual float get_total_density() const=0; // get density of this body space/area
+ virtual Vector3 get_total_gravity() const=0;
+ virtual float get_total_angular_damp() const=0;
+ virtual float get_total_linear_damp() const=0;
virtual float get_inverse_mass() const=0; // get the mass
virtual Vector3 get_inverse_inertia() const=0; // get density of this body space
@@ -300,7 +301,8 @@ public:
AREA_PARAM_GRAVITY_IS_POINT,
AREA_PARAM_GRAVITY_DISTANCE_SCALE,
AREA_PARAM_GRAVITY_POINT_ATTENUATION,
- AREA_PARAM_DENSITY,
+ AREA_PARAM_LINEAR_DAMP,
+ AREA_PARAM_ANGULAR_DAMP,
AREA_PARAM_PRIORITY
};
@@ -398,6 +400,9 @@ public:
BODY_PARAM_BOUNCE,
BODY_PARAM_FRICTION,
BODY_PARAM_MASS, ///< unused for static, always infinite
+ BODY_PARAM_GRAVITY_SCALE,
+ BODY_PARAM_LINEAR_DAMP,
+ BODY_PARAM_ANGULAR_DAMP,
BODY_PARAM_MAX,
};
@@ -411,7 +416,7 @@ public:
BODY_STATE_LINEAR_VELOCITY,
BODY_STATE_ANGULAR_VELOCITY,
BODY_STATE_SLEEPING,
- BODY_STATE_CAN_SLEEP
+ BODY_STATE_CAN_SLEEP
};
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant)=0;
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 0b115a4d1d..15c757665b 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -1022,6 +1022,7 @@ public:
virtual bool has_feature(VS::Features p_feature) const=0;
+ virtual void restore_framebuffer()=0;
virtual int get_render_info(VS::RenderInfo p_info)=0;
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
index e32f47b3d8..c05438aef3 100644
--- a/servers/visual/rasterizer_dummy.cpp
+++ b/servers/visual/rasterizer_dummy.cpp
@@ -1948,6 +1948,9 @@ bool RasterizerDummy::has_feature(VS::Features p_feature) const {
}
+void RasterizerDummy::restore_framebuffer() {
+
+}
RasterizerDummy::RasterizerDummy() {
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
index cc3c1724a4..9249ad6256 100644
--- a/servers/visual/rasterizer_dummy.h
+++ b/servers/visual/rasterizer_dummy.h
@@ -779,6 +779,7 @@ public:
virtual bool has_feature(VS::Features p_feature) const;
+ virtual void restore_framebuffer();
RasterizerDummy();
virtual ~RasterizerDummy();
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index b51f59050d..155d10d85a 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -7351,6 +7351,8 @@ void VisualServerRaster::_draw_cursors_and_margins() {
rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1));
};
+
+
if (black_image[MARGIN_LEFT].is_valid()) {
Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_LEFT]),rasterizer->texture_get_height(black_image[MARGIN_LEFT]));
rasterizer->canvas_draw_rect(Rect2(0,0,black_margin[MARGIN_LEFT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_LEFT],Color(1,1,1));
@@ -7362,10 +7364,22 @@ void VisualServerRaster::_draw_cursors_and_margins() {
rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_RIGHT],Color(1,1,1));
} else if (black_margin[MARGIN_RIGHT])
rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,1,1),RID(),Color(0,0,0));
- if (black_margin[MARGIN_TOP])
+
+ if (black_image[MARGIN_TOP].is_valid()) {
+ Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_TOP]),rasterizer->texture_get_height(black_image[MARGIN_TOP]));
+ rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_TOP],Color(1,1,1));
+
+ } else if (black_margin[MARGIN_TOP]) {
rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,1,1),RID(),Color(0,0,0));
- if (black_margin[MARGIN_BOTTOM])
+ }
+
+ if (black_image[MARGIN_BOTTOM].is_valid()) {
+
+ Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_BOTTOM]),rasterizer->texture_get_height(black_image[MARGIN_BOTTOM]));
+ rasterizer->canvas_draw_rect(Rect2(0,window_h-black_margin[MARGIN_BOTTOM],window_w,black_margin[MARGIN_BOTTOM]),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_BOTTOM],Color(1,1,1));
+ } else if (black_margin[MARGIN_BOTTOM]) {
rasterizer->canvas_draw_rect(Rect2(0,window_h-black_margin[MARGIN_BOTTOM],window_w,black_margin[MARGIN_BOTTOM]),0,Rect2(0,0,1,1),RID(),Color(0,0,0));
+ }
rasterizer->canvas_end_rect();
};
@@ -7413,6 +7427,8 @@ void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_col
if (p_image.empty())
return;
+ rasterizer->restore_framebuffer();
+
rasterizer->begin_frame();
int window_w = OS::get_singleton()->get_video_mode(0).width;
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp
index d431af6c8d..96bd1ed27d 100644
--- a/tools/editor/animation_editor.cpp
+++ b/tools/editor/animation_editor.cpp
@@ -33,6 +33,7 @@
#include "io/resource_saver.h"
#include "pair.h"
#include "scene/gui/separator.h"
+#include "editor_node.h"
/* Missing to fix:
*Set
@@ -634,9 +635,14 @@ void AnimationKeyEditor::_menu_track(int p_type) {
last_menu_track_opt=p_type;
switch(p_type) {
- case TRACK_MENU_ADD_VALUE_TRACK:
- case TRACK_MENU_ADD_TRANSFORM_TRACK:
case TRACK_MENU_ADD_CALL_TRACK: {
+ if (root) {
+ call_select->popup_centered_ratio();
+ break;
+ }
+ } break;
+ case TRACK_MENU_ADD_VALUE_TRACK:
+ case TRACK_MENU_ADD_TRANSFORM_TRACK: {
undo_redo->create_action("Anim Add Track");
undo_redo->add_do_method(animation.ptr(),"add_track",p_type);
@@ -2735,6 +2741,7 @@ void AnimationKeyEditor::_notification(int p_what) {
}
+ call_select->connect("selected",this,"_add_call_track");
// rename_anim->set_icon( get_icon("Rename","EditorIcons") );
/*
edit_anim->set_icon( get_icon("Edit","EditorIcons") );
@@ -3456,6 +3463,26 @@ void AnimationKeyEditor::_scale() {
}
+void AnimationKeyEditor::_add_call_track(const NodePath& p_base) {
+
+ print_line("BASE IS "+String(p_base));
+ Node* base = EditorNode::get_singleton()->get_edited_scene();
+ if (!base)
+ return;
+ Node* from=base->get_node(p_base);
+ if (!from || !root)
+ return;
+
+ NodePath path = root->get_path_to(from);
+
+ undo_redo->create_action("Anim Add Call Track");
+ undo_redo->add_do_method(animation.ptr(),"add_track",Animation::TYPE_METHOD);
+ undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),path);
+ undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
+ undo_redo->commit_action();
+
+}
+
void AnimationKeyEditor::cleanup() {
set_animation(Ref<Animation>());
@@ -3503,6 +3530,7 @@ void AnimationKeyEditor::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize);
ObjectTypeDB::bind_method(_MD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed);
ObjectTypeDB::bind_method(_MD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves);
+ ObjectTypeDB::bind_method(_MD("_add_call_track"),&AnimationKeyEditor::_add_call_track);
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
@@ -3815,7 +3843,9 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
scale_dialog->connect("confirmed",this,"_scale");
add_child(scale_dialog);
-
+ call_select = memnew( SceneTreeDialog );
+ add_child(call_select);
+ call_select->set_title("Call Functions in Which Node?");
}
diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h
index 35053fb6a3..4a1cc21154 100644
--- a/tools/editor/animation_editor.h
+++ b/tools/editor/animation_editor.h
@@ -44,7 +44,7 @@
#include "scene_tree_editor.h"
#include "editor_data.h"
#include "property_editor.h"
-
+#include "scene_tree_editor.h"
class AnimationKeyEdit;
class AnimationCurveEdit;
@@ -206,6 +206,8 @@ class AnimationKeyEditor : public VBoxContainer {
PropertyEditor *key_editor;
+ SceneTreeDialog *call_select;
+
Ref<Animation> animation;
void _update_paths();
@@ -299,6 +301,8 @@ class AnimationKeyEditor : public VBoxContainer {
void _toggle_edit_curves();
void _animation_len_update();
+ void _add_call_track(const NodePath& p_base);
+
void _root_removed();
protected:
diff --git a/tools/editor/array_property_edit.cpp b/tools/editor/array_property_edit.cpp
new file mode 100644
index 0000000000..9cd443270b
--- /dev/null
+++ b/tools/editor/array_property_edit.cpp
@@ -0,0 +1,231 @@
+#include "array_property_edit.h"
+
+#include "editor_node.h"
+
+#define ITEMS_PER_PAGE 100
+
+Variant ArrayPropertyEdit::get_array() const{
+
+ Object*o = ObjectDB::get_instance(obj);
+ if (!o)
+ return Array();
+ Variant arr=o->get(property);
+ if (!arr.is_array()) {
+ Variant::CallError ce;
+ arr=Variant::construct(default_type,NULL,0,ce);
+ }
+ return arr;
+}
+
+void ArrayPropertyEdit::_notif_change() {
+ _change_notify();
+}
+void ArrayPropertyEdit::_notif_changev(const String& p_v) {
+
+ _change_notify(p_v.utf8().get_data());
+}
+
+void ArrayPropertyEdit::_set_size(int p_size) {
+
+ Variant arr = get_array();
+ arr.call("resize",p_size);
+ Object*o = ObjectDB::get_instance(obj);
+ if (!o)
+ return;
+
+ o->set(property,arr);
+
+}
+
+void ArrayPropertyEdit::_set_value(int p_idx,const Variant& p_value) {
+
+ Variant arr = get_array();
+ arr.set(p_idx,p_value);
+ Object*o = ObjectDB::get_instance(obj);
+ if (!o)
+ return;
+
+ o->set(property,arr);
+}
+
+bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){
+
+ String pn=p_name;
+
+ if (pn.begins_with("array/")) {
+
+ if (pn=="array/size") {
+
+ Variant arr = get_array();
+ int size = arr.call("size");
+
+ int newsize=p_value;
+ if (newsize==size)
+ return true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Resize Array");
+ ur->add_do_method(this,"_set_size",newsize);
+ ur->add_undo_method(this,"_set_size",size);
+ if (newsize<size) {
+ for(int i=newsize;i<size;i++) {
+ ur->add_undo_method(this,"_set_value",i,arr.get(i));
+
+ }
+ }
+ ur->add_do_method(this,"_notif_change");
+ ur->add_undo_method(this,"_notif_change");
+ ur->commit_action();
+ return true;
+ }
+ if (pn=="array/page") {
+ page=p_value;
+ _change_notify();
+ return true;
+ }
+ } else if (pn.begins_with("indices")) {
+
+ if (pn.find("_")!=-1) {
+ //type
+ int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
+
+ int type = p_value;
+
+ Variant arr = get_array();
+
+ Variant value = arr.get(idx);
+ if (value.get_type()!=type && type>=0 && type<Variant::VARIANT_MAX) {
+ Variant::CallError ce;
+ Variant new_value=Variant::construct(Variant::Type(type),NULL,0,ce);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action("Change Array Value Type");
+ ur->add_do_method(this,"_set_value",idx,new_value);
+ ur->add_undo_method(this,"_set_value",idx,value);
+ ur->add_do_method(this,"_notif_change");
+ ur->add_undo_method(this,"_notif_change");
+ ur->commit_action();
+
+ }
+ return true;
+
+ } else {
+ int idx=pn.get_slicec('/',1).to_int();
+ Variant arr = get_array();
+
+ Variant value = arr.get(idx);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action("Change Array Value");
+ ur->add_do_method(this,"_set_value",idx,p_value);
+ ur->add_undo_method(this,"_set_value",idx,value);
+ ur->add_do_method(this,"_notif_changev",p_name);
+ ur->add_undo_method(this,"_notif_changev",p_name);
+ ur->commit_action();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ArrayPropertyEdit::_get(const StringName& p_name,Variant &r_ret) const {
+
+ Variant arr = get_array();
+ //int size = arr.call("size");
+
+ String pn=p_name;
+ if (pn.begins_with("array/")) {
+
+ if (pn=="array/size") {
+ r_ret=arr.call("size");
+ return true;
+ }
+ if (pn=="array/page") {
+ r_ret=page;
+ return true;
+ }
+ } else if (pn.begins_with("indices")) {
+
+ if (pn.find("_")!=-1) {
+ //type
+ int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
+ bool valid;
+ r_ret=arr.get(idx,&valid);
+ if (valid)
+ r_ret=r_ret.get_type();
+ return valid;
+
+ } else {
+ int idx=pn.get_slicec('/',1).to_int();
+ bool valid;
+ r_ret=arr.get(idx,&valid);
+ return valid;
+ }
+ }
+
+ return false;
+}
+
+void ArrayPropertyEdit::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ Variant arr = get_array();
+ int size = arr.call("size");
+
+ p_list->push_back( PropertyInfo(Variant::INT,"array/size",PROPERTY_HINT_RANGE,"0,100000,1") );
+ int pages = size/ITEMS_PER_PAGE;
+ if (pages>0)
+ p_list->push_back( PropertyInfo(Variant::INT,"array/page",PROPERTY_HINT_RANGE,"0,"+itos(pages)+",1") );
+
+ int offset=page*ITEMS_PER_PAGE;
+
+ int items=MIN(size-offset,ITEMS_PER_PAGE);
+
+
+ for(int i=0;i<items;i++) {
+
+ Variant v=arr.get(i+offset);
+ if (arr.get_type()==Variant::ARRAY) {
+ p_list->push_back(PropertyInfo(Variant::INT,"indices/"+itos(i+offset)+"_type",PROPERTY_HINT_ENUM,vtypes));
+ }
+ if (arr.get_type()!=Variant::ARRAY || v.get_type()!=Variant::NIL) {
+ PropertyInfo pi(v.get_type(),"indices/"+itos(i+offset));
+ if (v.get_type()==Variant::OBJECT) {
+ pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string="Resource";
+ }
+ p_list->push_back(pi);
+ }
+ }
+
+}
+
+void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,Variant::Type p_deftype) {
+
+ page=0;
+ property=p_prop;
+ obj=p_obj->get_instance_ID();
+ default_type=p_deftype;
+
+}
+
+void ArrayPropertyEdit::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("_set_size"),&ArrayPropertyEdit::_set_size);
+ ObjectTypeDB::bind_method(_MD("_set_value"),&ArrayPropertyEdit::_set_value);
+ ObjectTypeDB::bind_method(_MD("_notif_change"),&ArrayPropertyEdit::_notif_change);
+ ObjectTypeDB::bind_method(_MD("_notif_changev"),&ArrayPropertyEdit::_notif_changev);
+}
+
+ArrayPropertyEdit::ArrayPropertyEdit()
+{
+ page=0;
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+
+ if (i>0)
+ vtypes+=",";
+ vtypes+=Variant::get_type_name( Variant::Type(i) );
+ }
+ default_type=Variant::NIL;
+
+}
diff --git a/tools/editor/array_property_edit.h b/tools/editor/array_property_edit.h
new file mode 100644
index 0000000000..acfb8e68ed
--- /dev/null
+++ b/tools/editor/array_property_edit.h
@@ -0,0 +1,36 @@
+#ifndef ARRAY_PROPERTY_EDIT_H
+#define ARRAY_PROPERTY_EDIT_H
+
+#include "scene/main/node.h"
+
+class ArrayPropertyEdit : public Reference {
+
+ OBJ_TYPE(ArrayPropertyEdit,Reference);
+
+ int page;
+ ObjectID obj;
+ StringName property;
+ String vtypes;
+ Variant get_array() const;
+ Variant::Type default_type;
+
+ void _notif_change();
+ void _notif_changev(const String& p_v);
+ void _set_size(int p_size);
+ void _set_value(int p_idx,const Variant& p_value);
+
+protected:
+
+ static void _bind_methods();
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+ void edit(Object* p_obj, const StringName& p_prop, Variant::Type p_deftype);
+
+ ArrayPropertyEdit();
+};
+
+#endif // ARRAY_PROPERTY_EDIT_H
diff --git a/tools/editor/dependency_editor.cpp b/tools/editor/dependency_editor.cpp
new file mode 100644
index 0000000000..c04e82a08a
--- /dev/null
+++ b/tools/editor/dependency_editor.cpp
@@ -0,0 +1,512 @@
+#include "dependency_editor.h"
+#include "os/file_access.h"
+#include "scene/gui/margin_container.h"
+#include "io/resource_loader.h"
+#include "editor_node.h"
+
+void DependencyEditor::_notification(int p_what){
+
+
+}
+
+void DependencyEditor::_searched(const String& p_path) {
+
+ Map<String,String> dep_rename;
+ dep_rename[replacing]=p_path;
+
+
+ ResourceLoader::rename_dependencies(editing,dep_rename);
+
+ _update_list();
+ _update_file();
+}
+
+void DependencyEditor::_load_pressed(Object* p_item,int p_cell,int p_button){
+
+ TreeItem *ti=p_item->cast_to<TreeItem>();
+ String fname = ti->get_text(0);
+ replacing = ti->get_text(1);
+
+ search->set_title("Search Replacement For: "+replacing.get_file());
+
+ search->clear_filters();
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0),&ext);
+ for (List<String>::Element *E=ext.front();E;E=E->next()) {
+ search->add_filter("*"+E->get());
+ }
+ search->popup_centered_ratio();
+
+}
+
+void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates){
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _fix_and_find(efsd->get_subdir(i),candidates);
+ }
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ String file = efsd->get_file(i);
+ if (!candidates.has(file))
+ continue;
+
+ String path = efsd->get_file_path(i);
+ Map<String,String> &ss = candidates[file];
+
+
+ for(Map<String,String>::Element *E=candidates[file].front();E;E=E->next()) {
+
+ if (E->get()==String()) {
+ E->get()=path;
+ continue;
+ }
+
+ //must match the best, using subdirs
+ String existing=E->get().replace_first("res://","");
+ String current=path.replace_first("res://","");
+ String lost=E->key().replace_first("res://","");
+
+ Vector<String> existingv=existing.split("/");
+ existingv.invert();
+ Vector<String> currentv=current.split("/");
+ currentv.invert();
+ Vector<String> lostv=lost.split("/");
+ lostv.invert();
+
+ int existing_score=0;
+ int current_score=0;
+
+ for(int j=0;j<lostv.size();j++) {
+
+ if (j<existingv.size() && lostv[j]==existingv[j]) {
+ existing_score++;
+ }
+ if (j<currentv.size() && lostv[j]==currentv[j]) {
+ current_score++;
+ }
+ }
+
+ if (current_score > existing_score) {
+
+ //if it was the same, could track distance to new path but..
+
+ E->get()=path; //replace by more accurate
+ }
+
+ }
+
+ }
+
+}
+
+
+void DependencyEditor::_fix_all(){
+
+ if (!EditorFileSystem::get_singleton()->get_filesystem())
+ return;
+
+ Map<String,Map<String,String> > candidates;
+
+ for (List<String>::Element *E=missing.front();E;E=E->next()) {
+
+ String base = E->get().get_file();
+ if (!candidates.has(base)) {
+ candidates[base]=Map<String,String>();
+ }
+
+ candidates[base][E->get()]="";
+ }
+
+ _fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(),candidates);
+
+ Map<String,String> remaps;
+
+ for (Map<String,Map<String,String> >::Element *E=candidates.front();E;E=E->next()) {
+
+ for (Map<String,String>::Element *F=E->get().front();F;F=F->next()) {
+
+ if (F->get()!=String()) {
+ remaps[F->key()]=F->get();
+ }
+ }
+
+ }
+
+ if (remaps.size()) {
+
+ ResourceLoader::rename_dependencies(editing,remaps);
+
+ _update_list();
+ _update_file();
+ }
+}
+
+void DependencyEditor::_update_file() {
+
+ EditorFileSystem::get_singleton()->update_file(editing);
+
+}
+
+void DependencyEditor::_update_list() {
+
+ List<String> deps;
+ ResourceLoader::get_dependencies(editing,&deps,true);
+
+ tree->clear();
+ missing.clear();
+
+ TreeItem *root = tree->create_item();
+
+ Ref<Texture> folder = get_icon("folder","FileDialog");
+
+ bool broken=false;
+
+ for(List<String>::Element *E=deps.front();E;E=E->next()) {
+
+ TreeItem *item = tree->create_item(root);
+
+ String n = E->get();
+ String path;
+ String type;
+
+ if (n.find("::")!=-1) {
+ path = n.get_slice("::",0);
+ type = n.get_slice("::",1);
+ } else {
+ path=n;
+ type="Resource";
+ }
+ String name = path.get_file();
+
+ Ref<Texture> icon;
+ if (has_icon(type,"EditorIcons")) {
+ icon=get_icon(type,"EditorIcons");
+ } else {
+ icon=get_icon("Object","EditorIcons");
+ }
+ item->set_text(0,name);
+ item->set_icon(0,icon);
+ item->set_metadata(0,type);
+ item->set_text(1,path);
+
+ if (!FileAccess::exists(path)) {
+ item->set_custom_color(1,Color(1,0.4,0.3));
+ missing.push_back(path);
+ broken=true;
+ }
+
+ item->add_button(1,folder,0);
+ }
+
+ fixdeps->set_disabled(!broken);
+
+}
+
+
+
+void DependencyEditor::edit(const String& p_path) {
+
+
+ editing=p_path;
+ set_title("Dependencies For: "+p_path.get_file());
+
+ _update_list();
+ popup_centered_ratio();
+
+ if (EditorNode::get_singleton()->is_scene_open(p_path)) {
+ EditorNode::get_singleton()->show_warning("Scene '"+p_path.get_file()+"' is currently being edited.\nChanges will not take effect unless reloaded.");
+ } else if (ResourceCache::has(p_path)) {
+ EditorNode::get_singleton()->show_warning("Resource '"+p_path.get_file()+"' is in use.\nChanges will take effect when reloaded.");
+ }
+}
+
+
+void DependencyEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("_searched"),&DependencyEditor::_searched);
+ ObjectTypeDB::bind_method(_MD("_load_pressed"),&DependencyEditor::_load_pressed);
+ ObjectTypeDB::bind_method(_MD("_fix_all"),&DependencyEditor::_fix_all);
+
+}
+
+DependencyEditor::DependencyEditor() {
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ vb->set_name("Dependencies");
+ add_child(vb);
+ set_child_rect(vb);
+
+ tree = memnew( Tree );
+ tree->set_columns(2);
+ tree->set_column_titles_visible(true);
+ tree->set_column_title(0,"Resource");
+ tree->set_column_title(1,"Path");
+ tree->set_hide_root(true);
+ tree->connect("button_pressed",this,"_load_pressed");
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ Label *label = memnew( Label("Dependencies:"));
+ hbc->add_child(label);
+ hbc->add_spacer();
+ fixdeps = memnew( Button("Fix Broken"));
+ hbc->add_child(fixdeps);
+ fixdeps->connect("pressed",this,"_fix_all");
+
+ vb->add_child(hbc);
+
+ MarginContainer *mc = memnew( MarginContainer );
+ mc->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ mc->add_child(tree);
+ vb->add_child(mc);
+
+ set_title("Dependency Editor");
+ search = memnew( EditorFileDialog );
+ search->connect("file_selected",this,"_searched");
+ search->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ search->set_title("Search Replacement Resource:");
+ add_child(search);
+
+}
+
+/////////////////////////////////////
+
+
+
+void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) {
+
+ if (!efsd)
+ return;
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _fill_owners(efsd->get_subdir(i));
+ }
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ Vector<String> deps = efsd->get_file_deps(i);
+ //print_line(":::"+efsd->get_file_path(i));
+ bool found=false;
+ for(int j=0;j<deps.size();j++) {
+ //print_line("\t"+deps[j]+" vs "+editing);
+ if (deps[j]==editing) {
+ //print_line("found");
+ found=true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+
+ Ref<Texture> icon;
+ String type=efsd->get_file_type(i);
+ if (!has_icon(type,"EditorIcons")) {
+ icon=get_icon("Object","EditorIcons");
+ } else {
+ icon=get_icon(type,"EditorIcons");
+ }
+
+ owners->add_item(efsd->get_file_path(i),icon);
+ }
+
+}
+
+void DependencyEditorOwners::show(const String& p_path) {
+
+ editing=p_path;
+ owners->clear();
+ _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+ popup_centered_ratio();
+
+ set_title("Owners Of: "+p_path.get_file());
+
+}
+
+DependencyEditorOwners::DependencyEditorOwners() {
+
+
+ owners = memnew( ItemList );
+ add_child(owners);
+ set_child_rect(owners);
+
+
+}
+
+///////////////////////
+
+
+void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) {
+
+ if (!efsd)
+ return;
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _fill_owners(efsd->get_subdir(i));
+ }
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ Vector<String> deps = efsd->get_file_deps(i);
+ //print_line(":::"+efsd->get_file_path(i));
+ Set<String> met;
+ for(int j=0;j<deps.size();j++) {
+ if (files.has(deps[j])) {
+ met.insert(deps[j]);
+ }
+ }
+ if (!met.size())
+ continue;
+
+ exist=true;
+
+ Ref<Texture> icon;
+ String type=efsd->get_file_type(i);
+ if (!has_icon(type,"EditorIcons")) {
+ icon=get_icon("Object","EditorIcons");
+ } else {
+ icon=get_icon(type,"EditorIcons");
+ }
+
+
+ for(Set<String>::Element *E=met.front();E;E=E->next()) {
+
+ String which = E->get();
+ if (!files[which]) {
+ TreeItem *ti=owners->create_item(owners->get_root());
+ ti->set_text(0,which.get_file());
+ files[which]=ti;
+
+ }
+ TreeItem *ti=owners->create_item(files[which]);
+ ti->set_text(0,efsd->get_file_path(i));
+ ti->set_icon(0,icon);
+ }
+
+ }
+
+}
+
+void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
+
+ exist=false;
+ owners->clear();
+ files.clear();
+ TreeItem *root=owners->create_item();
+ for(int i=0;i<to_erase.size();i++) {
+ files[to_erase[i]]=NULL;
+ }
+
+ _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+
+ if (exist) {
+ owners->show();
+ text->set_text("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)");
+ popup_centered_minsize(Size2(500,220));
+ } else {
+ owners->hide();
+ text->set_text("Remove selected files from the project? (no undo)");
+ popup_centered_minsize(Size2(400,100));
+ }
+
+}
+
+void DependencyRemoveDialog::ok_pressed() {
+
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ for (Map<String,TreeItem*>::Element *E=files.front();E;E=E->next()) {
+
+ da->remove(E->key());
+ EditorFileSystem::get_singleton()->update_file(E->key());
+ }
+ memdelete(da);
+
+}
+
+DependencyRemoveDialog::DependencyRemoveDialog() {
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+ set_child_rect(vb);
+
+ text = memnew( Label );
+ vb->add_child(text);
+
+ owners = memnew( Tree );
+ owners->set_hide_root(true);
+ vb->add_child(owners);
+ owners->set_v_size_flags(SIZE_EXPAND_FILL);
+ get_ok()->set_text("Remove");
+}
+
+
+//////////////
+
+
+void DependencyErrorDialog::show(const String& p_for_file,const Vector<String> &report) {
+
+
+ for_file=p_for_file;
+ set_title("Error loading: "+p_for_file.get_file());
+ files->clear();
+
+ TreeItem *root = files->create_item(NULL);
+ for(int i=0;i<report.size();i++) {
+
+ String dep;
+ String type="Object";
+ dep=report[i].get_slice("::",0);
+ if (report[i].get_slice_count("::")>0)
+ type=report[i].get_slice("::",1);
+
+ Ref<Texture> icon;
+ if (!has_icon(type,"EditorIcons")) {
+ icon=get_icon("Object","EditorIcons");
+ } else {
+ icon=get_icon(type,"EditorIcons");
+ }
+
+ TreeItem *ti=files->create_item(root);
+ ti->set_text(0,dep);
+ ti->set_icon(0,icon);
+
+ }
+
+ popup_centered_minsize(Size2(500,220));
+
+}
+
+void DependencyErrorDialog::ok_pressed() {
+
+ EditorNode::get_singleton()->load_scene(for_file,true);
+}
+
+void DependencyErrorDialog::custom_action(const String&) {
+
+ EditorNode::get_singleton()->fix_dependencies(for_file);
+}
+
+DependencyErrorDialog::DependencyErrorDialog() {
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+ set_child_rect(vb);
+
+
+ files = memnew( Tree );
+ files->set_hide_root(true);
+ vb->add_margin_child("Scene failed to load due to missing dependencies:",files,true);
+ files->set_v_size_flags(SIZE_EXPAND_FILL);
+ get_ok()->set_text("Open Anyway");
+
+ text = memnew( Label );
+ vb->add_child(text);
+ text->set_text("Which action should be taken?");
+
+
+ fdep=add_button("Fix Dependencies",true,"fixdeps");
+
+ set_title("Errors loading!");
+
+}
diff --git a/tools/editor/dependency_editor.h b/tools/editor/dependency_editor.h
new file mode 100644
index 0000000000..1c328e7a93
--- /dev/null
+++ b/tools/editor/dependency_editor.h
@@ -0,0 +1,94 @@
+#ifndef DEPENDENCY_EDITOR_H
+#define DEPENDENCY_EDITOR_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/tab_container.h"
+#include "editor_file_dialog.h"
+
+class EditorFileSystemDirectory;
+
+class DependencyEditor : public AcceptDialog {
+ OBJ_TYPE(DependencyEditor,AcceptDialog);
+
+
+ Tree *tree;
+ Button *fixdeps;
+
+ EditorFileDialog *search;
+
+ String replacing;
+ String editing;
+ List<String> missing;
+
+
+ void _fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates);
+
+ void _searched(const String& p_path);
+ void _load_pressed(Object* p_item,int p_cell,int p_button);
+ void _fix_all();
+ void _update_list();
+
+ void _update_file();
+
+protected:
+
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+
+ void edit(const String& p_path);
+ DependencyEditor();
+};
+
+class DependencyEditorOwners : public AcceptDialog {
+ OBJ_TYPE(DependencyEditorOwners,AcceptDialog);
+
+ ItemList *owners;
+ String editing;
+ void _fill_owners(EditorFileSystemDirectory *efsd);
+
+public:
+
+ void show(const String& p_path);
+ DependencyEditorOwners();
+};
+
+class DependencyRemoveDialog : public ConfirmationDialog {
+ OBJ_TYPE(DependencyRemoveDialog,ConfirmationDialog);
+
+
+ Label *text;
+ Tree *owners;
+ bool exist;
+ Map<String,TreeItem*> files;
+ void _fill_owners(EditorFileSystemDirectory *efsd);
+
+ void ok_pressed();
+
+public:
+
+ void show(const Vector<String> &to_erase);
+ DependencyRemoveDialog();
+};
+
+
+class DependencyErrorDialog : public ConfirmationDialog {
+ OBJ_TYPE(DependencyErrorDialog,ConfirmationDialog);
+
+
+ String for_file;
+ Button *fdep;
+ Label *text;
+ Tree *files;
+ void ok_pressed();
+ void custom_action(const String&);
+
+public:
+
+ void show(const String& p_for,const Vector<String> &report);
+ DependencyErrorDialog();
+};
+
+#endif // DEPENDENCY_EDITOR_H
diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp
index 7f42f19a9b..673ee30adb 100644
--- a/tools/editor/editor_data.cpp
+++ b/tools/editor/editor_data.cpp
@@ -39,7 +39,7 @@ void EditorHistory::_cleanup_history() {
bool fail=false;
for(int j=0;j<history[i].path.size();j++) {
- if (!history[i].path[j].res.is_null())
+ if (!history[i].path[j].ref.is_null())
continue;
if (ObjectDB::get_instance(history[i].path[j].object))
@@ -70,10 +70,10 @@ void EditorHistory::_add_object(ObjectID p_object,const String& p_property,int p
Object *obj = ObjectDB::get_instance(p_object);
ERR_FAIL_COND(!obj);
- Resource *r = obj->cast_to<Resource>();
+ Reference *r = obj->cast_to<Reference>();
Obj o;
if (r)
- o.res=RES(r);
+ o.ref=REF(r);
o.object=p_object;
o.property=p_property;
@@ -123,6 +123,27 @@ void EditorHistory::add_object(ObjectID p_object,int p_relevel){
_add_object(p_object,"",p_relevel);
}
+int EditorHistory::get_history_len() {
+ return history.size();
+}
+int EditorHistory::get_history_pos() {
+ return current;
+}
+
+ObjectID EditorHistory::get_history_obj(int p_obj) const {
+ ERR_FAIL_INDEX_V(p_obj,history.size(),0);
+ ERR_FAIL_INDEX_V(history[p_obj].level,history[p_obj].path.size(),0);
+ return history[p_obj].path[history[p_obj].level].object;
+}
+
+bool EditorHistory::is_at_begining() const {
+ return current<=0;
+}
+bool EditorHistory::is_at_end() const {
+
+ return ((current+1)>=history.size());
+}
+
bool EditorHistory::next() {
@@ -523,7 +544,7 @@ Ref<Script> EditorData::get_scene_root_script(int p_idx) const {
if (!edited_scene[p_idx].root)
return Ref<Script>();
Ref<Script> s=edited_scene[p_idx].root->get_script();
- if (!s.is_valid()) {
+ if (!s.is_valid() && edited_scene[p_idx].root->get_child_count()) {
Node *n = edited_scene[p_idx].root->get_child(0);
while(!s.is_valid() && n && n->get_filename()==String()) {
s=n->get_script();
diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h
index cbec2295f6..c5ee83ae63 100644
--- a/tools/editor/editor_data.h
+++ b/tools/editor/editor_data.h
@@ -45,7 +45,7 @@ class EditorHistory {
struct Obj {
- RES res;
+ REF ref;
ObjectID object;
String property;
};
@@ -75,10 +75,17 @@ friend class EditorData;
public:
+ bool is_at_begining() const;
+ bool is_at_end() const;
+
void add_object(ObjectID p_object);
void add_object(ObjectID p_object,const String& p_subprop);
void add_object(ObjectID p_object,int p_relevel);
+ int get_history_len();
+ int get_history_pos();
+ ObjectID get_history_obj(int p_obj) const;
+
bool next();
bool previous();
ObjectID get_current();
diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp
index b1bbd71f7b..c62347d129 100644
--- a/tools/editor/editor_file_dialog.cpp
+++ b/tools/editor/editor_file_dialog.cpp
@@ -190,7 +190,7 @@ void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>&
void EditorFileDialog::_request_single_thumbnail(const String& p_path) {
EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path);
- print_line("want file "+p_path);
+ //print_line("want file "+p_path);
set_process(true);
preview_waiting=true;
preview_wheel_timeout=0;
@@ -359,7 +359,7 @@ void EditorFileDialog::_item_dc_selected(int p_item) {
if (d["dir"]) {
- print_line("change dir: "+String(d["name"]));
+ //print_line("change dir: "+String(d["name"]));
dir_access->change_dir(d["name"]);
if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR)
file->set_text("");
@@ -536,6 +536,7 @@ void EditorFileDialog::update_file_list() {
if (get_icon_func) {
+
Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
//ti->set_icon(0,icon);
if (display_mode==DISPLAY_THUMBNAILS) {
diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp
index d741087a9f..33e4a15c85 100644
--- a/tools/editor/editor_file_system.cpp
+++ b/tools/editor/editor_file_system.cpp
@@ -94,6 +94,12 @@ bool EditorFileSystemDirectory::get_file_meta(int p_idx) const {
return files[p_idx].meta.enabled;
}
+Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
+ return files[p_idx].meta.deps;
+
+}
Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
@@ -118,7 +124,7 @@ bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const {
return false;
}
-String EditorFileSystemDirectory::get_file_type(int p_idx) const {
+StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,files.size(),"");
return files[p_idx].type;
@@ -198,6 +204,13 @@ EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String&
}
m.import_editor=imd->get_editor();
}
+
+ List<String> deps;
+ ResourceLoader::get_dependencies(p_path,&deps);
+ for(List<String>::Element *E=deps.front();E;E=E->next()) {
+ m.deps.push_back(E->get());
+ }
+
return m;
}
@@ -358,7 +371,7 @@ void EditorFileSystem::_scan_scenes() {
String project=Globals::get_singleton()->get_resource_path();
- String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache");
+ String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache");
FileAccess *f =FileAccess::open(fscache,FileAccess::READ);
if (f) {
@@ -397,7 +410,7 @@ void EditorFileSystem::_scan_scenes() {
} else {
Vector<String> split = l.split("::");
- ERR_CONTINUE( split.size() != 4);
+ ERR_CONTINUE( split.size() != 5);
String name = split[0];
String file;
@@ -429,6 +442,15 @@ void EditorFileSystem::_scan_scenes() {
}
}
+ String deps = split[4].strip_edges();
+ if (deps.length()) {
+ Vector<String> dp = deps.split("<>");
+ for(int i=0;i<dp.size();i++) {
+ String path=dp[i];
+ fc.meta.deps.push_back(path);
+ }
+ }
+
file_cache[name]=fc;
ERR_CONTINUE(!dc);
@@ -530,6 +552,7 @@ void EditorFileSystem::scan() {
thread = Thread::create(_thread_func,this,s);
//tree->hide();
//progress->show();
+
}
@@ -798,6 +821,14 @@ void EditorFileSystem::_save_type_cache_fs(DirItem *p_dir,FileAccess *p_file) {
}
}
+ s+="::";
+ for(int j=0;j<p_dir->files[i]->meta.deps.size();j++) {
+
+ if (j>0)
+ s+="<>";
+ s+=p_dir->files[i]->meta.deps[j];
+ }
+
p_file->store_line(s);
}
@@ -1037,6 +1068,13 @@ void EditorFileSystem::update_file(const String& p_file) {
return;
}
+ if (!FileAccess::exists(p_file)) {
+ //was removed
+ fs->files.remove(cpos);
+ call_deferred("emit_signal","filesystem_changed"); //update later
+ return;
+
+ }
String type = ResourceLoader::get_resource_type(p_file);
diff --git a/tools/editor/editor_file_system.h b/tools/editor/editor_file_system.h
index 3f413292fe..f79dd209ef 100644
--- a/tools/editor/editor_file_system.h
+++ b/tools/editor/editor_file_system.h
@@ -59,13 +59,14 @@ class EditorFileSystemDirectory : public Object {
Vector<Source> sources;
String import_editor;
+ Vector<String> deps;
bool enabled;
};
struct FileInfo {
String file;
- String type;
+ StringName type;
uint64_t modified_time;
ImportMeta meta;
@@ -87,10 +88,11 @@ public:
int get_file_count() const;
String get_file(int p_idx) const;
String get_file_path(int p_idx) const;
- String get_file_type(int p_idx) const;
+ StringName get_file_type(int p_idx) const;
bool get_file_meta(int p_idx) const;
bool is_missing_sources(int p_idx) const;
Vector<String> get_missing_sources(int p_idx) const;
+ Vector<String> get_file_deps(int p_idx) const;
EditorFileSystemDirectory *get_parent();
@@ -120,7 +122,7 @@ class EditorFileSystem : public Node {
String path;
String name;
Vector<DirItem*> dirs;
- Vector<SceneItem*> files;
+ Vector<SceneItem*> files;
~DirItem();
};
@@ -149,6 +151,7 @@ class EditorFileSystem : public Node {
String type;
uint64_t modification_time;
EditorFileSystemDirectory::ImportMeta meta;
+ Vector<String> deps;
};
struct DirCache {
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index b28b349c86..84fc14d2ec 100644
--- a/tools/editor/editor_import_export.cpp
+++ b/tools/editor/editor_import_export.cpp
@@ -255,7 +255,16 @@ static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter)
}
+Vector<uint8_t> EditorExportPlatform::get_exported_file_default(String& p_fname) const {
+ FileAccess *f = FileAccess::open(p_fname,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,Vector<uint8_t>());
+ Vector<uint8_t> ret;
+ ret.resize(f->get_len());
+ int rbs = f->get_buffer(ret.ptr(),ret.size());
+ memdelete(f);
+ return ret;
+}
Vector<uint8_t> EditorExportPlatform::get_exported_file(String& p_fname) const {
@@ -270,13 +279,9 @@ Vector<uint8_t> EditorExportPlatform::get_exported_file(String& p_fname) const {
}
- FileAccess *f = FileAccess::open(p_fname,FileAccess::READ);
- ERR_FAIL_COND_V(!f,Vector<uint8_t>());
- Vector<uint8_t> ret;
- ret.resize(f->get_len());
- int rbs = f->get_buffer(ret.ptr(),ret.size());
- memdelete(f);
- return ret;
+ return get_exported_file_default(p_fname);
+
+
}
Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const {
@@ -557,6 +562,7 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink();
switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(E->get())) {
+ case EditorImportExport::IMAGE_ACTION_KEEP:
case EditorImportExport::IMAGE_ACTION_NONE: {
switch(EditorImportExport::get_singleton()->get_export_image_action()) {
@@ -581,7 +587,7 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
} break; //use default
case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
- } break; //use default
+ } break; //use default
}
String image_list_md5;
@@ -825,13 +831,32 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
StringName engine_cfg="res://engine.cfg";
+ StringName boot_splash;
+ {
+ String splash=Globals::get_singleton()->get("application/boot_splash"); //avoid splash from being converted
+ splash=splash.strip_edges();
+ if (splash!=String()) {
+ if (!splash.begins_with("res://"))
+ splash="res://"+splash;
+ splash=splash.simplify_path();
+ boot_splash=splash;
+ }
+ }
+
+
+
for(int i=0;i<files.size();i++) {
if (remap_files.has(files[i]) || files[i]==engine_cfg) //gonna be remapped (happened before!)
continue; //from atlas?
String src=files[i];
- Vector<uint8_t> buf = get_exported_file(src);
+ Vector<uint8_t> buf;
+
+ if (src==boot_splash)
+ buf = get_exported_file_default(src); //bootsplash must be kept if used
+ else
+ buf = get_exported_file(src);
ERR_CONTINUE( saved.has(src) );
@@ -1608,6 +1633,8 @@ void EditorImportExport::load_config() {
g.action=IMAGE_ACTION_COMPRESS_RAM;
else if (action=="compress_disk")
g.action=IMAGE_ACTION_COMPRESS_DISK;
+ else if (action=="keep")
+ g.action=IMAGE_ACTION_KEEP;
}
if (d.has("atlas"))
@@ -1735,6 +1762,7 @@ void EditorImportExport::save_config() {
case IMAGE_ACTION_NONE: d["action"]="default"; break;
case IMAGE_ACTION_COMPRESS_RAM: d["action"]="compress_ram"; break;
case IMAGE_ACTION_COMPRESS_DISK: d["action"]="compress_disk"; break;
+ case IMAGE_ACTION_KEEP: d["action"]="keep"; break;
}
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
index f134a479a4..d8601929cf 100644
--- a/tools/editor/editor_import_export.h
+++ b/tools/editor/editor_import_export.h
@@ -83,6 +83,7 @@ public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
protected:
+ Vector<uint8_t> get_exported_file_default(String& p_fname) const;
virtual Vector<uint8_t> get_exported_file(String& p_fname) const;
virtual Vector<StringName> get_dependencies(bool p_bundles) const;
@@ -227,6 +228,8 @@ public:
IMAGE_ACTION_NONE,
IMAGE_ACTION_COMPRESS_DISK,
IMAGE_ACTION_COMPRESS_RAM,
+ IMAGE_ACTION_KEEP //for group
+
};
enum ScriptAction {
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index b0a2c568de..63684dcc93 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -93,7 +93,7 @@
#include "plugins/light_occluder_2d_editor_plugin.h"
#include "plugins/color_ramp_editor_plugin.h"
#include "plugins/collision_shape_2d_editor_plugin.h"
-
+#include "os/input.h"
// end
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
@@ -459,17 +459,74 @@ void EditorNode::open_resource(const String& p_type) {
current_option=RESOURCE_LOAD;
}
-void EditorNode::save_resource(const Ref<Resource>& p_resource) {
+void EditorNode::save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path) {
- ERR_FAIL_COND(p_resource.is_null() || p_resource->get_path()=="" || p_resource->get_path().find("::")!=-1);
- resources_dock->save_resource(p_resource->get_path(),p_resource);
+ editor_data.apply_changes_in_editors();
+ int flg=0;
+ if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources"))
+ flg|=ResourceSaver::FLAG_COMPRESS;
+ if (EditorSettings::get_singleton()->get("on_save/save_paths_as_relative"))
+ flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
+
+ String path = Globals::get_singleton()->localize_path(p_path);
+ Error err = ResourceSaver::save(path,p_resource,flg|ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
+
+ if (err!=OK) {
+ accept->set_text("Error saving resource!");
+ accept->popup_centered_minsize();
+ return;
+ }
+// EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
+
+ ((Resource*)p_resource.ptr())->set_path(path);
+ emit_signal("resource_saved",p_resource);
+
+}
+
+void EditorNode::save_resource(const Ref<Resource>& p_resource) {
+
+ if (p_resource->get_path().is_resource_file()) {
+ save_resource_in_path(p_resource,p_resource->get_path());
+ } else {
+ save_resource_as(p_resource);
+ }
}
void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
- resources_dock->save_resource_as(p_resource);
+ file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ bool relpaths = (p_resource->has_meta("__editor_relpaths__") && p_resource->get_meta("__editor_relpaths__").operator bool());
+
+ List<String> extensions;
+ Ref<PackedScene> sd = memnew( PackedScene );
+ ResourceSaver::get_recognized_extensions(p_resource,&extensions);
+ file->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+ //file->set_current_path(current_path);
+ if (p_resource->get_path()!="") {
+ file->set_current_path(p_resource->get_path());
+ if (extensions.size()) {
+ String ext=p_resource->get_path().extension().to_lower();
+ if (extensions.find(ext)==NULL) {
+ file->set_current_path(p_resource->get_path().replacen("."+ext,"."+extensions.front()->get()));
+ }
+ }
+ } else {
+
+ String existing;
+ if (extensions.size()) {
+ existing="new_"+p_resource->get_type().to_lower()+"."+extensions.front()->get().to_lower();
+ }
+ file->set_current_path(existing);
+
+ }
+ file->popup_centered_ratio();
+ file->set_title("Save Resource As..");
}
@@ -1049,7 +1106,7 @@ void EditorNode::_dialog_action(String p_file) {
push_item(res.operator->() );
- } break;
+ } break;
case FILE_OPEN_SCENE: {
@@ -1320,7 +1377,20 @@ void EditorNode::_dialog_action(String p_file) {
unzClose(pkg);
} break;
+ case RESOURCE_SAVE:
+ case RESOURCE_SAVE_AS: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ save_resource_in_path(current_res,p_file);
+
+ } break;
default: { //save scene?
@@ -1358,6 +1428,67 @@ void EditorNode::push_item(Object *p_object,const String& p_property) {
}
+void EditorNode::_select_history(int p_idx) {
+
+ //push it to the top, it is not correct, but it's more useful
+ ObjectID id=editor_history.get_history_obj(p_idx);
+ Object* obj=ObjectDB::get_instance(id);
+ if (!obj)
+ return;
+ push_item(obj);
+}
+
+void EditorNode::_prepare_history() {
+
+ int history_to = MAX(0,editor_history.get_history_len()-25);
+
+ editor_history_menu->get_popup()->clear();
+
+ Ref<Texture> base_icon = gui_base->get_icon("Object","EditorIcons");
+ Set<ObjectID> already;
+ for(int i=editor_history.get_history_len()-1;i>=history_to;i--) {
+
+
+ ObjectID id=editor_history.get_history_obj(i);
+ Object* obj=ObjectDB::get_instance(id);
+ if (!obj || already.has(id)) {
+ if (history_to>0) {
+ history_to--;
+ }
+ continue;
+ }
+
+ already.insert(id);
+
+ Ref<Texture> icon = gui_base->get_icon("Object","EditorIcons");
+ if (gui_base->has_icon(obj->get_type(),"EditorIcons"))
+ icon=gui_base->get_icon(obj->get_type(),"EditorIcons");
+ else
+ icon=base_icon;
+
+ String text;
+ if (obj->cast_to<Resource>()) {
+ Resource *r=obj->cast_to<Resource>();
+ if (r->get_path().is_resource_file())
+ text=r->get_path().get_file();
+ else if (r->get_name()!=String()) {
+ text=r->get_name();
+ } else {
+ text=r->get_type();
+ }
+ } else if (obj->cast_to<Node>()) {
+ text=obj->cast_to<Node>()->get_name();
+ } else {
+ text=obj->get_type();
+ }
+
+ if (i==editor_history.get_history_pos()) {
+ text="["+text+"]";
+ }
+ editor_history_menu->get_popup()->add_icon_item(icon,text,i);
+ }
+}
+
void EditorNode::_property_editor_forward() {
if (editor_history.next())
@@ -1402,6 +1533,9 @@ void EditorNode::_edit_current() {
uint32_t current = editor_history.get_current();
Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+ property_back->set_disabled( editor_history.is_at_begining() );
+ property_forward->set_disabled( editor_history.is_at_end() );
+
this->current=current_obj;
editor_path->update_path();
@@ -1416,7 +1550,10 @@ void EditorNode::_edit_current() {
object_menu->set_disabled(true);
- if (current_obj->is_type("Resource")) {
+ bool is_resource = current_obj->is_type("Resource");
+ resource_save_button->set_disabled(!is_resource);
+
+ if (is_resource) {
Resource *current_res = current_obj->cast_to<Resource>();
@@ -1425,12 +1562,11 @@ void EditorNode::_edit_current() {
property_editor->edit( current_res );
object_menu->set_disabled(false);
- resources_dock->add_resource(Ref<Resource>(current_res));
- //top_pallete->set_current_tab(1);
- }
+ //resources_dock->add_resource(Ref<Resource>(current_res));
- if (current_obj->is_type("Node")) {
+ //top_pallete->set_current_tab(1);
+ } else if (current_obj->is_type("Node")) {
Node * current_node = current_obj->cast_to<Node>();
ERR_FAIL_COND(!current_node);
@@ -1445,6 +1581,12 @@ void EditorNode::_edit_current() {
//top_pallete->set_current_tab(0);
+ } else {
+
+ property_editor->edit( current_obj );
+ //scene_tree_dock->set_selected(current_node);
+ //object_menu->get_popup()->clear();
+
}
/* Take care of PLUGIN EDITOR */
@@ -1517,7 +1659,13 @@ void EditorNode::_edit_current() {
p->add_item("Copy Params",OBJECT_COPY_PARAMS);
p->add_item("Set Params",OBJECT_PASTE_PARAMS);
p->add_separator();
- p->add_item("Make Resources Unique",OBJECT_UNIQUE_RESOURCES);
+ p->add_item("Paste Resource",RESOURCE_PASTE);
+ if (is_resource) {
+ p->add_item("Copy Resource",RESOURCE_COPY);
+ p->add_item("Make Built-In",RESOURCE_UNREF);
+ }
+ p->add_separator();
+ p->add_item("Make Sub-Resources Unique",OBJECT_UNIQUE_RESOURCES);
p->add_separator();
p->add_icon_item(gui_base->get_icon("Help","EditorIcons"),"Class Reference",OBJECT_REQUEST_HELP);
List<MethodInfo> methods;
@@ -1550,6 +1698,20 @@ void EditorNode::_edit_current() {
_update_keying();
}
+void EditorNode::_resource_created() {
+
+ Object *c = create_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Resource *r = c->cast_to<Resource>();
+ ERR_FAIL_COND(!r);
+
+ REF res( r );
+
+ push_item(c);
+
+}
+
void EditorNode::_resource_selected(const RES& p_res,const String& p_property) {
@@ -1762,6 +1924,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
int idx = editor_data.add_edited_scene(-1);
_scene_tab_changed(idx);
+ editor_data.clear_editor_states();
//_cleanup_scene();
@@ -1804,6 +1967,13 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
quick_open->set_title("Quick Open Script..");
} break;
+ case FILE_QUICK_OPEN_FILE: {
+
+
+ quick_open->popup("Resource",false,true);
+ quick_open->set_title("Quick Search File..");
+
+ } break;
case FILE_RUN_SCRIPT: {
file_script->popup_centered_ratio();
@@ -2266,7 +2436,70 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
#endif
-
+ case RESOURCE_NEW: {
+
+ create_dialog->popup_centered_ratio();
+ } break;
+ case RESOURCE_LOAD: {
+
+ open_resource();
+ } break;
+ case RESOURCE_SAVE: {
+
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ save_resource(current_res);
+
+ } break;
+ case RESOURCE_SAVE_AS: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ save_resource_as(current_res);
+
+ } break;
+ case RESOURCE_UNREF: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+ current_res->set_path("");
+ _edit_current();
+ } break;
+ case RESOURCE_COPY: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ EditorSettings::get_singleton()->set_resource_clipboard(current_res);
+
+ } break;
+ case RESOURCE_PASTE: {
+
+ RES r = EditorSettings::get_singleton()->get_resource_clipboard();
+ if (r.is_valid()) {
+ push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(),String());
+ }
+
+ } break;
case OBJECT_REQUEST_HELP: {
if (current) {
@@ -3050,7 +3283,21 @@ void EditorNode::set_current_scene(int p_idx) {
}
-Error EditorNode::load_scene(const String& p_scene) {
+bool EditorNode::is_scene_open(const String& p_path) {
+
+ for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+ if (editor_data.get_scene_path(i)==p_path)
+ return true;
+ }
+
+ return false;
+}
+
+void EditorNode::fix_dependencies(const String& p_for_file) {
+ dependency_fixer->edit(p_for_file);
+}
+
+Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps) {
if (!is_inside_tree()) {
defer_load_scene = p_scene;
@@ -3096,6 +3343,8 @@ Error EditorNode::load_scene(const String& p_scene) {
//_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
+ dependency_errors.clear();
+
Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true);
if (!sdata.is_valid()) {
@@ -3113,6 +3362,35 @@ Error EditorNode::load_scene(const String& p_scene) {
return ERR_FILE_NOT_FOUND;
}
+ if (!p_ignore_broken_deps && dependency_errors.has(lpath)) {
+
+ current_option=-1;
+ Vector<String> errors;
+ for(Set<String>::Element *E=dependency_errors[lpath].front();E;E=E->next()) {
+
+ errors.push_back(E->get());
+ }
+ dependency_error->show(lpath,errors);
+ opening_prev=false;
+
+ if (prev!=-1) {
+ set_current_scene(prev);
+ editor_data.remove_scene(idx);
+ }
+ return ERR_FILE_MISSING_DEPENDENCIES;
+ }
+
+ dependency_errors.erase(lpath); //at least not self path
+
+ for (Map<String,Set<String> >::Element *E=dependency_errors.front();E;E=E->next()) {
+
+ String txt="Scene '"+E->key()+"' has broken dependencies:\n";
+ for(Set<String>::Element *F=E->get().front();F;F=F->next()) {
+ txt+="\t"+F->get()+"\n";
+ }
+ add_io_error(txt);
+ }
+
sdata->set_path(lpath,true); //take over path
Node*new_scene=sdata->instance(true);
@@ -3408,9 +3686,12 @@ void EditorNode::hide_animation_player_editors() {
void EditorNode::_quick_opened(const String& p_resource) {
- print_line("quick_opened");
- if (quick_open->get_base_type()=="PackedScene") {
+ if (current_option==FILE_QUICK_OPEN_FILE) {
+ scenes_dock->open(p_resource);
+ return;
+ }
+ if (quick_open->get_base_type()=="PackedScene") {
open_request(p_resource);
} else {
load_resource(p_resource);
@@ -3595,6 +3876,8 @@ void EditorNode::_bind_methods() {
ObjectTypeDB::bind_method("_quick_opened",&EditorNode::_quick_opened);
ObjectTypeDB::bind_method("_quick_run",&EditorNode::_quick_run);
+ ObjectTypeDB::bind_method("_resource_created",&EditorNode::_resource_created);
+
ObjectTypeDB::bind_method("_import_action",&EditorNode::_import_action);
//ObjectTypeDB::bind_method("_import",&EditorNode::_import);
// ObjectTypeDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved);
@@ -3624,6 +3907,8 @@ void EditorNode::_bind_methods() {
ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
+ ObjectTypeDB::bind_method("_prepare_history",&EditorNode::_prepare_history);
+ ObjectTypeDB::bind_method("_select_history",&EditorNode::_select_history);
ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
@@ -4105,6 +4390,14 @@ EditorNode::EditorNode() {
EditorHelp::generate_doc(); //before any editor classes are crated
+ if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
+ //only if no touchscreen ui hint, set emulation
+ InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
+ if (id)
+ id->set_emulate_touch(false); //just disable just in case
+ }
+
+
singleton=this;
last_checked_version=0;
changing_scene=false;
@@ -4120,6 +4413,7 @@ EditorNode::EditorNode() {
ResourceLoader::set_abort_on_missing_resources(false);
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
ResourceLoader::set_error_notify_func(this,_load_error_notify);
+ ResourceLoader::set_dependency_error_notify_func(this,_dependency_error_report);
ResourceLoader::set_timestamp_on_load(true);
ResourceSaver::set_timestamp_on_save(true);
@@ -4493,6 +4787,7 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_item("Quick Open Scene..",FILE_QUICK_OPEN_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O);
p->add_item("Quick Open Script..",FILE_QUICK_OPEN_SCRIPT,KEY_MASK_ALT+KEY_MASK_CMD+KEY_O);
+ p->add_item("Quick Search File..",FILE_QUICK_OPEN_FILE,KEY_MASK_ALT+KEY_MASK_CMD+KEY_P);
p->add_separator();
PopupMenu *pm_export = memnew(PopupMenu );
@@ -4735,13 +5030,14 @@ EditorNode::EditorNode() {
scene_tree_dock->set_name("Scene");
//top_pallete->add_child(scene_tree_dock);
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock);
-
+#if 0
resources_dock = memnew( ResourcesDock(this) );
resources_dock->set_name("Resources");
//top_pallete->add_child(resources_dock);
dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(resources_dock);
//top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
+#endif
+ dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
/*Control *editor_spacer = memnew( Control );
editor_spacer->set_custom_minimum_size(Size2(260,200));
editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -4766,27 +5062,40 @@ EditorNode::EditorNode() {
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(prop_editor_base);
HBoxContainer *prop_editor_hb = memnew( HBoxContainer );
- prop_editor_base->add_child(prop_editor_hb);
- editor_path = memnew( EditorPath(&editor_history) );
- editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- prop_editor_hb->add_child(editor_path);
-
- property_editor = memnew( PropertyEditor );
- property_editor->set_autoclear(true);
- property_editor->set_show_categories(true);
- property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- property_editor->hide_top_label();
- prop_editor_base->add_child( property_editor );
- property_editor->set_undo_redo(&editor_data.get_undo_redo());
+ prop_editor_base->add_child(prop_editor_hb);
+ resource_new_button = memnew( ToolButton );
+ resource_new_button->set_tooltip("Create a new resource in memory and edit it");
+ resource_new_button->set_icon(gui_base->get_icon("New","EditorIcons"));
+ prop_editor_hb->add_child(resource_new_button);
+ resource_new_button->connect("pressed",this,"_menu_option",varray(RESOURCE_NEW));
+ resource_new_button->set_focus_mode(Control::FOCUS_NONE);
+
+ resource_load_button = memnew( ToolButton );
+ resource_load_button->set_tooltip("Load an existing resource from disk and edit it");
+ resource_load_button->set_icon(gui_base->get_icon("Load","EditorIcons"));
+ prop_editor_hb->add_child(resource_load_button);
+ resource_load_button->connect("pressed",this,"_menu_option",varray(RESOURCE_LOAD));
+ resource_load_button->set_focus_mode(Control::FOCUS_NONE);
+
+ resource_save_button = memnew( MenuButton );
+ resource_save_button->set_tooltip("Save the currently edited resource");
+ resource_save_button->set_icon(gui_base->get_icon("Save","EditorIcons"));
+ prop_editor_hb->add_child(resource_save_button);
+ resource_save_button->get_popup()->add_item("Save",RESOURCE_SAVE);
+ resource_save_button->get_popup()->add_item("Save As..",RESOURCE_SAVE_AS);
+ resource_save_button->get_popup()->connect("item_pressed",this,"_menu_option");
+ resource_save_button->set_focus_mode(Control::FOCUS_NONE);
+ resource_save_button->set_disabled(true);
+
+ prop_editor_hb->add_spacer();
-
property_back = memnew( ToolButton );
property_back->set_icon( gui_base->get_icon("Back","EditorIcons") );
property_back->set_flat(true);
property_back->set_tooltip("Go to the previous edited object in history.");
+ property_back->set_disabled(true);
prop_editor_hb->add_child( property_back );
@@ -4794,14 +5103,48 @@ EditorNode::EditorNode() {
property_forward->set_icon( gui_base->get_icon("Forward","EditorIcons") );
property_forward->set_flat(true);
property_forward->set_tooltip("Go to the next edited object in history.");
+ property_forward->set_disabled(true);
prop_editor_hb->add_child( property_forward );
+
+ editor_history_menu = memnew( MenuButton );
+ editor_history_menu->set_icon( gui_base->get_icon("History","EditorIcons"));
+ prop_editor_hb->add_child(editor_history_menu);
+ editor_history_menu->connect("about_to_show",this,"_prepare_history");
+ editor_history_menu->get_popup()->connect("item_pressed",this,"_select_history");
+
+
+ prop_editor_hb = memnew( HBoxContainer ); //again...
+
+ prop_editor_base->add_child(prop_editor_hb);
+ editor_path = memnew( EditorPath(&editor_history) );
+ editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ prop_editor_hb->add_child(editor_path);
+
+
object_menu = memnew( MenuButton );
object_menu->set_icon(gui_base->get_icon("Tools","EditorIcons"));
prop_editor_hb->add_child( object_menu );
object_menu->set_tooltip("Object properties.");
+ create_dialog = memnew( CreateDialog );
+ gui_base->add_child(create_dialog);
+ create_dialog->set_base_type("Resource");
+ create_dialog->connect("create",this,"_resource_created");
+
+
+ property_editor = memnew( PropertyEditor );
+ property_editor->set_autoclear(true);
+ property_editor->set_show_categories(true);
+ property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ property_editor->set_use_doc_hints(true);
+
+ property_editor->hide_top_label();
+
+ prop_editor_base->add_child( property_editor );
+ property_editor->set_undo_redo(&editor_data.get_undo_redo());
+
scenes_dock = memnew( ScenesDock(this) );
scenes_dock->set_name("FileSystem");
@@ -4929,7 +5272,11 @@ EditorNode::EditorNode() {
+ dependency_error = memnew( DependencyErrorDialog );
+ gui_base->add_child(dependency_error);
+ dependency_fixer = memnew( DependencyEditor );
+ gui_base->add_child( dependency_fixer );
settings_config_dialog = memnew( EditorSettingsDialog );
gui_base->add_child(settings_config_dialog);
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index d40658a056..dba2b7b86c 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -123,6 +123,7 @@ class EditorNode : public Node {
FILE_OPEN_OLD_SCENE,
FILE_QUICK_OPEN_SCENE,
FILE_QUICK_OPEN_SCRIPT,
+ FILE_QUICK_OPEN_FILE,
FILE_RUN_SCRIPT,
FILE_OPEN_PREV,
FILE_CLOSE,
@@ -137,6 +138,7 @@ class EditorNode : public Node {
RESOURCE_SAVE_AS,
RESOURCE_UNREF,
RESOURCE_COPY,
+ RESOURCE_PASTE,
OBJECT_COPY_PARAMS,
OBJECT_PASTE_PARAMS,
OBJECT_UNIQUE_RESOURCES,
@@ -256,11 +258,13 @@ class EditorNode : public Node {
Button *property_back;
Button *property_forward;
SceneTreeDock *scene_tree_dock;
- ResourcesDock *resources_dock;
+ //ResourcesDock *resources_dock;
PropertyEditor *property_editor;
ScenesDock *scenes_dock;
EditorRunNative *run_native;
+ CreateDialog *create_dialog;
+
CallDialog *call_dialog;
ConfirmationDialog *confirmation;
ConfirmationDialog *import_confirmation;
@@ -298,6 +302,10 @@ class EditorNode : public Node {
HBoxContainer *animation_panel_hb;
VBoxContainer *animation_vb;
EditorPath *editor_path;
+ ToolButton *resource_new_button;
+ ToolButton *resource_load_button;
+ MenuButton *resource_save_button;
+ MenuButton *editor_history_menu;
AnimationKeyEditor *animation_editor;
EditorLog *log;
CenterContainer *tabs_center;
@@ -312,6 +320,9 @@ class EditorNode : public Node {
ProgressDialog *progress_dialog;
BackgroundProgress *progress_hb;
+ DependencyErrorDialog *dependency_error;
+ DependencyEditor *dependency_fixer;
+
TabContainer *dock_slot[DOCK_SLOT_MAX];
Rect2 dock_select_rect[DOCK_SLOT_MAX];
int dock_select_rect_over;
@@ -367,6 +378,7 @@ class EditorNode : public Node {
int current_option;
//void _animation_visibility_toggle();
+ void _resource_created();
void _resource_selected(const RES& p_res,const String& p_property="");
void _menu_option(int p_option);
void _menu_confirm_current();
@@ -375,6 +387,9 @@ class EditorNode : public Node {
void _property_editor_forward();
void _property_editor_back();
+ void _select_history(int p_idx);
+ void _prepare_history();
+
void _fs_changed();
void _sources_changed(bool p_exist);
@@ -451,6 +466,16 @@ class EditorNode : public Node {
void _save_scene_with_preview(String p_file);
+ Map<String,Set<String> > dependency_errors;
+
+ static void _dependency_error_report(void *ud,const String& p_path,const String& p_dep,const String& p_type) {
+ EditorNode*en=(EditorNode*)ud;
+ if (!en->dependency_errors.has(p_path))
+ en->dependency_errors[p_path]=Set<String>();
+ en->dependency_errors[p_path].insert(p_dep+"::"+p_type);
+
+ }
+
struct ExportDefer {
String platform;
String path;
@@ -503,6 +528,8 @@ public:
void edit_node(Node *p_node);
void edit_resource(const Ref<Resource>& p_resource);
void open_resource(const String& p_type="");
+
+ void save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path);
void save_resource(const Ref<Resource>& p_resource);
void save_resource_as(const Ref<Resource>& p_resource);
@@ -534,10 +561,13 @@ public:
Viewport *get_scene_root() { return scene_root; } //root of the scene being edited
Error save_optimized_copy(const String& p_scene,const String& p_preset);
+ void fix_dependencies(const String& p_for_file);
void clear_scene() { _cleanup_scene(); }
- Error load_scene(const String& p_scene);
+ Error load_scene(const String& p_scene,bool p_ignore_broken_deps=false);
Error load_resource(const String& p_scene);
+ bool is_scene_open(const String& p_path);
+
void set_current_version(uint64_t p_version);
void set_current_scene(int p_idx);
diff --git a/tools/editor/editor_path.cpp b/tools/editor/editor_path.cpp
index 86fd79d014..94e2efe346 100644
--- a/tools/editor/editor_path.cpp
+++ b/tools/editor/editor_path.cpp
@@ -73,7 +73,11 @@ void EditorPath::_notification(int p_what) {
if (obj->cast_to<Resource>()) {
Resource *r = obj->cast_to<Resource>();
- name=r->get_name();
+ if (r->get_path().is_resource_file())
+ name=r->get_path().get_file();
+ else
+ name=r->get_name();
+
if (name=="")
name=r->get_type();
} else if (obj->cast_to<Node>()) {
diff --git a/tools/editor/editor_run.cpp b/tools/editor/editor_run.cpp
index 77c5f419b1..4d07463b21 100644
--- a/tools/editor/editor_run.cpp
+++ b/tools/editor/editor_run.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "editor_run.h"
#include "globals.h"
-
+#include "editor_settings.h"
EditorRun::Status EditorRun::get_status() const {
@@ -61,6 +61,70 @@ Error EditorRun::run(const String& p_scene,const String p_custom_args,const List
}
}
+
+ int screen = EditorSettings::get_singleton()->get("game_window_placement/screen");
+
+ if (screen==0) {
+ screen=OS::get_singleton()->get_current_screen();
+ } else {
+ screen--;
+ }
+
+ Rect2 screen_rect;
+ screen_rect.pos=OS::get_singleton()->get_screen_position(screen);
+ screen_rect.size=OS::get_singleton()->get_screen_size(screen);
+
+
+ Size2 desired_size;
+
+ desired_size.x=Globals::get_singleton()->get("display/width");
+ desired_size.y=Globals::get_singleton()->get("display/height");
+
+ Size2 test_size;
+ test_size.x=Globals::get_singleton()->get("display/test_width");
+ test_size.y=Globals::get_singleton()->get("display/test_height");
+ if (test_size.x>0 && test_size.y>0) {
+
+ desired_size=test_size;
+ }
+
+
+ int window_placement=EditorSettings::get_singleton()->get("game_window_placement/rect");
+
+ switch(window_placement) {
+ case 0: { // default
+
+ args.push_back("-p");
+ args.push_back(itos(screen_rect.pos.x)+"x"+itos(screen_rect.pos.y));
+ } break;
+ case 1: { // centered
+ Vector2 pos=screen_rect.pos+((screen_rect.size-desired_size)/2).floor();
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ } break;
+ case 2: { // custom pos
+ Vector2 pos = EditorSettings::get_singleton()->get("game_window_placement/rect_custom_position");
+ pos+=screen_rect.pos;
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ } break;
+ case 3: { // force maximized
+ Vector2 pos=screen_rect.pos;
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ args.push_back("-mx");
+
+ } break;
+ case 4: { // force fullscreen
+
+ Vector2 pos=screen_rect.pos;
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ args.push_back("-f");
+ } break;
+ }
+
+
if (p_breakpoints.size()) {
args.push_back("-bp");
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 2f61d4f09d..a771893bdd 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -496,6 +496,15 @@ void EditorSettings::_load_defaults() {
set("2d_editor/bone_selected_color",Color(0.9,0.45,0.45,0.9));
set("2d_editor/bone_ik_color",Color(0.9,0.9,0.45,0.9));
+ set("game_window_placement/rect",0);
+ hints["game_window_placement/rect"]=PropertyInfo(Variant::INT,"game_window_placement/rect",PROPERTY_HINT_ENUM,"Default,Centered,Custom Position,Force Maximized,Force Full Screen");
+ String screen_hints="Default (Same as Editor)";
+ for(int i=0;i<OS::get_singleton()->get_screen_count();i++) {
+ screen_hints+=",Monitor "+itos(i+1);
+ }
+ set("game_window_placement/rect_custom_position",Vector2());
+ set("game_window_placement/screen",0);
+ hints["game_window_placement/screen"]=PropertyInfo(Variant::INT,"game_window_placement/screen",PROPERTY_HINT_ENUM,screen_hints);
set("on_save/compress_binary_resources",true);
set("on_save/save_modified_external_resources",true);
diff --git a/tools/editor/icons/icon_anchor.png b/tools/editor/icons/icon_anchor.png
new file mode 100644
index 0000000000..1f9f9fa139
--- /dev/null
+++ b/tools/editor/icons/icon_anchor.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_center.png b/tools/editor/icons/icon_control_align_bottom_center.png
new file mode 100644
index 0000000000..5ce9fe5c1c
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_bottom_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_left.png b/tools/editor/icons/icon_control_align_bottom_left.png
new file mode 100644
index 0000000000..6c5129bf95
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_bottom_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_right.png b/tools/editor/icons/icon_control_align_bottom_right.png
new file mode 100644
index 0000000000..8857f4e940
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_bottom_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_wide.png b/tools/editor/icons/icon_control_align_bottom_wide.png
new file mode 100644
index 0000000000..56f009b8e4
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_bottom_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_center.png b/tools/editor/icons/icon_control_align_center.png
new file mode 100644
index 0000000000..acd42525fa
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_center_left.png b/tools/editor/icons/icon_control_align_center_left.png
new file mode 100644
index 0000000000..997074b097
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_center_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_center_right.png b/tools/editor/icons/icon_control_align_center_right.png
new file mode 100644
index 0000000000..b5cae63f7a
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_center_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_left_center.png b/tools/editor/icons/icon_control_align_left_center.png
new file mode 100644
index 0000000000..7bb4dfb567
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_left_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_left_wide.png b/tools/editor/icons/icon_control_align_left_wide.png
new file mode 100644
index 0000000000..1b0a6cff95
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_left_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_right_center.png b/tools/editor/icons/icon_control_align_right_center.png
new file mode 100644
index 0000000000..cf12d44c6a
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_right_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_right_wide.png b/tools/editor/icons/icon_control_align_right_wide.png
new file mode 100644
index 0000000000..406ed25aed
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_right_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_center.png b/tools/editor/icons/icon_control_align_top_center.png
new file mode 100644
index 0000000000..da7ede984a
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_top_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_left.png b/tools/editor/icons/icon_control_align_top_left.png
new file mode 100644
index 0000000000..84a224fbbe
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_top_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_right.png b/tools/editor/icons/icon_control_align_top_right.png
new file mode 100644
index 0000000000..3b58eead9c
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_top_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_wide.png b/tools/editor/icons/icon_control_align_top_wide.png
new file mode 100644
index 0000000000..869ae26134
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_top_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_wide.png b/tools/editor/icons/icon_control_align_wide.png
new file mode 100644
index 0000000000..57a2933b25
--- /dev/null
+++ b/tools/editor/icons/icon_control_align_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_hcenter_wide.png b/tools/editor/icons/icon_control_hcenter_wide.png
new file mode 100644
index 0000000000..739ea5baeb
--- /dev/null
+++ b/tools/editor/icons/icon_control_hcenter_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_vcenter_wide.png b/tools/editor/icons/icon_control_vcenter_wide.png
new file mode 100644
index 0000000000..44cbb8f344
--- /dev/null
+++ b/tools/editor/icons/icon_control_vcenter_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_list.png b/tools/editor/icons/icon_file_list.png
index e5e9213e61..ab790a85a5 100644
--- a/tools/editor/icons/icon_file_list.png
+++ b/tools/editor/icons/icon_file_list.png
Binary files differ
diff --git a/tools/editor/icons/icon_filesystem.png b/tools/editor/icons/icon_filesystem.png
new file mode 100644
index 0000000000..6841f9a792
--- /dev/null
+++ b/tools/editor/icons/icon_filesystem.png
Binary files differ
diff --git a/tools/editor/icons/icon_history.png b/tools/editor/icons/icon_history.png
new file mode 100644
index 0000000000..5c306c3ac9
--- /dev/null
+++ b/tools/editor/icons/icon_history.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_node_edit.png b/tools/editor/icons/icon_multi_node_edit.png
new file mode 100644
index 0000000000..357c062cbd
--- /dev/null
+++ b/tools/editor/icons/icon_multi_node_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_non_favorite.png b/tools/editor/icons/icon_non_favorite.png
new file mode 100644
index 0000000000..edd806fbe8
--- /dev/null
+++ b/tools/editor/icons/icon_non_favorite.png
Binary files differ
diff --git a/tools/editor/icons/icon_patch_9_frame.png b/tools/editor/icons/icon_patch_9_frame.png
new file mode 100644
index 0000000000..c8f38fa61a
--- /dev/null
+++ b/tools/editor/icons/icon_patch_9_frame.png
Binary files differ
diff --git a/tools/editor/inspector_dock.cpp b/tools/editor/inspector_dock.cpp
new file mode 100644
index 0000000000..57d19c3ec8
--- /dev/null
+++ b/tools/editor/inspector_dock.cpp
@@ -0,0 +1,22 @@
+#include "inspector_dock.h"
+
+#if 0
+void InspectorDock::_go_next() {
+
+
+}
+
+void InspectorDock::_go_prev() {
+
+
+}
+
+void InspectorDock::_bind_methods() {
+
+}
+
+InspectorDock::InspectorDock() {
+
+
+}
+#endif
diff --git a/tools/editor/inspector_dock.h b/tools/editor/inspector_dock.h
new file mode 100644
index 0000000000..90f043aba8
--- /dev/null
+++ b/tools/editor/inspector_dock.h
@@ -0,0 +1,35 @@
+#ifndef INSPECTOR_DOCK_H
+#define INSPECTOR_DOCK_H
+
+#include "scene/gui/box_container.h"
+#include "property_editor.h"
+
+
+//this is for now bundled in EditorNode, will be moved away here eventually
+
+#if 0
+class InspectorDock : public VBoxContainer
+{
+ OBJ_TYPE(InspectorDock,VBoxContainer);
+
+ PropertyEditor *property_editor;
+
+ EditorHistory editor_history;
+
+ void _go_next();
+ void _go_prev();
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ EditorHistory &get_editor_history();
+
+ PropertyEditor *get_property_editor();
+
+ InspectorDock();
+};
+
+#endif
+#endif // INSPECTOR_DOCK_H
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index d510333a32..d57cff850e 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -710,10 +710,126 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
//find largest source..
+ /************************/
+ /* ADD WEIGHTS IF EXIST */
+ /************************/
+
+ Map<int,Vector<Collada::Vertex::Weight> > pre_weights;
+
+ bool has_weights=false;
+
+ if (skin_controller) {
+
+ const Collada::SkinControllerData::Source *weight_src=NULL;
+ int weight_ofs=0;
+
+ if (skin_controller->weights.sources.has("WEIGHT")) {
+
+ String weight_id = skin_controller->weights.sources["WEIGHT"].source;
+ weight_ofs = skin_controller->weights.sources["WEIGHT"].offset;
+ if (skin_controller->sources.has(weight_id)) {
+
+ weight_src = &skin_controller->sources[weight_id];
+
+ }
+ }
+
+ int joint_ofs=0;
+
+ if (skin_controller->weights.sources.has("JOINT")) {
+
+ joint_ofs = skin_controller->weights.sources["JOINT"].offset;
+ }
+
+ //should be OK, given this was pre-checked.
+
+ int index_ofs=0;
+ int wstride = skin_controller->weights.sources.size();
+ for(int w_i=0;w_i<skin_controller->weights.sets.size();w_i++) {
+
+ int amount = skin_controller->weights.sets[w_i];
+
+ Vector<Collada::Vertex::Weight> weights;
+
+ for (int a_i=0;a_i<amount;a_i++) {
+
+ Collada::Vertex::Weight w;
+
+ int read_from = index_ofs+a_i*wstride;
+ ERR_FAIL_INDEX_V(read_from+wstride-1,skin_controller->weights.indices.size(),ERR_INVALID_DATA);
+ int weight_index = skin_controller->weights.indices[read_from+weight_ofs];
+ ERR_FAIL_INDEX_V(weight_index,weight_src->array.size(),ERR_INVALID_DATA);
+
+ w.weight = weight_src->array[weight_index];
+
+ int bone_index = skin_controller->weights.indices[read_from+joint_ofs];
+ if (bone_index==-1)
+ continue; //ignore this weight (refers to bind shape)
+ ERR_FAIL_INDEX_V(bone_index,bone_remap.size(),ERR_INVALID_DATA);
+
+ w.bone_idx=bone_remap[bone_index];
+
+
+ weights.push_back(w);
+ }
+
+ /* FIX WEIGHTS */
+
+
+
+ weights.sort();
+
+ if (weights.size()>4) {
+ //cap to 4 and make weights add up 1
+ weights.resize(4);
+
+ }
+
+ //make sure weights allways add up to 1
+ float total=0;
+ for(int i=0;i<weights.size();i++)
+ total+=weights[i].weight;
+ if (total)
+ for(int i=0;i<weights.size();i++)
+ weights[i].weight/=total;
+
+ if (weights.size()==0 || total==0) { //if nothing, add a weight to bone 0
+ //no weights assigned
+ Collada::Vertex::Weight w;
+ w.bone_idx=0;
+ w.weight=1.0;
+ weights.clear();
+ weights.push_back(w);
+
+ }
+
+ pre_weights[w_i]=weights;
+
+ /*
+ for(Set<int>::Element *E=vertex_map[w_i].front();E;E=E->next()) {
+
+ int dst = E->get();
+ ERR_EXPLAIN("invalid vertex index in array");
+ ERR_FAIL_INDEX_V(dst,vertex_array.size(),ERR_INVALID_DATA);
+ vertex_array[dst].weights=weights;
+
+ }*/
+
+
+
+
+ index_ofs+=wstride*amount;
+
+ }
+
+ //vertices need to be localized
+ has_weights=true;
+
+ }
Set<Collada::Vertex> vertex_set; //vertex set will be the vertices
List<int> indices_list; //indices will be the indices
- Map<int,Set<int> > vertex_map; //map vertices (for setting skinning/morph)
+ //Map<int,Set<int> > vertex_map; //map vertices (for setting skinning/morph)
/**************************/
/* CREATE PRIMITIVE ARRAY */
@@ -753,11 +869,16 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
if (!p_optimize)
vertex.uid=vertidx++;
+
+
int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers)
int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index;
ERR_FAIL_INDEX_V(vertex_pos,vertex_src->array.size(),ERR_INVALID_DATA);
vertex.vertex=Vector3(vertex_src->array[vertex_pos+0],vertex_src->array[vertex_pos+1],vertex_src->array[vertex_pos+2]);
+ if (pre_weights.has(vertex_index)) {
+ vertex.weights=pre_weights[vertex_index];
+ }
if (normal_src) {
@@ -836,9 +957,9 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
vertex_set.insert(vertex);
}
- if (!vertex_map.has(vertex_index))
+ /* if (!vertex_map.has(vertex_index))
vertex_map[vertex_index]=Set<int>();
- vertex_map[vertex_index].insert(index); //should be outside..
+ vertex_map[vertex_index].insert(index); //should be outside..*/
//build triangles if needed
if (j==0)
prev2[0]=index;
@@ -874,120 +995,10 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
vertex_array[F->get().idx]=F->get();
}
- /************************/
- /* ADD WEIGHTS IF EXIST */
- /************************/
-
-
- bool has_weights=false;
-
- if (skin_controller) {
-
- const Collada::SkinControllerData::Source *weight_src=NULL;
- int weight_ofs=0;
-
- if (skin_controller->weights.sources.has("WEIGHT")) {
-
- String weight_id = skin_controller->weights.sources["WEIGHT"].source;
- weight_ofs = skin_controller->weights.sources["WEIGHT"].offset;
- if (skin_controller->sources.has(weight_id)) {
-
- weight_src = &skin_controller->sources[weight_id];
-
- }
- }
-
- int joint_ofs=0;
-
- if (skin_controller->weights.sources.has("JOINT")) {
-
- joint_ofs = skin_controller->weights.sources["JOINT"].offset;
- }
-
- //should be OK, given this was pre-checked.
-
- int index_ofs=0;
- int wstride = skin_controller->weights.sources.size();
- for(int w_i=0;w_i<skin_controller->weights.sets.size();w_i++) {
-
- int amount = skin_controller->weights.sets[w_i];
-
- if (vertex_map.has(w_i)) { //vertex may no longer be here, don't bother converting
- Vector<Collada::Vertex::Weight> weights;
-
- for (int a_i=0;a_i<amount;a_i++) {
-
- Collada::Vertex::Weight w;
-
- int read_from = index_ofs+a_i*wstride;
- ERR_FAIL_INDEX_V(read_from+wstride-1,skin_controller->weights.indices.size(),ERR_INVALID_DATA);
- int weight_index = skin_controller->weights.indices[read_from+weight_ofs];
- ERR_FAIL_INDEX_V(weight_index,weight_src->array.size(),ERR_INVALID_DATA);
-
- w.weight = weight_src->array[weight_index];
-
- int bone_index = skin_controller->weights.indices[read_from+joint_ofs];
- if (bone_index==-1)
- continue; //ignore this weight (refers to bind shape)
- ERR_FAIL_INDEX_V(bone_index,bone_remap.size(),ERR_INVALID_DATA);
-
- w.bone_idx=bone_remap[bone_index];
-
-
- weights.push_back(w);
- }
-
- /* FIX WEIGHTS */
-
-
-
- weights.sort();
-
- if (weights.size()>4) {
- //cap to 4 and make weights add up 1
- weights.resize(4);
-
- }
-
- //make sure weights allways add up to 1
- float total=0;
- for(int i=0;i<weights.size();i++)
- total+=weights[i].weight;
- if (total)
- for(int i=0;i<weights.size();i++)
- weights[i].weight/=total;
-
- if (weights.size()==0 || total==0) { //if nothing, add a weight to bone 0
- //no weights assigned
- Collada::Vertex::Weight w;
- w.bone_idx=0;
- w.weight=1.0;
- weights.clear();
- weights.push_back(w);
-
- }
-
-
- for(Set<int>::Element *E=vertex_map[w_i].front();E;E=E->next()) {
-
- int dst = E->get();
- ERR_EXPLAIN("invalid vertex index in array");
- ERR_FAIL_INDEX_V(dst,vertex_array.size(),ERR_INVALID_DATA);
- vertex_array[dst].weights=weights;
-
- }
-
- } else {
- //zzprint_line("no vertex found for index "+itos(w_i));
- }
-
- index_ofs+=wstride*amount;
-
- }
-
- //vertices need to be localized
+ if (has_weights) {
+ //if skeleton, localize
Transform local_xform = p_local_xform;
for(int i=0;i<vertex_array.size();i++) {
@@ -1000,11 +1011,9 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
//vertex_array[i].tangent.normal*=-1.0;
}
}
-
- has_weights=true;
-
}
+
DVector<int> index_array;
index_array.resize(indices_list.size());
DVector<int>::Write index_arrayw = index_array.write();
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
index 4f7ec1839a..436725f6fb 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
@@ -1068,12 +1068,14 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
//prepare atlas!
Vector< Image > sources;
+ Vector< Image > tsources;
bool alpha=false;
bool crop = from->get_option("crop");
EditorProgress ep("make_atlas","Build Atlas For: "+p_path.get_file(),from->get_source_count()+3);
print_line("sources: "+itos(from->get_source_count()));
+
for(int i=0;i<from->get_source_count();i++) {
String path = EditorImportPlugin::expand_source_path(from->get_source_path(i));
@@ -1091,17 +1093,57 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
if (src.detect_alpha())
alpha=true;
- sources.push_back(src);
+ tsources.push_back(src);
}
ep.step("Converting Images",sources.size());
- for(int i=0;i<sources.size();i++) {
+ int base_index=0;
+
+
+ Map<uint64_t,int> source_md5;
+ Map<int,List<int> > source_map;
+
+ for(int i=0;i<tsources.size();i++) {
+
+ Image src = tsources[i];
if (alpha) {
- sources[i].convert(Image::FORMAT_RGBA);
+ src.convert(Image::FORMAT_RGBA);
+ } else {
+ src.convert(Image::FORMAT_RGB);
+ }
+
+ DVector<uint8_t> data = src.get_data();
+ MD5_CTX md5;
+ DVector<uint8_t>::Read r=data.read();
+ MD5Init(&md5);
+ int len=data.size();
+ for(int j=0;j<len;j++) {
+ uint8_t b = r[j];
+ b>>=2; //to aid in comparing
+ MD5Update(&md5,(unsigned char*)&b,1);
+ }
+ MD5Final(&md5);
+ uint64_t *cmp = (uint64_t*)md5.digest; //less bits, but still useful for this
+
+ tsources[i]=Image(); //clear
+
+ if (source_md5.has(*cmp)) {
+ int sidx=source_md5[*cmp];
+ source_map[sidx].push_back(i);
+ print_line("REUSING "+from->get_source_path(i));
+
} else {
- sources[i].convert(Image::FORMAT_RGB);
+ int sidx=sources.size();
+ source_md5[*cmp]=sidx;
+ sources.push_back(src);
+ List<int> sm;
+ sm.push_back(i);
+ source_map[sidx]=sm;
+
}
+
+
}
//texturepacker is not really good for optimizing, so..
@@ -1141,28 +1183,44 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
Image atlas;
atlas.create(nearest_power_of_2(dst_size.width),nearest_power_of_2(dst_size.height),0,alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB);
+
+ atlases.resize(from->get_source_count());
+
for(int i=0;i<sources.size();i++) {
int x=dst_positions[i].x;
int y=dst_positions[i].y;
- Ref<AtlasTexture> at = memnew( AtlasTexture );
Size2 sz = Size2(sources[i].get_width(),sources[i].get_height());
+
+ Rect2 region;
+ Rect2 margin;
+
if (crop && sz!=crops[i].size) {
Rect2 rect = crops[i];
rect.size=sz-rect.size;
- at->set_region(Rect2(x+border,y+border,crops[i].size.width,crops[i].size.height));
- at->set_margin(rect);
+ region=Rect2(x+border,y+border,crops[i].size.width,crops[i].size.height);
+ margin=rect;
atlas.blit_rect(sources[i],crops[i],Point2(x+border,y+border));
} else {
- at->set_region(Rect2(x+border,y+border,sz.x,sz.y));
+ region=Rect2(x+border,y+border,sz.x,sz.y);
atlas.blit_rect(sources[i],Rect2(0,0,sources[i].get_width(),sources[i].get_height()),Point2(x+border,y+border));
}
- String apath = p_path.get_base_dir().plus_file(from->get_source_path(i).get_file().basename()+".atex");
- print_line("Atlas Tex: "+apath);
- at->set_path(apath);
- atlases.push_back(at);
+ ERR_CONTINUE( !source_map.has(i) );
+ for (List<int>::Element *E=source_map[i].front();E;E=E->next()) {
+
+ Ref<AtlasTexture> at = memnew( AtlasTexture );
+
+
+ at->set_region(region);
+ at->set_margin(margin);
+ String apath = p_path.get_base_dir().plus_file(from->get_source_path(E->get()).get_file().basename()+".atex");
+ at->set_path(apath);
+ atlases[E->get()]=at;
+ print_line("Atlas Tex: "+apath);
+
+ }
}
if (ResourceCache::has(p_path)) {
texture = Ref<ImageTexture> ( ResourceCache::get(p_path)->cast_to<ImageTexture>() );
@@ -1414,6 +1472,9 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c
case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
} break; //use default
+ case EditorImportExport::IMAGE_ACTION_KEEP: {
+ return Vector<uint8_t>();
+ } break; //use default
}
diff --git a/tools/editor/multi_node_edit.cpp b/tools/editor/multi_node_edit.cpp
new file mode 100644
index 0000000000..cfa998bee9
--- /dev/null
+++ b/tools/editor/multi_node_edit.cpp
@@ -0,0 +1,118 @@
+#include "multi_node_edit.h"
+#include "editor_node.h"
+
+bool MultiNodeEdit::_set(const StringName& p_name, const Variant& p_value){
+
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (!es)
+ return false;
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action("MultiNode Set "+String(p_name));
+ for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
+
+ if (!es->has_node(E->get()))
+ continue;
+
+ Node*n=es->get_node(E->get());
+ if (!n)
+ continue;
+
+ ur->add_do_property(n,p_name,p_value);
+ ur->add_undo_property(n,p_name,n->get(p_name));
+
+ }
+
+ ur->commit_action();
+ return true;
+}
+
+bool MultiNodeEdit::_get(const StringName& p_name,Variant &r_ret) const {
+
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (!es)
+ return false;
+
+ for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
+
+ if (!es->has_node(E->get()))
+ continue;
+
+ const Node*n=es->get_node(E->get());
+ if (!n)
+ continue;
+
+ bool found;
+ r_ret=n->get(p_name,&found);
+ if (found)
+ return true;
+
+ }
+
+ return false;
+}
+
+void MultiNodeEdit::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ HashMap<String,PLData> usage;
+
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (!es)
+ return;
+
+ int nc=0;
+
+ List<PLData*> datas;
+
+ for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
+
+ if (!es->has_node(E->get()))
+ continue;
+
+ Node*n=es->get_node(E->get());
+ if (!n)
+ continue;
+
+ List<PropertyInfo> plist;
+ n->get_property_list(&plist,true);
+
+ for(List<PropertyInfo>::Element *F=plist.front();F;F=F->next()) {
+
+ if (!usage.has(F->get().name)) {
+ PLData pld;
+ pld.uses=0;
+ pld.info=F->get();
+ usage[F->get().name]=pld;
+ datas.push_back(usage.getptr(F->get().name));
+ }
+
+ usage[F->get().name].uses++;
+ }
+
+ nc++;
+ }
+
+ for (List<PLData*>::Element *E=datas.front();E;E=E->next()) {
+
+ if (nc==E->get()->uses) {
+ p_list->push_back(E->get()->info);
+ }
+ }
+
+
+}
+
+void MultiNodeEdit::clear_nodes() {
+
+ nodes.clear();
+}
+
+void MultiNodeEdit::add_node(const NodePath& p_node){
+
+ nodes.push_back(p_node);
+}
+
+MultiNodeEdit::MultiNodeEdit()
+{
+}
diff --git a/tools/editor/multi_node_edit.h b/tools/editor/multi_node_edit.h
new file mode 100644
index 0000000000..5a0cabf4be
--- /dev/null
+++ b/tools/editor/multi_node_edit.h
@@ -0,0 +1,32 @@
+#ifndef MULTI_NODE_EDIT_H
+#define MULTI_NODE_EDIT_H
+
+#include "scene/main/node.h"
+
+class MultiNodeEdit : public Reference {
+
+ OBJ_TYPE(MultiNodeEdit,Reference);
+
+ List<NodePath> nodes;
+ struct PLData {
+ int uses;
+ PropertyInfo info;
+ };
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+
+
+ void clear_nodes();
+ void add_node(const NodePath& p_node);
+
+ MultiNodeEdit();
+};
+
+#endif // MULTI_NODE_EDIT_H
diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp
index 05b12543d2..f8c484e886 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.cpp
+++ b/tools/editor/plugins/animation_player_editor_plugin.cpp
@@ -549,6 +549,49 @@ void AnimationPlayerEditor::ensure_visibility() {
_animation_edit();
}
+Dictionary AnimationPlayerEditor::get_state() const {
+
+ Dictionary d;
+
+ d["visible"]=is_visible();
+ if (is_visible() && player) {
+ d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
+ d["animation"]=player->get_current_animation();
+ d["editing"]=edit_anim->is_pressed();
+ }
+
+ return d;
+
+}
+void AnimationPlayerEditor::set_state(const Dictionary& p_state) {
+
+ if (p_state.has("visible") && p_state["visible"]) {
+
+ Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]);
+ if (n && n->cast_to<AnimationPlayer>()) {
+ player=n->cast_to<AnimationPlayer>();
+ _update_player();
+ show();
+ set_process(true);
+ ensure_visibility();
+ EditorNode::get_singleton()->animation_panel_make_visible(true);
+
+ if (p_state.has("animation")) {
+ String anim = p_state["animation"];
+ _select_anim_by_name(anim);
+ if (p_state.has("editing") && p_state["editing"]) {
+
+ edit_anim->set_pressed(true);
+ _animation_edit();
+ }
+ }
+
+ }
+ }
+
+}
+
+
void AnimationPlayerEditor::_animation_resource_edit() {
if (animation->get_item_count()) {
@@ -1350,6 +1393,7 @@ AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) {
editor=p_node;
anim_editor = memnew( AnimationPlayerEditor(editor) );
+ anim_editor->set_undo_redo(editor->get_undo_redo());
editor->get_animation_panel()->add_child(anim_editor);
/*
editor->get_viewport()->add_child(anim_editor);
diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h
index 9f0413088d..5705742565 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.h
+++ b/tools/editor/plugins/animation_player_editor_plugin.h
@@ -151,6 +151,10 @@ protected:
static void _bind_methods();
public:
+ Dictionary get_state() const;
+ void set_state(const Dictionary& p_state);
+
+
void ensure_visibility();
void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
@@ -167,6 +171,9 @@ class AnimationPlayerEditorPlugin : public EditorPlugin {
public:
+ virtual Dictionary get_state() const { return anim_editor->get_state(); }
+ virtual void set_state(const Dictionary& p_state) { anim_editor->set_state(p_state); }
+
virtual String get_name() const { return "Anim"; }
bool has_main_screen() const { return false; }
virtual void edit(Object *p_node);
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index f2738f0a62..8fc2945450 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1910,12 +1910,20 @@ void CanvasItemEditor::_notification(int p_what) {
List<Node*> &selection = editor_selection->get_selected_node_list();
+ bool all_control=true;
+ bool has_control=false;
+
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item || !canvas_item->is_visible())
continue;
+ if (canvas_item->cast_to<Control>())
+ has_control=true;
+ else
+ all_control=false;
+
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
continue;
@@ -1932,6 +1940,13 @@ void CanvasItemEditor::_notification(int p_what) {
}
+ bool show_anchor = all_control && has_control;
+ if (show_anchor != !anchor_menu->is_hidden()) {
+ if (show_anchor)
+ anchor_menu->show();
+ else
+ anchor_menu->hide();
+ }
for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
@@ -1974,6 +1989,32 @@ void CanvasItemEditor::_notification(int p_what) {
ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
key_insert_button->set_icon(get_icon("Key","EditorIcons"));
+
+ //anchor_menu->add_icon_override("Align Top Left");
+ anchor_menu->set_icon(get_icon("Anchor","EditorIcons"));
+ PopupMenu *p=anchor_menu->get_popup();
+
+ p->add_icon_item(get_icon("ControlAlignTopLeft","EditorIcons"),"Top Left",ANCHOR_ALIGN_TOP_LEFT);
+ p->add_icon_item(get_icon("ControlAlignTopRight","EditorIcons"),"Top Right",ANCHOR_ALIGN_TOP_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomRight","EditorIcons"),"Bottom Right",ANCHOR_ALIGN_BOTTOM_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomLeft","EditorIcons"),"Bottom Left",ANCHOR_ALIGN_BOTTOM_LEFT);
+ p->add_separator();
+ p->add_icon_item(get_icon("ControlAlignLeftCenter","EditorIcons"),"Center Left",ANCHOR_ALIGN_CENTER_LEFT);
+ p->add_icon_item(get_icon("ControlAlignTopCenter","EditorIcons"),"Center Top",ANCHOR_ALIGN_CENTER_TOP);
+ p->add_icon_item(get_icon("ControlAlignRightCenter","EditorIcons"),"Center Right",ANCHOR_ALIGN_CENTER_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomCenter","EditorIcons"),"Center Bottom",ANCHOR_ALIGN_CENTER_BOTTOM);
+ p->add_icon_item(get_icon("ControlAlignCenter","EditorIcons"),"Center",ANCHOR_ALIGN_CENTER);
+ p->add_separator();
+ p->add_icon_item(get_icon("ControlAlignLeftWide","EditorIcons"),"Left Wide",ANCHOR_ALIGN_LEFT_WIDE);
+ p->add_icon_item(get_icon("ControlAlignTopWide","EditorIcons"),"Top Wide",ANCHOR_ALIGN_TOP_WIDE);
+ p->add_icon_item(get_icon("ControlAlignRightWide","EditorIcons"),"Right Wide",ANCHOR_ALIGN_RIGHT_WIDE);
+ p->add_icon_item(get_icon("ControlAlignBottomWide","EditorIcons"),"Bottom Wide",ANCHOR_ALIGN_BOTTOM_WIDE);
+ p->add_icon_item(get_icon("ControlVcenterWide","EditorIcons"),"VCenter Wide ",ANCHOR_ALIGN_VCENTER_WIDE);
+ p->add_icon_item(get_icon("ControlHcenterWide","EditorIcons"),"HCenter Wide ",ANCHOR_ALIGN_HCENTER_WIDE);
+ p->add_separator();
+ p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE);
+
+
}
if (p_what==NOTIFICATION_READY) {
@@ -2179,6 +2220,27 @@ void CanvasItemEditor::_update_scroll(float) {
}
+void CanvasItemEditor::_set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom) {
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ undo_redo->create_action("Change Anchors");
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Control *c = E->get()->cast_to<Control>();
+
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_LEFT,p_left);
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_TOP,p_top);
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_RIGHT,p_right);
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_BOTTOM,p_bottom);
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_LEFT,c->get_anchor(MARGIN_LEFT));
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_TOP,c->get_anchor(MARGIN_TOP));
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_RIGHT,c->get_anchor(MARGIN_RIGHT));
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_BOTTOM,c->get_anchor(MARGIN_BOTTOM));
+ }
+
+ undo_redo->commit_action();
+
+}
void CanvasItemEditor::_popup_callback(int p_op) {
@@ -2381,6 +2443,56 @@ void CanvasItemEditor::_popup_callback(int p_op) {
case SPACE_VERTICAL: {
//space_selected_items< proj_vector2_y, compare_items_y >();
} break;
+ case ANCHOR_ALIGN_TOP_LEFT: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_TOP_RIGHT: {
+ _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_BOTTOM_LEFT: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_BOTTOM_RIGHT: {
+ _set_anchor(ANCHOR_END,ANCHOR_END,ANCHOR_END,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_CENTER_LEFT: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_CENTER_RIGHT: {
+
+ _set_anchor(ANCHOR_END,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_CENTER_TOP: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_CENTER_BOTTOM: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_CENTER: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_TOP_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_LEFT_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_RIGHT_WIDE: {
+ _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_BOTTOM_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_VCENTER_WIDE: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_HCENTER_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
+ } break;
+
case ANIM_INSERT_KEY:
case ANIM_INSERT_KEY_EXISTING: {
@@ -2999,6 +3111,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_item("Center Selection", VIEW_CENTER_TO_SELECTION, KEY_F);
p->add_item("Frame Selection", VIEW_FRAME_TO_SELECTION, KEY_MASK_CMD|KEY_F);
+ anchor_menu = memnew( MenuButton );
+ anchor_menu->set_text("Anchor");
+ hb->add_child(anchor_menu);
+ anchor_menu->get_popup()->connect("item_pressed", this,"_popup_callback");
+ anchor_menu->hide();
+
+ //p = anchor_menu->get_popup();
+
animation_hb = memnew( HBoxContainer );
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h
index 48a34e2d07..485422028e 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.h
+++ b/tools/editor/plugins/canvas_item_editor_plugin.h
@@ -90,6 +90,23 @@ class CanvasItemEditor : public VBoxContainer {
UNGROUP_SELECTED,
ALIGN_HORIZONTAL,
ALIGN_VERTICAL,
+ ANCHOR_ALIGN_TOP_LEFT,
+ ANCHOR_ALIGN_TOP_RIGHT,
+ ANCHOR_ALIGN_BOTTOM_LEFT,
+ ANCHOR_ALIGN_BOTTOM_RIGHT,
+ ANCHOR_ALIGN_CENTER_LEFT,
+ ANCHOR_ALIGN_CENTER_RIGHT,
+ ANCHOR_ALIGN_CENTER_TOP,
+ ANCHOR_ALIGN_CENTER_BOTTOM,
+ ANCHOR_ALIGN_CENTER,
+ ANCHOR_ALIGN_TOP_WIDE,
+ ANCHOR_ALIGN_LEFT_WIDE,
+ ANCHOR_ALIGN_RIGHT_WIDE,
+ ANCHOR_ALIGN_BOTTOM_WIDE,
+ ANCHOR_ALIGN_VCENTER_WIDE,
+ ANCHOR_ALIGN_HCENTER_WIDE,
+ ANCHOR_ALIGN_WIDE,
+
SPACE_HORIZONTAL,
SPACE_VERTICAL,
EXPAND_TO_PARENT,
@@ -225,6 +242,7 @@ class CanvasItemEditor : public VBoxContainer {
MenuButton *view_menu;
HBoxContainer *animation_hb;
MenuButton *animation_menu;
+ MenuButton *anchor_menu;
Button *key_loc_button;
Button *key_rot_button;
@@ -305,6 +323,8 @@ class CanvasItemEditor : public VBoxContainer {
void _viewport_input_event(const InputEvent& p_event);
void _viewport_draw();
+ void _set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom);
+
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
index 2c64b2eb6b..13d4c8db5a 100644
--- a/tools/editor/plugins/mesh_editor_plugin.cpp
+++ b/tools/editor/plugins/mesh_editor_plugin.cpp
@@ -216,6 +216,8 @@ MeshInstanceEditor::MeshInstanceEditor() {
SpatialEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text("Mesh");
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshInstance","EditorIcons"));
+
options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY);
options->get_popup()->add_separator();
diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/tools/editor/plugins/multimesh_editor_plugin.cpp
index 0df906117e..3c88b1d3a8 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.cpp
+++ b/tools/editor/plugins/multimesh_editor_plugin.cpp
@@ -330,6 +330,8 @@ MultiMeshEditor::MultiMeshEditor() {
options->set_area_as_parent_rect();
options->set_text("MultiMesh");
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MultiMeshInstance","EditorIcons"));
+
options->get_popup()->add_item("Populate Surface");
options->get_popup()->connect("item_pressed", this,"_menu_option");
diff --git a/tools/editor/plugins/particles_2d_editor_plugin.cpp b/tools/editor/plugins/particles_2d_editor_plugin.cpp
index fdf534a3a8..dadfa8bfdc 100644
--- a/tools/editor/plugins/particles_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/particles_2d_editor_plugin.cpp
@@ -146,6 +146,7 @@ void Particles2DEditorPlugin::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
menu->get_popup()->connect("item_pressed",this,"_menu_callback");
+ menu->set_icon(menu->get_popup()->get_icon("Particles2D","EditorIcons"));
file->connect("file_selected",this,"_file_selected");
}
}
diff --git a/tools/editor/plugins/particles_editor_plugin.cpp b/tools/editor/plugins/particles_editor_plugin.cpp
index f6f01d82ca..5c84d9a86a 100644
--- a/tools/editor/plugins/particles_editor_plugin.cpp
+++ b/tools/editor/plugins/particles_editor_plugin.cpp
@@ -111,6 +111,7 @@ void ParticlesEditor::_populate() {
void ParticlesEditor::_notification(int p_notification) {
if (p_notification==NOTIFICATION_ENTER_TREE) {
+ options->set_icon(options->get_popup()->get_icon("Particles","EditorIcons"));
}
}
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index 77663f39c0..8fc6a6931e 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -2168,7 +2168,18 @@ void SpatialEditorViewport::set_state(const Dictionary& p_state) {
view_menu->get_popup()->set_item_checked( idx, listener );
}
-
+ if (p_state.has("previewing")) {
+ Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
+ if (pv && pv->cast_to<Camera>()) {
+ previewing=pv->cast_to<Camera>();
+ previewing->connect("exit_tree",this,"_preview_exited_scene");
+ VS::get_singleton()->viewport_attach_camera( viewport->get_viewport(), previewing->get_camera() ); //replace
+ view_menu->hide();
+ surface->update();
+ preview_camera->set_pressed(true);
+ preview_camera->show();
+ }
+ }
}
Dictionary SpatialEditorViewport::get_state() const {
@@ -2181,6 +2192,10 @@ Dictionary SpatialEditorViewport::get_state() const {
d["use_environment"]=camera->get_environment().is_valid();
d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
d["listener"]=viewport->is_audio_listener();
+ if (previewing) {
+ d["previewing"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
+ }
+
return d;
}
diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp
index a087f23c25..9f871fd3ab 100644
--- a/tools/editor/project_export.cpp
+++ b/tools/editor/project_export.cpp
@@ -80,7 +80,7 @@ bool ProjectExportDialog::_create_tree(TreeItem *p_parent,EditorFileSystemDirect
String path = p_dir->get_file_path(i);
fitem->set_tooltip(0,path);
fitem->set_metadata(0,path);
- Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),"EditorIcons")?p_dir->get_file_type(i):String("Object")),"EditorIcons");
+ Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),ei)?p_dir->get_file_type(i):ot),ei);
fitem->set_icon(0,icon);
fitem->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
@@ -1216,6 +1216,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
group_image_action->add_item("Default");
group_image_action->add_item("Compress Disk");
group_image_action->add_item("Compress RAM");
+ group_image_action->add_item("Keep Original");
group_options->add_margin_child("Compress Mode:",group_image_action);
group_image_action->connect("item_selected",this,"_group_changed");
@@ -1372,6 +1373,8 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
button_export = add_button("Export..",!OS::get_singleton()->get_swap_ok_cancel(),"export_pck");
updating_script=false;
+ ei="EditorIcons";
+ ot="Object";
}
diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h
index c88233ae01..d85e688e58 100644
--- a/tools/editor/project_export.h
+++ b/tools/editor/project_export.h
@@ -78,6 +78,9 @@ private:
HBoxContainer *plat_errors;
Label *platform_error_string;
+ StringName ei;
+ StringName ot;
+
Tree * tree;
EditorFileDialog *pck_export;
diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp
index fea9c705ef..25a2750166 100644
--- a/tools/editor/project_settings.cpp
+++ b/tools/editor/project_settings.cpp
@@ -771,18 +771,47 @@ void ProjectSettings::_autoload_add() {
void ProjectSettings::_autoload_delete(Object *p_item,int p_column, int p_button) {
+
TreeItem *ti=p_item->cast_to<TreeItem>();
String name = "autoload/"+ti->get_text(0);
- undo_redo->create_action("Remove Autoload");
- undo_redo->add_do_property(Globals::get_singleton(),name,Variant());
- undo_redo->add_undo_property(Globals::get_singleton(),name,Globals::get_singleton()->get(name));
- undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",name,true);
- undo_redo->add_do_method(this,"_update_autoload");
- undo_redo->add_undo_method(this,"_update_autoload");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
+ if (p_button==0) {
+ //delete
+ undo_redo->create_action("Remove Autoload");
+ undo_redo->add_do_property(Globals::get_singleton(),name,Variant());
+ undo_redo->add_undo_property(Globals::get_singleton(),name,Globals::get_singleton()->get(name));
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",name,true);
+ undo_redo->add_do_method(this,"_update_autoload");
+ undo_redo->add_undo_method(this,"_update_autoload");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+ } else {
+
+ TreeItem *swap;
+
+ if (p_button==1) {
+ swap=ti->get_prev();
+ } else if (p_button==2) {
+ swap=ti->get_next();
+ }
+ if (!swap)
+ return;
+
+ String swap_name= "autoload/"+swap->get_text(0);
+
+ undo_redo->create_action("Move Autoload");
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",swap_name,Globals::get_singleton()->get_order(name));
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",name,Globals::get_singleton()->get_order(swap_name));
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",swap_name,Globals::get_singleton()->get_order(swap_name));
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",name,Globals::get_singleton()->get_order(name));
+ undo_redo->add_do_method(this,"_update_autoload");
+ undo_redo->add_undo_method(this,"_update_autoload");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+ }
}
@@ -1134,6 +1163,8 @@ void ProjectSettings::_update_autoload() {
TreeItem *t = autoload_list->create_item(root);
t->set_text(0,name);
t->set_text(1,Globals::get_singleton()->get(pi.name));
+ t->add_button(1,get_icon("MoveUp","EditorIcons"),1);
+ t->add_button(1,get_icon("MoveDown","EditorIcons"),2);
t->add_button(1,get_icon("Del","EditorIcons"),0);
}
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index 955c426d2b..b513e32c13 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -39,6 +39,9 @@
#include "editor_settings.h"
#include "editor_import_export.h"
#include "editor_node.h"
+#include "multi_node_edit.h"
+#include "array_property_edit.h"
+#include "editor_help.h"
void CustomPropertyEditor::_notification(int p_what) {
@@ -2212,6 +2215,23 @@ void PropertyEditor::update_tree() {
sep->set_selectable(1,false);
sep->set_custom_bg_color(0,get_color("prop_category","Editor"));
sep->set_custom_bg_color(1,get_color("prop_category","Editor"));
+
+ if (use_doc_hints) {
+ StringName type=p.name;
+ if (!class_descr_cache.has(type)) {
+
+ String descr;
+ DocData *dd=EditorHelp::get_doc_data();
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
+ if (E) {
+ descr=E->get().brief_description;
+ }
+ class_descr_cache[type]=descr.world_wrap(80);
+
+ }
+
+ sep->set_tooltip(0,"Class: "+p.name+":\n\n"+class_descr_cache[type]);
+ }
//sep->set_custom_color(0,Color(1,1,1));
@@ -2265,6 +2285,42 @@ void PropertyEditor::update_tree() {
item->set_tooltip(0, p.name);
+ if (use_doc_hints) {
+ StringName setter;
+ StringName type;
+ if (ObjectTypeDB::get_setter_and_type_for_property(obj->get_type_name(),p.name,type,setter)) {
+
+ String descr;
+ bool found=false;
+ Map<StringName,Map<StringName,String> >::Element *E=descr_cache.find(type);
+ if (E) {
+
+ Map<StringName,String>::Element *F=E->get().find(setter);
+ if (F) {
+ found=true;
+ descr=F->get();
+ }
+ }
+ if (!found) {
+
+ DocData *dd=EditorHelp::get_doc_data();
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
+ if (E) {
+ for(int i=0;i<E->get().methods.size();i++) {
+ if (E->get().methods[i].name==setter.operator String()) {
+ descr=E->get().methods[i].description.strip_edges().world_wrap(80);
+ }
+ }
+ }
+
+ descr_cache[type][setter]=descr;
+ }
+
+ item->set_tooltip(0, "Property: "+p.name+"\n\n"+descr);
+ }
+ }
+ //EditorHelp::get_doc_data();
+
Dictionary d;
d["name"]=p.name;
d["type"]=(int)p.type;
@@ -2347,8 +2403,10 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
+ if (p.hint==PROPERTY_HINT_SPRITE_FRAME) {
+ item->set_range_config(1,0,99999,1);
- if (p.hint==PROPERTY_HINT_RANGE || p.hint==PROPERTY_HINT_EXP_RANGE) {
+ } else if (p.hint==PROPERTY_HINT_RANGE || p.hint==PROPERTY_HINT_EXP_RANGE) {
int c = p.hint_string.get_slice_count(",");
float min=0,max=100,step=1;
@@ -2449,11 +2507,32 @@ void PropertyEditor::update_tree() {
}
} break;
+ case Variant::ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Array["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Array[]");
+ item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
+
+
+ } break;
+
case Variant::INT_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- item->set_text(1,"[IntArray]");
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"IntArray["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"IntArray[]");
item->set_icon( 0, get_icon("ArrayInt","EditorIcons") );
@@ -2461,26 +2540,86 @@ void PropertyEditor::update_tree() {
case Variant::REAL_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- item->set_text(1,"[RealArray]");
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"FloatArray["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"FloatArray[]");
item->set_icon( 0, get_icon("ArrayReal","EditorIcons") );
+
} break;
case Variant::STRING_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- item->set_text(1,"[StringArray]");
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"String["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"String[]");
item->set_icon( 0, get_icon("ArrayString","EditorIcons") );
+
} break;
case Variant::RAW_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- item->set_text(1,"[Raw Data]");
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Byte["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Byte[]");
item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
+
+ } break;
+ case Variant::VECTOR2_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Vector2["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Vector2[]");
+ item->set_icon( 0, get_icon("Vector2","EditorIcons") );
+
+
+ } break;
+ case Variant::VECTOR3_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Vector3["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Vector3[]");
+ item->set_icon( 0, get_icon("Vector","EditorIcons") );
+
+
+ } break;
+ case Variant::COLOR_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Color["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Color[]");
+ item->set_icon( 0, get_icon("Color","EditorIcons") );
+
+
} break;
case Variant::VECTOR2: {
@@ -2676,7 +2815,7 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) {
}
}
- if (!undo_redo) {
+ if (!undo_redo || obj->cast_to<MultiNodeEdit>() || obj->cast_to<ArrayPropertyEdit>()) { //kind of hacky
obj->set(p_name,p_value);
_changed_callbacks(obj,p_name);
@@ -2996,6 +3135,19 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
emit_signal("resource_selected",r,n);
}
+ } else if (t==Variant::ARRAY || t==Variant::INT_ARRAY || t==Variant::REAL_ARRAY || t==Variant::STRING_ARRAY || t==Variant::VECTOR2_ARRAY || t==Variant::VECTOR3_ARRAY || t==Variant::COLOR_ARRAY || t==Variant::RAW_ARRAY) {
+
+ Variant v = obj->get(n);
+
+ if (v.get_type()!=t) {
+ Variant::CallError ce;
+ v=Variant::construct(Variant::Type(t),NULL,0,ce);
+ }
+
+ Ref<ArrayPropertyEdit> ape = memnew( ArrayPropertyEdit );
+ ape->edit(obj,n,Variant::Type(t));
+
+ EditorNode::get_singleton()->push_item(ape.ptr());
}
}
}
@@ -3181,6 +3333,7 @@ PropertyEditor::PropertyEditor() {
read_only=false;
show_categories=false;
refresh_countdown=0;
+ use_doc_hints=false;
}
diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h
index de5cac8711..36ecc794ed 100644
--- a/tools/editor/property_editor.h
+++ b/tools/editor/property_editor.h
@@ -95,6 +95,7 @@ class CustomPropertyEditor : public Popup {
Button *checks20[20];
+
Control *easing_draw;
Object* owner;
@@ -157,9 +158,13 @@ class PropertyEditor : public Control {
bool read_only;
bool show_categories;
float refresh_countdown;
+ bool use_doc_hints;
HashMap<String,String> pending;
String selected_property;
+
+ Map<StringName,Map<StringName,String> > descr_cache;
+ Map<StringName,String > class_descr_cache;
CustomPropertyEditor *custom_editor;
@@ -217,6 +222,7 @@ public:
void set_autoclear(bool p_enable);
void set_show_categories(bool p_show);
+ void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; }
PropertyEditor();
~PropertyEditor();
diff --git a/tools/editor/quick_open.cpp b/tools/editor/quick_open.cpp
index 749318386c..6135a4ab64 100644
--- a/tools/editor/quick_open.cpp
+++ b/tools/editor/quick_open.cpp
@@ -30,8 +30,9 @@
#include "os/keyboard.h"
-void EditorQuickOpen::popup(const String& p_base, bool p_dontclear) {
+void EditorQuickOpen::popup(const StringName &p_base, bool p_dontclear, bool p_add_dirs) {
+ add_directories=p_add_dirs;
popup_centered_ratio(0.6);
if (p_dontclear)
search_box->select_all();
@@ -66,27 +67,53 @@ void EditorQuickOpen::_sbox_input(const InputEvent& p_ie) {
void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd) {
- for(int i=0;i<efsd->get_subdir_count();i++) {
+ if (!add_directories) {
+ for(int i=0;i<efsd->get_subdir_count();i++) {
- _parse_fs(efsd->get_subdir(i));
+ _parse_fs(efsd->get_subdir(i));
+ }
}
+ TreeItem *root = search_options->get_root();
+
+ if (add_directories) {
+ String path = efsd->get_path();
+ if (!path.ends_with("/"))
+ path+="/";
+ if (path!="res://") {
+ path=path.substr(6,path.length());
+ if (path.findn(search_box->get_text())!=-1) {
+ TreeItem *ti = search_options->create_item(root);
+ ti->set_text(0,path);
+ Ref<Texture> icon = get_icon("folder","FileDialog");
+ ti->set_icon(0,icon);
+ }
+ }
+ }
for(int i=0;i<efsd->get_file_count();i++) {
String file = efsd->get_file_path(i);
file=file.substr(6,file.length());
if (ObjectTypeDB::is_type(efsd->get_file_type(i),base_type) && (search_box->get_text()=="" || file.findn(search_box->get_text())!=-1)) {
- TreeItem *root = search_options->get_root();
TreeItem *ti = search_options->create_item(root);
ti->set_text(0,file);
- Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),"EditorIcons")?efsd->get_file_type(i):String("Object")),"EditorIcons");
+ Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),ei)?efsd->get_file_type(i):ot),ei);
ti->set_icon(0,icon);
if (root->get_children()==ti)
ti->select(0);
}
}
+
+
+ if (add_directories) {
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+
+ _parse_fs(efsd->get_subdir(i));
+ }
+ }
+
}
void EditorQuickOpen::_update_search() {
@@ -118,7 +145,7 @@ void EditorQuickOpen::_notification(int p_what) {
}
-String EditorQuickOpen::get_base_type() const {
+StringName EditorQuickOpen::get_base_type() const {
return base_type;
}
@@ -152,4 +179,7 @@ EditorQuickOpen::EditorQuickOpen() {
set_hide_on_ok(false);
search_options->connect("item_activated",this,"_confirmed");
search_options->set_hide_root(true);
+ ei="EditorIcons";
+ ot="Object";
+ add_directories=false;
}
diff --git a/tools/editor/quick_open.h b/tools/editor/quick_open.h
index 63652a442a..8b38256d39 100644
--- a/tools/editor/quick_open.h
+++ b/tools/editor/quick_open.h
@@ -38,7 +38,11 @@ class EditorQuickOpen : public ConfirmationDialog {
LineEdit *search_box;
Tree *search_options;
- String base_type;
+ StringName base_type;
+ StringName ei;
+ StringName ot;
+ bool add_directories;
+
void _update_search();
@@ -55,9 +59,9 @@ protected:
static void _bind_methods();
public:
- String get_base_type() const;
+ StringName get_base_type() const;
- void popup(const String& p_base,bool p_dontclear=false);
+ void popup(const StringName& p_base,bool p_dontclear=false,bool p_add_dirs=false);
EditorQuickOpen();
};
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index ae0b58a665..276f2dea33 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -35,7 +35,7 @@
#include "tools/editor/plugins/canvas_item_editor_plugin.h"
#include "script_editor_debugger.h"
#include "tools/editor/plugins/script_editor_plugin.h"
-
+#include "multi_node_edit.h"
void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
@@ -450,6 +450,19 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
reparent_dialog->set_current( nodeset );
} break;
+ case TOOL_MULTI_EDIT: {
+
+ Node*root=EditorNode::get_singleton()->get_edited_scene();
+ if (!root)
+ break;
+ Ref<MultiNodeEdit> mne = memnew( MultiNodeEdit );
+ for (const Map<Node*,Object*>::Element *E=EditorNode::get_singleton()->get_editor_selection()->get_selection().front();E;E=E->next()) {
+ mne->add_node(root->get_path_to(E->key()));
+ }
+
+ EditorNode::get_singleton()->push_item(mne.ptr());
+
+ } break;
case TOOL_ERASE: {
List<Node*> remove_list = editor_selection->get_selected_node_list();
@@ -507,6 +520,7 @@ void SceneTreeDock::_notification(int p_what) {
"MoveDown",
"Duplicate",
"Reparent",
+ "MultiNodeEdit",
"Remove",
};
@@ -515,6 +529,8 @@ void SceneTreeDock::_notification(int p_what) {
for(int i=0;i<TOOL_BUTTON_MAX;i++)
tool_buttons[i]->set_icon(get_icon(button_names[i],"EditorIcons"));
+ EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed",this,"_selection_changed");
+
} break;
}
}
@@ -1075,9 +1091,19 @@ void SceneTreeDock::_update_tool_buttons() {
tool_buttons[TOOL_DUPLICATE]->set_disabled(disable_root);
tool_buttons[TOOL_REPARENT]->set_disabled(disable_root);
tool_buttons[TOOL_ERASE]->set_disabled(disable);
+ tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
+
}
+
+void SceneTreeDock::_selection_changed() {
+
+ tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
+
+}
+
+
void SceneTreeDock::_create() {
@@ -1262,6 +1288,7 @@ void SceneTreeDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_delete_confirm"),&SceneTreeDock::_delete_confirm);
ObjectTypeDB::bind_method(_MD("_node_prerenamed"),&SceneTreeDock::_node_prerenamed);
ObjectTypeDB::bind_method(_MD("_import_subscene"),&SceneTreeDock::_import_subscene);
+ ObjectTypeDB::bind_method(_MD("_selection_changed"),&SceneTreeDock::_selection_changed);
ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance);
}
@@ -1365,6 +1392,12 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
hbc_bottom->add_spacer();
tb = memnew( ToolButton );
+ tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_MULTI_EDIT, false));
+ tb->set_tooltip("Multi-Edit Selected Nodes");
+ hbc_bottom->add_child(tb);
+ tool_buttons[TOOL_MULTI_EDIT]=tb;
+
+ tb = memnew( ToolButton );
tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_ERASE, false));
tb->set_tooltip("Erase Selected Node(s)");
hbc_bottom->add_child(tb);
diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h
index f0bbbad6be..b1c53d2ff9 100644
--- a/tools/editor/scene_tree_dock.h
+++ b/tools/editor/scene_tree_dock.h
@@ -62,6 +62,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_MOVE_DOWN,
TOOL_DUPLICATE,
TOOL_REPARENT,
+ TOOL_MULTI_EDIT,
TOOL_ERASE,
TOOL_BUTTON_MAX
};
@@ -119,6 +120,7 @@ class SceneTreeDock : public VBoxContainer {
void _import_subscene();
bool _validate_no_foreign();
+ void _selection_changed();
void _fill_path_renames(Vector<StringName> base_path,Vector<StringName> new_base_path,Node * p_node, List<Pair<NodePath,NodePath> > *p_renames);
diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp
index 9153616775..7d9c5b24b2 100644
--- a/tools/editor/scenes_dock.cpp
+++ b/tools/editor/scenes_dock.cpp
@@ -35,15 +35,30 @@
#include "os/os.h"
#include "editor_node.h"
+#include "editor_settings.h"
+
bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) {
- String search_term = tree_filter->get_search_term();
- ScenesDockFilter::FilterOption file_filter = tree_filter->get_file_filter();
TreeItem *item = tree->create_item(p_parent);
- item->set_text(0,p_dir->get_name()+"/");
+ String dname=p_dir->get_name();
+ if (dname=="")
+ dname="res://";
+
+ item->set_text(0,dname);
item->set_icon(0,get_icon("Folder","EditorIcons"));
- item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
+ item->set_selectable(0,true);
+ String lpath = p_dir->get_path();
+ if (lpath!="res://" && lpath.ends_with("/")) {
+ lpath=lpath.substr(0,lpath.length()-1);
+ }
+ item->set_metadata(0,lpath);
+ if (lpath==path) {
+ item->select(0);
+ }
+
+
+ //item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
bool has_items=false;
@@ -52,7 +67,7 @@ bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_di
if (_create_tree(item,p_dir->get_subdir(i)))
has_items=true;
}
-
+#if 0
for (int i=0;i<p_dir->get_file_count();i++) {
String file_name = p_dir->get_file(i);
@@ -89,13 +104,13 @@ bool ScenesDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_di
has_items=true;
}
-
- if (!has_items) {
+#endif
+ /*if (!has_items) {
memdelete(item);
return false;
- }
+ }*/
return true;
}
@@ -105,7 +120,28 @@ void ScenesDock::_update_tree() {
tree->clear();
updating_tree=true;
- _create_tree(NULL,EditorFileSystem::get_singleton()->get_filesystem());
+ TreeItem *root = tree->create_item();
+ TreeItem *favorites = tree->create_item(root);
+ favorites->set_icon(0, get_icon("Favorites","EditorIcons") );
+ favorites->set_text(0,"Favorites:");
+ favorites->set_selectable(0,false);
+ Vector<String> faves = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<faves.size();i++) {
+ if (!faves[i].begins_with("res://"))
+ continue;
+
+ TreeItem *ti = tree->create_item(favorites);
+ String fv = faves[i];
+ if (fv=="res://")
+ ti->set_text(0,"/");
+ else
+ ti->set_text(0,faves[i].get_file());
+ ti->set_icon(0,get_icon("Folder","EditorIcons"));
+ ti->set_selectable(0,true);
+ ti->set_metadata(0,faves[i]);
+ }
+
+ _create_tree(root,EditorFileSystem::get_singleton()->get_filesystem());
updating_tree=false;
}
@@ -117,68 +153,192 @@ void ScenesDock::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
+ if (initialized)
+ return;
+ initialized=false;
- EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_update_tree");
+ EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed");
button_reload->set_icon( get_icon("Reload","EditorIcons"));
button_favorite->set_icon( get_icon("Favorites","EditorIcons"));
+ button_fav_up->set_icon( get_icon("MoveUp","EditorIcons"));
+ button_fav_down->set_icon( get_icon("MoveDown","EditorIcons"));
button_instance->set_icon( get_icon("Add","EditorIcons"));
button_open->set_icon( get_icon("Folder","EditorIcons"));
+ button_back->set_icon( get_icon("Filesystem","EditorIcons"));
+ display_mode->set_icon( get_icon("FileList","EditorIcons"));
+ display_mode->connect("pressed",this,"_change_file_display");
+ file_options->set_icon( get_icon("Tools","EditorIcons"));
+ files->connect("item_activated",this,"_select_file");
+ button_hist_next->connect("pressed",this,"_fw_history");
+ button_hist_prev->connect("pressed",this,"_bw_history");
- String path = Globals::get_singleton()->get_resource_path()+"/favorites.cfg";
- FileAccess *f=FileAccess::open(path,FileAccess::READ);
- if (f) {
+ button_hist_next->set_icon( get_icon("Forward","EditorIcons"));
+ button_hist_prev->set_icon( get_icon("Back","EditorIcons"));
+ file_options->get_popup()->connect("item_pressed",this,"_file_option");
- String l = f->get_line();
- while(l!="") {
- favorites.insert(l);
- l = f->get_line();
-
- }
+ button_back->connect("pressed",this,"_go_to_tree",varray(),CONNECT_DEFERRED);
+ current_path->connect("text_entered",this,"_go_to_dir");
+ _update_tree(); //maybe it finished already
- f->close();
- memdelete(f);
+ if (EditorFileSystem::get_singleton()->is_scanning()) {
+ _set_scannig_mode();
}
-
-
- _update_tree(); //maybe it finished already
+ } break;
+ case NOTIFICATION_PROCESS: {
+ if (EditorFileSystem::get_singleton()->is_scanning()) {
+ scanning_progress->set_val(EditorFileSystem::get_singleton()->get_scanning_progress()*100);
+ }
} break;
case NOTIFICATION_EXIT_TREE: {
} break;
- case NOTIFICATION_PROCESS: {
- } break;
}
}
-void ScenesDock::_favorite_toggled() {
- if (updating_tree)
+
+
+void ScenesDock::_dir_selected() {
+
+ TreeItem *ti = tree->get_selected();
+ if (!ti)
return;
+ String dir = ti->get_metadata(0);
+ bool found=false;
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<favorites.size();i++) {
+
+ if (favorites[i]==dir) {
+ found=true;
+ break;
+ }
+ }
+
+
+ button_favorite->set_pressed(found);
+ if (ti->get_parent() && ti->get_parent()->get_parent()==tree->get_root() && !ti->get_parent()->get_prev()) {
+
+ //a favorite!!!
+ button_fav_up->set_disabled(!ti->get_prev());
+ button_fav_down->set_disabled(!ti->get_next());
+ } else {
+ button_fav_up->set_disabled(true);
+ button_fav_down->set_disabled(true);
+
+ }
+}
+
+void ScenesDock::_fav_up_pressed() {
TreeItem *sel = tree->get_selected();
if (!sel)
- return; //?
+ return ;
- bool faved = sel->is_checked(0);
- String path = sel->get_metadata(0);
- if (faved)
- favorites.insert(path);
- else
- favorites.erase(path);
+ if (!sel->get_prev())
+ return;
+
+ String sw = sel->get_prev()->get_metadata(0);
+ String txt = sel->get_metadata(0);
+
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+
+ int a_idx=favorited.find(sw);
+ int b_idx=favorited.find(txt);
+
+ if (a_idx==-1 || b_idx==-1)
+ return;
+ SWAP(favorited[a_idx],favorited[b_idx]);
+
+ EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+
+ _update_tree();
- timer->start();
+ if (!tree->get_root() || !tree->get_root()->get_children() || !tree->get_root()->get_children()->get_children())
+ return;
+ sel = tree->get_root()->get_children()->get_children();
+ while(sel) {
+ String t = sel->get_metadata(0);
+ if (t==txt) {
+ sel->select(0);
+ return;
+ }
+ sel=sel->get_next();
+ }
}
-void ScenesDock::_favorites_toggled(bool p_toggled) {
+void ScenesDock::_fav_down_pressed() {
+
+ TreeItem *sel = tree->get_selected();
+ if (!sel)
+ return ;
+
+ if (!sel->get_next())
+ return;
+
+ String sw = sel->get_next()->get_metadata(0);
+ String txt = sel->get_metadata(0);
+
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+
+ int a_idx=favorited.find(sw);
+ int b_idx=favorited.find(txt);
+
+ if (a_idx==-1 || b_idx==-1)
+ return;
+ SWAP(favorited[a_idx],favorited[b_idx]);
+
+ EditorSettings::get_singleton()->set_favorite_dirs(favorited);
_update_tree();
+
+ if (!tree->get_root() || !tree->get_root()->get_children() || !tree->get_root()->get_children()->get_children())
+ return;
+ sel = tree->get_root()->get_children()->get_children();
+ while(sel) {
+
+ String t = sel->get_metadata(0);
+ if (t==txt) {
+ sel->select(0);
+ return;
+ }
+ sel=sel->get_next();
+ }
+}
+
+void ScenesDock::_favorites_pressed() {
+
+ TreeItem *sel = tree->get_selected();
+ if (!sel)
+ return ;
+ String dir = sel->get_metadata(0);
+
+ int idx = -1;
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<favorites.size();i++) {
+
+ if (favorites[i]==dir) {
+ idx=i;
+ break;
+ }
+ }
+
+ if (button_favorite->is_pressed() && idx==-1) {
+ favorites.push_back(dir);
+ EditorSettings::get_singleton()->set_favorite_dirs(favorites);
+ _update_tree();
+ } else if (!button_favorite->is_pressed() && idx!=-1) {
+ favorites.remove(idx);
+ EditorSettings::get_singleton()->set_favorite_dirs(favorites);
+ _update_tree();
+ }
+
}
String ScenesDock::get_selected_path() const {
@@ -199,65 +359,712 @@ void ScenesDock::_instance_pressed() {
emit_signal("instance",path);
}
-void ScenesDock::_open_pressed(){
+void ScenesDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
- TreeItem *sel = tree->get_selected();
- if (!sel) {
+ if (p_preview.is_valid() && path==p_path.get_base_dir()) {
+
+ int idx=p_udata;
+ if (idx>=files->get_item_count())
+ return;
+ String fpath = files->get_item_metadata(idx);
+ if (fpath!=p_path)
+ return;
+ files->set_item_icon(idx,p_preview);
+
+ }
+
+}
+
+void ScenesDock::_change_file_display() {
+
+ if (display_mode->is_pressed()) {
+ display_mode->set_icon( get_icon("FileThumbnail","EditorIcons"));
+
+ } else {
+ display_mode->set_icon( get_icon("FileList","EditorIcons"));
+ }
+
+ _update_files(true);
+}
+
+void ScenesDock::_update_files(bool p_keep_selection) {
+
+ Set<String> cselection;
+
+ if (p_keep_selection) {
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ if (files->is_selected(i))
+ cselection.insert(files->get_item_text(i));
+ }
+ }
+
+ files->clear();
+
+ EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_path(path);
+ if (!efd)
return;
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+ Ref<Texture> folder_thumbnail;
+ Ref<Texture> file_thumbnail;
+
+ bool use_thumbnails=!display_mode->is_pressed();
+
+ if (use_thumbnails) { //thumbnails
+
+ files->set_max_columns(0);
+ files->set_icon_mode(ItemList::ICON_MODE_TOP);
+ files->set_fixed_column_width(thumbnail_size*3/2);
+ files->set_max_text_lines(2);
+ files->set_min_icon_size(Size2(thumbnail_size,thumbnail_size));
+
+ if (!has_icon("ResizedFolder","EditorIcons")) {
+ Ref<ImageTexture> folder = get_icon("FolderBig","EditorIcons");
+ Image img = folder->get_data();
+ img.resize(thumbnail_size,thumbnail_size);
+ Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
+ resized_folder->create_from_image(img,0);
+ Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
+ }
+
+ folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
+
+ if (!has_icon("ResizedFile","EditorIcons")) {
+ Ref<ImageTexture> file = get_icon("FileBig","EditorIcons");
+ Image img = file->get_data();
+ img.resize(thumbnail_size,thumbnail_size);
+ Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
+ resized_file->create_from_image(img,0);
+ Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
+ }
+
+ file_thumbnail = get_icon("ResizedFile","EditorIcons");
+
+ } else {
+
+ files->set_icon_mode(ItemList::ICON_MODE_LEFT);
+ files->set_max_columns(1);
+ files->set_max_text_lines(1);
+ files->set_fixed_column_width(0);
+ files->set_min_icon_size(Size2());
+
}
- String path = sel->get_metadata(0);
- if (ResourceLoader::get_resource_type(path)=="PackedScene") {
- editor->open_request(path);
+ if (path!="res://") {
+
+ if (use_thumbnails) {
+ files->add_item("..",folder_thumbnail,true);
+ } else {
+ files->add_item("..",get_icon("folder","FileDialog"),true);
+ }
+
+ String bd = path.get_base_dir();
+ if (bd!="res://" && !bd.ends_with("/"))
+ bd+="/";
+
+ files->set_item_metadata(files->get_item_count()-1,bd);
+ }
+
+ for(int i=0;i<efd->get_subdir_count();i++) {
+
+ String dname=efd->get_subdir(i)->get_name();
+
+
+ if (use_thumbnails) {
+ files->add_item(dname,folder_thumbnail,true);
+ } else {
+ files->add_item(dname,get_icon("folder","FileDialog"),true);
+ }
+
+ files->set_item_metadata(files->get_item_count()-1,path.plus_file(dname)+"/");
+
+ if (cselection.has(dname))
+ files->select(files->get_item_count()-1,false);
+ }
+
+ for(int i=0;i<efd->get_file_count();i++) {
+
+ String fname=efd->get_file(i);
+ String fp = path.plus_file(fname);
+
+
+ String type = efd->get_file_type(i);
+ Ref<Texture> type_icon;
+
+ if (has_icon(type,"EditorIcons")) {
+ type_icon=get_icon(type,"EditorIcons");
+ } else {
+ type_icon=get_icon("Object","EditorIcons");
+ }
+
+ if (use_thumbnails) {
+ files->add_item(fname,file_thumbnail,true);
+ files->set_item_metadata(files->get_item_count()-1,fp);
+ files->set_item_tag_icon(files->get_item_count()-1,type_icon);
+ EditorResourcePreview::get_singleton()->queue_resource_preview(fp,this,"_thumbnail_done",files->get_item_count()-1);
+ } else {
+ files->add_item(fname,type_icon,true);
+ files->set_item_metadata(files->get_item_count()-1,fp);
+
+ }
+
+ if (cselection.has(fname))
+ files->select(files->get_item_count()-1,false);
+
+ }
+
+
+}
+
+void ScenesDock::_select_file(int p_idx) {
+
+ files->select(p_idx,true);
+ _open_pressed();
+}
+
+void ScenesDock::_go_to_tree() {
+
+ tree->show();
+ files->hide();
+ path_hb->hide();
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
+ button_favorite->show();
+ button_fav_up->show();
+ button_fav_down->show();
+ button_open->hide();
+ button_instance->hide();
+ button_open->hide();
+ file_options->hide();
+ tree_mode=true;
+}
+
+void ScenesDock::_go_to_dir(const String& p_dir){
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->change_dir(p_dir)==OK) {
+ path=da->get_current_dir();
+ _update_files(false);
+ }
+ current_path->set_text(path);
+ memdelete(da);
+
+
+}
+void ScenesDock::_fs_changed() {
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+ scanning_vb->hide();
+
+ if (tree_mode) {
+
+ tree->show();
+ button_favorite->show();
+ button_fav_up->show();
+ button_fav_down->show();
+ _update_tree();
+ } else {
+ files->show();
+ path_hb->show();
+ button_instance->show();
+ button_open->show();
+ file_options->show();
+ _update_files(true);
+ }
+
+ set_process(false);
+}
+
+void ScenesDock::_set_scannig_mode() {
+
+ tree->hide();
+ button_favorite->hide();
+ button_fav_up->hide();
+ button_fav_down->hide();
+ button_instance->hide();
+ button_open->hide();
+ file_options->hide();
+ button_hist_prev->set_disabled(true);
+ button_hist_next->set_disabled(true);
+ scanning_vb->show();
+ path_hb->hide();
+ files->hide();
+ set_process(true);
+ if (EditorFileSystem::get_singleton()->is_scanning()) {
+ scanning_progress->set_val(EditorFileSystem::get_singleton()->get_scanning_progress()*100);
+ } else {
+ scanning_progress->set_val(0);
+ }
+
+}
+
+void ScenesDock::_fw_history() {
+
+ if (history_pos<history.size()-1)
+ history_pos++;
+
+ path=history[history_pos];
+
+ if (tree_mode) {
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
+ } else {
+ _update_files(false);
+ current_path->set_text(path);
+ }
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+
+}
+
+void ScenesDock::_bw_history() {
+
+ if (history_pos>0)
+ history_pos--;
+
+ path=history[history_pos];
+
+ if (tree_mode) {
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
} else {
+ _update_files(false);
+ current_path->set_text(path);
+ }
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+
+}
+
+void ScenesDock::_push_to_history() {
- /*
+ history.resize(history_pos+1);
+ if (history[history_pos]!=path) {
+ history.push_back(path);
+ history_pos++;
+ }
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+
+}
+
+
+void ScenesDock::_find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files) {
- RES res = ResourceLoader::load(path);
- if (res.is_null()) {
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _find_inside_move_files(efsd->get_subdir(i),files);
+ }
+ for(int i=0;i<efsd->get_file_count();i++) {
+ files.push_back(efsd->get_file_path(i));
+ }
+
+}
+void ScenesDock::_find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps) {
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _find_remaps(efsd->get_subdir(i),renames,to_remaps);
+ }
+ for(int i=0;i<efsd->get_file_count();i++) {
+ Vector<String> deps=efsd->get_file_deps(i);
+ for(int j=0;j<deps.size();j++) {
+ if (renames.has(deps[j])) {
+ to_remaps.push_back(efsd->get_file_path(i));
+ break;
+ }
+ }
+ }
+}
+
+
+void ScenesDock::_rename_operation(const String& p_to_path) {
+
+ if (move_files[0]==p_to_path) {
+ EditorNode::get_singleton()->show_warning("Same source and destination files, doing nothing.");
+ return;
+ }
+ if (FileAccess::exists(p_to_path)) {
+ EditorNode::get_singleton()->show_warning("Target file exists, can't overwrite. Delete first.");
+ return;
+ }
+
+ Map<String,String> renames;
+ renames[move_files[0]]=p_to_path;
+
+ List<String> remap;
+
+ _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap);
+ print_line("found files to remap: "+itos(remap.size()));
+
+ //perform remaps
+ for(List<String>::Element *E=remap.front();E;E=E->next()) {
+
+ Error err = ResourceLoader::rename_dependencies(E->get(),renames);
+ print_line("remapping: "+E->get());
+
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n");
+ }
+ }
+
+ //finally, perform moves
+
+ DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES);
+
+ Error err = da->rename(move_files[0],p_to_path);
+ print_line("moving file "+move_files[0]+" to "+p_to_path);
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[0]+"\n");
+ }
+
+ //rescan everything
+ memdelete(da);
+ print_line("call rescan!");
+ _rescan();
+}
+
+
+void ScenesDock::_move_operation(const String& p_to_path) {
+
+ if (p_to_path==path) {
+ EditorNode::get_singleton()->show_warning("Same source and destination paths, doing nothing.");
+ return;
+ }
+
+ //find files inside dirs to be moved
+
+ Vector<String> inside_files;
+
+ for(int i=0;i<move_dirs.size();i++) {
+ if (p_to_path.begins_with(move_dirs[i])) {
+ EditorNode::get_singleton()->show_warning("Can't move directories to within themselves");
return;
- }*/
+ }
- editor->load_resource(path);
+ EditorFileSystemDirectory *efsd=EditorFileSystem::get_singleton()->get_path(move_dirs[i]);
+ if (!efsd)
+ continue;
+ _find_inside_move_files(efsd,inside_files);
}
-// emit_signal("open",path);
+ //make list of remaps
+ Map<String,String> renames;
+ String repfrom=path=="res://"?path:String(path+"/");
+ String repto=p_to_path=="res://"?p_to_path:String(p_to_path+"/");
+
+ for(int i=0;i<move_files.size();i++) {
+ renames[move_files[i]]=move_files[i].replace_first(repfrom,repto);
+ print_line("move file "+move_files[i]+" -> "+renames[move_files[i]]);
+ }
+ for(int i=0;i<inside_files.size();i++) {
+ renames[inside_files[i]]=inside_files[i].replace_first(repfrom,repto);
+ print_line("inside file "+inside_files[i]+" -> "+renames[inside_files[i]]);
+ }
+
+ //make list of files that will be run the remapping
+ List<String> remap;
+ _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap);
+ print_line("found files to remap: "+itos(remap.size()));
+
+ //perform remaps
+ for(List<String>::Element *E=remap.front();E;E=E->next()) {
+
+ Error err = ResourceLoader::rename_dependencies(E->get(),renames);
+ print_line("remapping: "+E->get());
+
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n");
+ }
+ }
+
+ //finally, perform moves
+
+ DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES);
+
+ for(int i=0;i<move_files.size();i++) {
+
+ String to = move_files[i].replace_first(repfrom,repto);
+ Error err = da->rename(move_files[i],to);
+ print_line("moving file "+move_files[i]+" to "+to);
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[i]+"\n");
+ }
+ }
+
+ for(int i=0;i<move_dirs.size();i++) {
+
+ String to = p_to_path.plus_file(move_dirs[i].get_file());
+ Error err = da->rename(move_dirs[i],to);
+ print_line("moving dir "+move_dirs[i]+" to "+to);
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Error moving dir:\n"+move_dirs[i]+"\n");
+ }
+ }
+
+ memdelete(da);
+ //rescan everything
+ print_line("call rescan!");
+ _rescan();
+
+}
+
+void ScenesDock::_file_option(int p_option) {
+
+ switch(p_option) {
+
+ case FILE_DEPENDENCIES: {
+
+ int idx = files->get_current();
+ if (idx<0 || idx>=files->get_item_count())
+ break;
+ String path = files->get_item_metadata(idx);
+ deps_editor->edit(path);
+ } break;
+ case FILE_OWNERS: {
+
+ int idx = files->get_current();
+ if (idx<0 || idx>=files->get_item_count())
+ break;
+ String path = files->get_item_metadata(idx);
+ owners_editor->show(path);
+ } break;
+ case FILE_MOVE: {
+
+ move_dirs.clear();;
+ move_files.clear();
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ String path = files->get_item_metadata(i);
+ if (!files->is_selected(i))
+ continue;
+
+ if (files->get_item_text(i)=="..") {
+ EditorNode::get_singleton()->show_warning("Can't operate on '..'");
+ return;
+ }
+
+ if (path.ends_with("/")) {
+ move_dirs.push_back(path.substr(0,path.length()-1));
+ } else {
+ move_files.push_back(path);
+ }
+ }
+
+
+ if (move_dirs.empty() && move_files.size()==1) {
+
+ rename_dialog->clear_filters();
+ rename_dialog->add_filter("*."+move_files[0].extension());
+ rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ rename_dialog->set_current_path(move_files[0]);
+ rename_dialog->popup_centered_ratio();
+ rename_dialog->set_title("Pick New Name and Location For: "+move_files[0].get_file());
+
+
+ } else {
+ //just move
+ move_dialog->popup_centered_ratio();
+ }
+
+
+ } break;
+ case FILE_REMOVE: {
+
+ Vector<String> torem;
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ String path = files->get_item_metadata(i);
+ if (path.ends_with("/") || !files->is_selected(i))
+ continue;
+ torem.push_back(path);
+ }
+
+ if (torem.empty()) {
+ EditorNode::get_singleton()->show_warning("No files selected!");
+ break;
+ }
+
+ remove_dialog->show(torem);
+ //1) find if used
+ //2) warn
+
+ } break;
+ case FILE_INFO: {
+
+ } break;
+
+ }
}
-void ScenesDock::_save_favorites() {
+void ScenesDock::_open_pressed(){
+
+
+ if (tree_mode) {
+
+ TreeItem *sel = tree->get_selected();
+ if (!sel) {
+ return;
+ }
+ path = sel->get_metadata(0);
+ /*if (path!="res://" && path.ends_with("/")) {
+ path=path.substr(0,path.length()-1);
+ }*/
+
+ tree_mode=false;
+
+ tree->hide();
+ files->show();
+ path_hb->show();
+ button_favorite->hide();
+ button_fav_up->hide();
+ button_fav_down->hide();
+ button_instance->show();
+ button_open->show();
+ file_options->show();
+
+ _update_files(false);
- String path = Globals::get_singleton()->get_resource_path()+"/favorites.cfg";
- FileAccess *f=FileAccess::open(path,FileAccess::WRITE);
- ERR_FAIL_COND(!f);
- for(Set<String>::Element *E=favorites.front();E;E=E->next() ) {
+ current_path->set_text(path);
- CharString utf8f = E->get().utf8();
- f->store_buffer((const uint8_t*)utf8f.get_data(),utf8f.length());
- f->store_8('\n');
+ _push_to_history();
+
+
+ } else {
+
+ int idx=-1;
+ for(int i=0;i<files->get_item_count();i++) {
+ if (files->is_selected(i)) {
+ idx=i;
+ break;
+ }
+ }
+
+ if (idx<0)
+ return;
+
+
+
+ String path = files->get_item_metadata(idx);
+
+ if (path.ends_with("/")) {
+ if (path!="res://") {
+ path=path.substr(0,path.length()-1);
+ }
+ this->path=path;
+ _update_files(false);
+ current_path->set_text(path);
+ _push_to_history();
+ } else {
+
+ if (ResourceLoader::get_resource_type(path)=="PackedScene") {
+
+ editor->open_request(path);
+ } else {
+
+ editor->load_resource(path);
+ }
+ }
}
- f->close();
- memdelete(f);
+// emit_signal("open",path);
+
}
+
void ScenesDock::_rescan() {
+ _set_scannig_mode();
EditorFileSystem::get_singleton()->scan();
+
+}
+
+void ScenesDock::fix_dependencies(const String& p_for_file) {
+ deps_editor->edit(p_for_file);
+}
+
+void ScenesDock::open(const String& p_path) {
+
+
+ String npath;
+ String nfile;
+
+ if (p_path.ends_with("/")) {
+
+ if (p_path!="res://")
+ npath=p_path.substr(0,p_path.length()-1);
+ else
+ npath="res://";
+ } else {
+ nfile=p_path.get_file();
+ npath=p_path.get_base_dir();
+ }
+
+ path=npath;
+
+ if (tree_mode && nfile=="") {
+ _update_tree();
+ tree->grab_focus();
+ tree->call_deferred("ensure_cursor_is_visible");
+ _push_to_history();
+ return;
+ } else if (tree_mode){
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
+ _open_pressed();
+ current_path->set_text(path);
+ } else {
+ _update_files(false);
+ _push_to_history();
+ }
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ String md = files->get_item_metadata(i);
+ if (md==p_path) {
+ files->select(i,true);
+ files->ensure_current_is_visible();
+ break;
+ }
+ }
+
}
void ScenesDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_update_tree"),&ScenesDock::_update_tree);
ObjectTypeDB::bind_method(_MD("_rescan"),&ScenesDock::_rescan);
- ObjectTypeDB::bind_method(_MD("_favorites_toggled"),&ScenesDock::_favorites_toggled);
- ObjectTypeDB::bind_method(_MD("_favorite_toggled"),&ScenesDock::_favorite_toggled);
+ ObjectTypeDB::bind_method(_MD("_favorites_pressed"),&ScenesDock::_favorites_pressed);
ObjectTypeDB::bind_method(_MD("_instance_pressed"),&ScenesDock::_instance_pressed);
ObjectTypeDB::bind_method(_MD("_open_pressed"),&ScenesDock::_open_pressed);
- ObjectTypeDB::bind_method(_MD("_save_favorites"),&ScenesDock::_save_favorites);
+
+ ObjectTypeDB::bind_method(_MD("_thumbnail_done"),&ScenesDock::_thumbnail_done);
+ ObjectTypeDB::bind_method(_MD("_select_file"), &ScenesDock::_select_file);
+ ObjectTypeDB::bind_method(_MD("_go_to_tree"), &ScenesDock::_go_to_tree);
+ ObjectTypeDB::bind_method(_MD("_go_to_dir"), &ScenesDock::_go_to_dir);
+ ObjectTypeDB::bind_method(_MD("_change_file_display"), &ScenesDock::_change_file_display);
+ ObjectTypeDB::bind_method(_MD("_fw_history"), &ScenesDock::_fw_history);
+ ObjectTypeDB::bind_method(_MD("_bw_history"), &ScenesDock::_bw_history);
+ ObjectTypeDB::bind_method(_MD("_fs_changed"), &ScenesDock::_fs_changed);
+ ObjectTypeDB::bind_method(_MD("_dir_selected"), &ScenesDock::_dir_selected);
+ ObjectTypeDB::bind_method(_MD("_fav_up_pressed"), &ScenesDock::_fav_up_pressed);
+ ObjectTypeDB::bind_method(_MD("_fav_down_pressed"), &ScenesDock::_fav_down_pressed);
+ ObjectTypeDB::bind_method(_MD("_file_option"), &ScenesDock::_file_option);
+ ObjectTypeDB::bind_method(_MD("_move_operation"), &ScenesDock::_move_operation);
+ ObjectTypeDB::bind_method(_MD("_rename_operation"), &ScenesDock::_rename_operation);
ADD_SIGNAL(MethodInfo("instance"));
ADD_SIGNAL(MethodInfo("open"));
@@ -271,153 +1078,156 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
HBoxContainer *toolbar_hbc = memnew( HBoxContainer );
add_child(toolbar_hbc);
+ button_hist_prev = memnew( ToolButton );
+ toolbar_hbc->add_child(button_hist_prev);
+ button_hist_prev->set_disabled(true);
+ button_hist_prev->set_tooltip("Previous Directory");
+
+ button_hist_next = memnew( ToolButton );
+ toolbar_hbc->add_child(button_hist_next);
+ button_hist_next->set_disabled(true);
+ button_hist_prev->set_focus_mode(FOCUS_NONE);
+ button_hist_next->set_focus_mode(FOCUS_NONE);
+ button_hist_next->set_tooltip("Next Directory");
+
button_reload = memnew( Button );
button_reload->set_flat(true);
button_reload->connect("pressed",this,"_rescan");
toolbar_hbc->add_child(button_reload);
+ button_reload->set_focus_mode(FOCUS_NONE);
+ button_reload->set_tooltip("Re-Scan Filesystem");
+
+ toolbar_hbc->add_spacer();
+
+ button_fav_up = memnew( ToolButton );
+ button_fav_up->set_flat(true);
+ toolbar_hbc->add_child(button_fav_up);
+ button_fav_up->set_disabled(true);
+ button_fav_up->connect("pressed",this,"_fav_up_pressed");
+ button_fav_up->set_tooltip("Move Favorite Up");
+
+ button_fav_down = memnew( ToolButton );
+ button_fav_down->set_flat(true);
+ toolbar_hbc->add_child(button_fav_down);
+ button_fav_down->set_disabled(true);
+ button_fav_down->connect("pressed",this,"_fav_down_pressed");
+ button_fav_down->set_tooltip("Move Favorite Down");
button_favorite = memnew( Button );
button_favorite->set_flat(true);
button_favorite->set_toggle_mode(true);
- button_favorite->connect("toggled",this,"_favorites_toggled");
+ button_favorite->connect("pressed",this,"_favorites_pressed");
toolbar_hbc->add_child(button_favorite);
+ button_favorite->set_tooltip("Toggle folder status as Favorite");
+
+ button_favorite->set_focus_mode(FOCUS_NONE);
+ button_fav_up->set_focus_mode(FOCUS_NONE);
+ button_fav_down->set_focus_mode(FOCUS_NONE);
- toolbar_hbc->add_spacer();
button_open = memnew( Button );
button_open->set_flat(true);
button_open->connect("pressed",this,"_open_pressed");
toolbar_hbc->add_child(button_open);
+ button_open->hide();
+ button_open->set_focus_mode(FOCUS_NONE);
+ button_open->set_tooltip("Open the selected file.\nOpen as scene if a scene, or as resource otherwise.");
+
button_instance = memnew( Button );
button_instance->set_flat(true);
button_instance->connect("pressed",this,"_instance_pressed");
toolbar_hbc->add_child(button_instance);
+ button_instance->hide();
+ button_instance->set_focus_mode(FOCUS_NONE);
+ button_instance->set_tooltip("Instance the selected scene(s) as child of the selected node.");
+
+
+ file_options = memnew( MenuButton );
+ toolbar_hbc->add_child(file_options);
+ file_options->get_popup()->add_item("Rename or Move",FILE_MOVE);
+ file_options->get_popup()->add_item("Delete",FILE_REMOVE);
+ file_options->get_popup()->add_separator();
+ file_options->get_popup()->add_item("Edit Dependencies",FILE_DEPENDENCIES);
+ file_options->get_popup()->add_item("View Owners",FILE_OWNERS);
+ //file_options->get_popup()->add_item("Info",FILE_INFO);
+ file_options->hide();
+ file_options->set_focus_mode(FOCUS_NONE);
+ file_options->set_tooltip("Miscenaneous options related to resources on disk.");
tree = memnew( Tree );
- tree_filter=memnew( ScenesDockFilter() );
- tree_filter->connect("filter_changed", this, "_update_tree");
- add_child(tree_filter);
+
+ tree->set_hide_root(true);
add_child(tree);
+
tree->set_v_size_flags(SIZE_EXPAND_FILL);
tree->connect("item_edited",this,"_favorite_toggled");
tree->connect("item_activated",this,"_open_pressed");
-
- timer = memnew( Timer );
- timer->set_one_shot(true);
- timer->set_wait_time(2);
- timer->connect("timeout",this,"_save_favorites");
- add_child(timer);
-
+ tree->connect("cell_selected",this,"_dir_selected");
+
+ files = memnew( ItemList );
+ files->set_v_size_flags(SIZE_EXPAND_FILL);
+ files->set_select_mode(ItemList::SELECT_MULTI);
+
+ path_hb = memnew( HBoxContainer );
+ button_back = memnew( ToolButton );
+ path_hb->add_child(button_back);
+ current_path=memnew( LineEdit );
+ current_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ path_hb->add_child(current_path);
+ display_mode = memnew( ToolButton );
+ path_hb->add_child(display_mode);
+ display_mode->set_toggle_mode(true);
+ add_child(path_hb);
+ path_hb->hide();
+
+
+ add_child(files);
+ files->hide();
+
+ scanning_vb = memnew( VBoxContainer );
+ Label *slabel = memnew( Label );
+ slabel->set_text("Scanning Files,\nPlease Wait..");
+ slabel->set_align(Label::ALIGN_CENTER);
+ scanning_vb->add_child(slabel);
+ scanning_progress = memnew( ProgressBar );
+ scanning_vb->add_child(scanning_progress);
+ add_child(scanning_vb);
+ scanning_vb->hide();
+
+
+
+ deps_editor = memnew( DependencyEditor );
+ add_child(deps_editor);
+
+ owners_editor = memnew( DependencyEditorOwners);
+ add_child(owners_editor);
+
+ remove_dialog = memnew( DependencyRemoveDialog);
+ add_child(remove_dialog);
+
+ move_dialog = memnew( EditorDirDialog );
+ add_child(move_dialog);
+ move_dialog->connect("dir_selected",this,"_move_operation");
+ move_dialog->get_ok()->set_text("Move");
+
+ rename_dialog = memnew( EditorFileDialog );
+ rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ rename_dialog->connect("file_selected",this,"_rename_operation");
+ add_child(rename_dialog);
updating_tree=false;
+ initialized=false;
-}
-
-ScenesDock::~ScenesDock() {
-
-}
-
-void ScenesDockFilter::_setup_filters() {
-
- filter_option->clear();
- filter_option->add_item("Path");
- filter_option->add_item("Name");
- filter_option->add_item("Folder");
-#if 0
- 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+" )");
- }
-#endif
-}
-
-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();
-}
-
-ScenesDockFilter::FilterOption ScenesDockFilter::get_file_filter() {
- return _current_filter;
-}
-
-void ScenesDockFilter::_file_filter_selected(int p_idx) {
- FilterOption selected = (FilterOption)(filter_option->get_selected());
- if (_current_filter != selected ) {
- _current_filter = selected;
- emit_signal("filter_changed");
- }
-}
-
-void ScenesDockFilter::_notification(int p_what) {
- switch(p_what) {
- case NOTIFICATION_ENTER_TREE: {
- clear_search_button->set_icon(get_icon("CloseHover","EditorIcons"));
- } break;
- }
-}
-
-void ScenesDockFilter::_bind_methods() {
+ history.push_back("res://");
+ history_pos=0;
+ tree_mode=true;
- 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() {
-
- _current_filter = FILTER_PATH;
-
- filter_option = memnew( OptionButton );
- filter_option->set_custom_minimum_size(Size2(60,10));
- filter_option->set_clip_text(true);
- filter_option->connect("item_selected", this, "_file_filter_selected");
- add_child(filter_option);
-
- _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( ToolButton );
- clear_search_button->connect("pressed",this,"_command",make_binds(CMD_CLEAR_FILTER));
- add_child(clear_search_button);
+ScenesDock::~ScenesDock() {
}
diff --git a/tools/editor/scenes_dock.h b/tools/editor/scenes_dock.h
index de7ab51edc..d045124bf7 100644
--- a/tools/editor/scenes_dock.h
+++ b/tools/editor/scenes_dock.h
@@ -36,40 +36,112 @@
#include "scene/gui/tool_button.h"
#include "scene/gui/option_button.h"
#include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/progress_bar.h"
+
#include "os/dir_access.h"
#include "os/thread.h"
#include "editor_file_system.h"
-
+#include "editor_dir_dialog.h"
+#include "dependency_editor.h"
class EditorNode;
-class ScenesDockFilter;
+
class ScenesDock : public VBoxContainer {
OBJ_TYPE( ScenesDock, VBoxContainer );
+ enum FileMenu {
+ FILE_DEPENDENCIES,
+ FILE_OWNERS,
+ FILE_MOVE,
+ FILE_REMOVE,
+ FILE_REIMPORT,
+ FILE_INFO
+ };
+
+
+ VBoxContainer *scanning_vb;
+ ProgressBar *scanning_progress;
+
EditorNode *editor;
Set<String> favorites;
Button *button_reload;
Button *button_instance;
Button *button_favorite;
+ Button *button_fav_up;
+ Button *button_fav_down;
Button *button_open;
- Timer *timer;
+ Button *button_back;
+ Button *display_mode;
+ Button *button_hist_next;
+ Button *button_hist_prev;
+ LineEdit *current_path;
+ HBoxContainer *path_hb;
+
+ MenuButton *file_options;
+
+
+ DependencyEditor *deps_editor;
+ DependencyEditorOwners *owners_editor;
+ DependencyRemoveDialog *remove_dialog;
+
+ EditorDirDialog *move_dialog;
+ EditorFileDialog *rename_dialog;
- ScenesDockFilter *tree_filter;
+ Vector<String> move_dirs;
+ Vector<String> move_files;
+
+
+ Vector<String> history;
+ int history_pos;
+
+ String path;
+
+ bool initialized;
bool updating_tree;
- Tree * tree;
+ Tree * tree; //directories
+ ItemList *files;
+
+ bool tree_mode;
+
+ void _go_to_tree();
+ void _go_to_dir(const String& p_dir);
+ void _select_file(int p_idx);
+
bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
+ void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata);
+ void _find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files);
+ void _find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps);
+
+ void _rename_operation(const String& p_to_path);
+ void _move_operation(const String& p_to_path);
+
+
+ void _file_option(int p_option);
+ void _update_files(bool p_keep_selection);
+ void _change_file_display();
+ void _fs_changed();
+ void _fw_history();
+ void _bw_history();
+ void _push_to_history();
+
+ void _fav_up_pressed();
+ void _fav_down_pressed();
+ void _dir_selected();
void _update_tree();
void _rescan();
- void _favorites_toggled(bool);
- void _favorite_toggled();
+ void _set_scannig_mode();
+
+ void _favorites_pressed();
void _instance_pressed();
void _open_pressed();
- void _save_favorites();
+
protected:
void _notification(int p_what);
@@ -77,48 +149,14 @@ protected:
public:
String get_selected_path() const;
+ void open(const String& p_path);
+
+ void fix_dependencies(const String& p_for_file);
+
ScenesDock(EditorNode *p_editor);
~ScenesDock();
};
-class ScenesDockFilter : public HBoxContainer {
-
- OBJ_TYPE( ScenesDockFilter, HBoxContainer );
-
-private:
- friend class ScenesDock;
-
- enum Command {
- CMD_CLEAR_FILTER,
- };
-
- Tree *tree;
- OptionButton *filter_option;
- LineEdit *search_box;
- ToolButton *clear_search_button;
-
- enum FilterOption {
- FILTER_PATH, // NAME or Folder
- FILTER_NAME,
- FILTER_FOLDER,
- };
- FilterOption _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:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- String get_search_term();
- FilterOption get_file_filter();
- ScenesDockFilter();
-};
#endif // SCENES_DOCK_H
diff --git a/tools/editor/spatial_editor_gizmos.h b/tools/editor/spatial_editor_gizmos.h
index 8d6730e2f1..02f60db7f8 100644
--- a/tools/editor/spatial_editor_gizmos.h
+++ b/tools/editor/spatial_editor_gizmos.h
@@ -201,6 +201,8 @@ public:
};
+
+
class SpatialPlayerSpatialGizmo : public SpatialGizmoTool {
OBJ_TYPE(SpatialPlayerSpatialGizmo,SpatialGizmoTool);
@@ -214,6 +216,8 @@ public:
};
+
+
class TestCubeSpatialGizmo : public SpatialGizmoTool {
OBJ_TYPE(TestCubeSpatialGizmo,SpatialGizmoTool);
diff --git a/tools/html_fs/godot.html b/tools/html_fs/godot.html
new file mode 100644
index 0000000000..36761deb90
--- /dev/null
+++ b/tools/html_fs/godot.html
@@ -0,0 +1,1317 @@
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Emscripten-Generated Code</title>
+ <style>
+ body {
+ font-family: arial;
+ margin: 0;
+ padding: none;
+ }
+
+ .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+ div.emscripten { text-align: center; }
+ div.emscripten_border { border: 1px solid black; }
+ /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
+ canvas.emscripten { border: 0px none; }
+
+ #emscripten_logo {
+ display: inline-block;
+ margin: 0;
+ }
+
+ .spinner {
+ height: 30px;
+ width: 30px;
+ margin: 0;
+ margin-top: 20px;
+ margin-left: 20px;
+ display: inline-block;
+ vertical-align: top;
+
+ -webkit-animation: rotation .8s linear infinite;
+ -moz-animation: rotation .8s linear infinite;
+ -o-animation: rotation .8s linear infinite;
+ animation: rotation 0.8s linear infinite;
+
+ border-left: 5px solid rgb(235, 235, 235);
+ border-right: 5px solid rgb(235, 235, 235);
+ border-bottom: 5px solid rgb(235, 235, 235);
+ border-top: 5px solid rgb(120, 120, 120);
+
+ border-radius: 100%;
+ background-color: rgb(189, 215, 46);
+ }
+
+ @-webkit-keyframes rotation {
+ from {-webkit-transform: rotate(0deg);}
+ to {-webkit-transform: rotate(360deg);}
+ }
+ @-moz-keyframes rotation {
+ from {-moz-transform: rotate(0deg);}
+ to {-moz-transform: rotate(360deg);}
+ }
+ @-o-keyframes rotation {
+ from {-o-transform: rotate(0deg);}
+ to {-o-transform: rotate(360deg);}
+ }
+ @keyframes rotation {
+ from {transform: rotate(0deg);}
+ to {transform: rotate(360deg);}
+ }
+
+ #status {
+ display: inline-block;
+ vertical-align: top;
+ margin-top: 30px;
+ margin-left: 20px;
+ font-weight: bold;
+ color: rgb(120, 120, 120);
+ }
+
+ #progress {
+ height: 20px;
+ width: 30px;
+ }
+
+ #controls {
+ display: inline-block;
+ float: right;
+ vertical-align: top;
+ margin-top: 30px;
+ margin-right: 20px;
+ }
+
+ #output {
+ width: 100%;
+ height: 200px;
+ margin: 0 auto;
+ margin-top: 10px;
+ display: block;
+ background-color: black;
+ color: white;
+ font-family: 'Lucida Console', Monaco, monospace;
+ outline: none;
+ }
+ </style>
+ </head>
+ <body>
+ <a href="http://emscripten.org">
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="296px"
+ height="78px"
+ viewBox="420 120 100 170"
+ enable-background="new 0 0 900 400"
+ xml:space="preserve"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="emscripten_powered_by_logo.svg"><metadata
+ id="metadata345"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs343"><linearGradient
+ y2="247.6265"
+ x2="225.1929"
+ y1="152.499"
+ x1="225.1929"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5104"><stop
+ id="stop5106"
+ style="stop-color:#C1D72F"
+ offset="0.3227531" /><stop
+ id="stop5108"
+ style="stop-color:#BCD631"
+ offset="0.45119295" /><stop
+ id="stop5110"
+ style="stop-color:#AFD136"
+ offset="0.64491969" /><stop
+ id="stop5112"
+ style="stop-color:#ABD037"
+ offset="1" /><a:midPointStop
+ style="stop-color:#C1D72F"
+ offset="0.0123" /><a:midPointStop
+ style="stop-color:#C1D72F"
+ offset="0.3086" /><a:midPointStop
+ style="stop-color:#ABD037"
+ offset="1" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ xlink:href="#SVGID_2_"
+ id="linearGradient5120"
+ x1="397.56918"
+ y1="128.12726"
+ x2="397.56918"
+ y2="166.25996"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.103059,0,0,1.103059,-38.997823,3.1312145)" /><filter
+ inkscape:collect="always"
+ id="filter5126"><feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.56377237"
+ id="feGaussianBlur5128" /></filter><linearGradient
+ inkscape:collect="always"
+ xlink:href="#SVGID_2_"
+ id="linearGradient5134"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.103059,0,0,1.103059,-38.997823,3.1312145)"
+ x1="397.56918"
+ y1="128.12726"
+ x2="397.56918"
+ y2="166.25996" /></defs><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1440"
+ inkscape:window-height="838"
+ id="namedview341"
+ showgrid="false"
+ inkscape:zoom="0.63555556"
+ inkscape:cx="224.82424"
+ inkscape:cy="-52.085109"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1" /><g
+ id="g5130"
+ transform="matrix(0.91591318,0,0,0.91591318,28.176953,14.143571)"><path
+ transform="matrix(1.103059,0,0,1.103059,-35.073492,-16.03923)"
+ id="path5122"
+ style="fill:#383838;fill-opacity:0.34705882;stroke:none;filter:url(#filter5126)"
+ d="m 494.39333,173.6323 c 0.57407,0.28703 1.87073,1.00226 2.89426,1.02855 0.55732,0.0143 1.14006,-0.1672 1.60262,-0.4784 1.20466,-0.81046 2.23561,-2.03031 2.72683,-3.39661 0.19424,-0.54027 0.0238,-1.72222 0.0238,-1.72222 l -3.82713,-14.06478 -1.98533,0 0.50231,-2.67891 6.36261,0 2.55939,12.22285 4.78392,-9.68746 -2.00924,0 0,-2.65498 7.19979,0 -11.00301,22.38875 -1.69829,1.91358 -2.29628,1.3395 -2.46371,0.26312 -2.29628,-0.21528 -2.79859,-1.36342 z m -12.0637,-14.56445 c -0.93698,1.88565 -1.70261,4.35262 -0.81842,6.26333 0.36549,0.78976 1.35098,1.19428 2.192,1.41737 0.60934,0.16133 1.29167,0.0999 1.88775,-0.10468 0.48126,-0.1655 0.8829,-0.5224 1.255,-0.8697 0.40341,-0.3768 0.77723,-0.80461 1.03505,-1.29262 0.21864,-0.41395 0.40236,-0.84786 0.49325,-1.30698 0.20667,-1.0485 0.35879,-2.1079 0.33583,-3.17631 -0.0184,-0.87403 -0.0789,-1.87107 -0.47711,-2.64959 -0.26344,-0.51379 -0.77017,-0.71849 -1.33113,-0.85633 -0.42395,-0.10479 -0.81432,-0.0626 -1.21773,0.10517 -0.65479,0.27273 -1.2544,0.5311 -1.82112,0.95764 -0.57331,0.4317 -1.21403,0.86959 -1.53337,1.5127 z m 0.65588,-4.31208 c 0,0 2.19341,-1.80738 3.45549,-2.27082 0.71718,-0.26365 3.45363,-0.65258 4.15,-0.3378 1.47292,0.66633 2.26103,1.57529 2.7222,2.60001 0.46118,1.02472 0.69944,2.59956 0.79701,3.73627 0.13278,1.55027 -0.13682,3.77629 -0.53404,5.74843 -0.30079,1.49256 -1.01883,2.74423 -1.83478,3.92156 -1.06526,1.5373 -1.82382,2.15116 -3.66756,2.46594 -0.98864,0.16889 -1.93845,0.46787 -3.25466,0.0928 -1.4384,-0.40963 -2.35273,-0.81244 -3.39599,-1.63337 -0.72524,-0.57054 -1.16043,-1.54043 -1.16043,-1.54043 l 0,2.82636 -4.8903,0 3.39872,-23.01602 -1.92242,-0.85888 0.0403,-2.38127 7.25847,0.0534 z m -23.77803,2.20447 c 0.29175,1.49273 0.0813,4.83252 -0.86111,6.69751 -0.3062,0.60617 -0.94813,1.32967 -1.55479,1.6983 -1.01515,0.61713 -2.21688,1.21322 -3.3966,1.07639 -0.47944,-0.0541 -0.97036,-0.34348 -1.24383,-0.74151 -0.47686,-0.69328 -0.43621,-1.55032 -0.45448,-2.39198 -0.024,-1.06873 0.13137,-2.23775 0.38272,-3.277 0.18705,-0.7744 0.4229,-1.58254 0.86111,-2.24844 0.39037,-0.59323 0.92628,-1.12617 1.55478,-1.45909 0.54854,-0.29014 1.19695,-0.38467 1.81791,-0.40664 0.63637,-0.0231 1.3031,0.0385 1.88966,0.28704 0.3875,0.16453 0.92361,0.3524 1.00463,0.76542 z m 1.29312,-9.69052 -0.64254,6.12262 c 0,0 -1.68393,-0.96858 -2.605,-1.25148 -0.73032,-0.22434 -1.50312,-0.36654 -2.26624,-0.33838 -0.97069,0.0345 -1.91182,0.22099 -2.81751,0.57088 -0.9185,0.35497 -1.78344,0.94565 -2.49338,1.62792 -0.88025,0.84538 -1.51404,1.90455 -2.02977,3.0106 -0.39653,0.84993 -0.69517,1.75284 -0.87975,2.67232 -0.22875,1.14241 -0.44415,2.38719 -0.43937,3.55197 0.01,1.44865 0.0623,2.89489 0.54092,4.26214 0.25525,0.72907 0.71643,1.40578 1.28572,1.9283 0.56835,0.52207 1.29566,0.87604 2.02935,1.11621 0.41072,0.13491 0.85346,0.17274 1.28579,0.16935 1.00285,-0.01 2.03715,-0.0883 2.97671,-0.43999 0.66497,-0.2489 1.21759,-0.73399 1.79298,-1.1502 0.75304,-0.54475 2.16476,-1.86006 2.16476,-1.86006 l 0,1.62374 -0.5751,0 0,1.48807 6.86709,0 0,-2.84135 -1.92841,0 3.21374,-23.57782 -7.37422,0 0,2.33412 z m -93.60062,7.55781 2.33363,15.57933 6.23084,0 4.04243,-11.34169 1.62654,11.34169 5.88425,0 7.05633,-16.38872 0,-2.0141 -6.1713,0 0,2.82349 1.88966,0 -4.04243,10.16973 -0.74151,0 -1.29167,-12.55773 -5.38194,0 -4.7361,12.50989 -1.55478,-12.94538 -6.86496,0 0,2.82349 z m -12.15,0.72146 c -0.56264,0.0892 -1.03524,0.17358 -1.53086,0.45447 -0.737,0.41808 -1.46132,0.95771 -1.91357,1.67437 -0.44123,0.70048 -0.53204,1.57581 -0.66975,2.39196 -0.1751,1.04003 -0.20064,2.10306 -0.19136,3.15741 0.01,0.81614 -0.0138,1.66577 0.35879,2.39197 0.1904,0.37315 0.52874,0.80945 0.88503,1.02855 0.56015,0.34453 1.06632,0.55494 1.72222,0.598 0.72597,0.0483 1.48801,-0.18852 2.10493,-0.57408 0.59422,-0.37072 1.03334,-0.97401 1.38735,-1.5787 0.46117,-0.78744 0.70905,-1.69257 0.90895,-2.58334 0.20377,-0.90704 0.33579,-1.84565 0.28703,-2.77468 -0.0491,-0.92714 -0.18211,-1.88434 -0.57407,-2.72684 -0.2728,-0.58681 -0.70954,-1.00753 -1.29166,-1.29165 -0.44403,-0.21628 -0.99455,-0.24402 -1.48303,-0.16744 z m -6.62442,-0.73581 c 0.65404,-0.6664 1.4072,-1.25479 2.23273,-1.69161 1.0305,-0.54505 2.16429,-0.92749 3.31518,-1.11604 1.51307,-0.24806 3.09342,-0.2847 4.60036,0 0.88055,0.16632 1.78322,0.44742 2.50307,0.98113 0.77409,0.57312 1.35279,1.40936 1.79291,2.26639 0.42901,0.83457 0.6828,1.77223 0.77798,2.70605 0.16564,1.61985 0.024,3.29135 -0.37201,4.87103 -0.33328,1.33759 -0.88436,2.64754 -1.65745,3.78889 -0.67549,0.99679 -1.52894,1.91262 -2.53721,2.5709 -0.89957,0.58746 -1.9718,0.87641 -3.01035,1.15006 -0.87153,0.22963 -1.77166,0.4095 -2.67235,0.40576 -1.21068,-0.01 -2.47998,-0.0817 -3.58589,-0.57511 -1.09854,-0.48896 -1.89728,-1.32739 -2.60455,-2.30013 -0.61123,-0.83995 -1.02561,-1.59975 -1.31932,-2.87516 -0.2125,-0.9233 -0.40006,-2.19912 -0.37215,-3.14592 0.0335,-1.16537 0.3568,-2.74121 0.83416,-3.80434 0.52547,-1.17098 1.17609,-2.3161 2.07489,-3.2319 z m 94.95184,13.82318 c -2.20516,1.01761 -4.61429,1.69636 -7.02343,1.69636 -5.32726,0 -7.22678,-3.12145 -7.22678,-7.22678 0,-7.1251 4.54685,-11.19645 10.0772,-11.19645 3.7324,0 5.56453,1.69625 5.56453,4.47856 0,4.85189 -5.12329,6.27735 -10.41633,6.82001 0.10168,1.73076 0.81446,3.32485 3.3592,3.32485 1.2218,0 2.88401,-0.37315 4.91982,-1.22099 z m -3.22292,-11.77374 c 0,-0.81423 -0.57695,-1.28891 -1.62876,-1.28891 -1.89988,0 -3.46041,1.66212 -3.96978,4.34287 1.45897,-0.20368 5.59854,-0.91613 5.59854,-3.05396 z m -30.33408,11.77374 c -2.2054,1.01761 -4.61457,1.69636 -7.02371,1.69636 -5.32653,0 -7.22671,-3.12145 -7.22671,-7.22678 0,-7.1251 4.54679,-11.19645 10.07785,-11.19645 3.73175,0 5.56382,1.69625 5.56382,4.47856 0,4.85189 -5.12273,6.27735 -10.41568,6.82001 0.10142,1.73076 0.81422,3.32485 3.35884,3.32485 1.22158,0 2.8842,-0.37315 4.91994,-1.22099 z m -3.22305,-11.77374 c 0,-0.81423 -0.57638,-1.28891 -1.62883,-1.28891 -1.89959,0 -3.46023,1.66212 -3.96971,4.34287 1.4591,-0.20368 5.59854,-0.91613 5.59854,-3.05396 z m -82.36051,20.5268 -0.0679,-0.13571 0.98406,-5.66614 2.10303,-15.16698 c 0.0687,-0.40664 -0.0332,-0.61046 -0.30522,-0.71214 l -1.66259,-0.61111 0.37379,-2.57855 6.78556,0 -0.40663,2.71427 0.10142,0.0335 c 2.0016,-1.86631 4.10566,-3.08743 6.24306,-3.08743 2.91821,0 4.95366,1.86577 4.95366,6.78561 0,4.68241 -1.83206,11.6379 -8.14271,11.6379 -2.20534,0 -3.42694,-0.84825 -4.68256,-1.73039 l -0.74621,5.08917 c -0.0341,0.37361 0.0326,0.50898 0.47457,0.54273 l 3.42697,0.33969 -0.37385,2.5447 -9.0589,0 z m 6.78613,-12.04485 c 0.84787,0.71258 1.96788,1.32305 3.22348,1.32305 2.74798,0 3.76601,-3.86811 3.76601,-6.85368 0,-2.002 -0.47476,-3.32542 -1.76432,-3.32542 -1.35696,0 -3.08763,1.4591 -4.30913,2.54506 z m 81.08934,4.85147 0.33969,-2.54464 1.56064,-0.2038 c 0.47498,-0.0683 0.5429,-0.1695 0.61084,-0.67837 l 1.42466,-10.34864 c 0.0335,-0.37315 -0.0335,-0.61046 -0.33914,-0.71214 l -1.69691,-0.61111 0.37365,-2.57855 6.71797,0 -0.44097,3.05395 0.10191,0.0679 c 1.32326,-1.89982 3.22359,-3.46042 5.39485,-3.46042 0.7463,0 2.0359,0.13582 2.61295,0.30538 l -0.84863,6.17508 -3.96972,-0.13582 -0.10157,-1.76443 c -0.0335,-0.30537 -0.10223,-0.40701 -0.37391,-0.40701 -0.64452,0 -1.69636,0.78027 -2.64651,1.76455 l -1.18674,8.61817 c -0.0687,0.54303 -0.0334,0.64474 0.47477,0.67874 l 3.22351,0.27142 -0.37384,2.51081 -10.8575,0 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssscccccccccccccccccssssssssccssscssssscsssccccccccsssssssssccsccsssssssssscsscccccccccccccccccccccccccccccccsssscsssssscscsssssssscsssssssssscsssscsccsscscsssscsccsscsccccccccccsssccccccccssscccccccccccccsccccsccccccc" /><path
+ sodipodi:nodetypes="cssscccccccccccccccccssssssssccssscssssscsssccccccccsssssssssccsccsssssssssscsscccccccccccccccccccccccccccccccsssscsssssscscsssssssscsssssssssscsssscsccsscscsssscsccsscsccccccccccsssccccccccssscccccccccccccsccccsccccccc"
+ inkscape:connector-curvature="0"
+ d="m 509.55935,174.26011 c 0.63327,0.31663 2.06355,1.10555 3.19256,1.13455 0.61476,0.0158 1.25757,-0.18443 1.76781,-0.5277 1.3288,-0.89397 2.46618,-2.23946 3.00784,-3.74661 0.21419,-0.59598 0.0258,-1.89972 0.0258,-1.89972 l -4.22153,-15.51428 -2.18993,0 0.55406,-2.95501 7.01835,0 2.82313,13.48255 5.27696,-10.68586 -2.21631,0 0,-2.92858 7.94179,0 -12.13698,24.69605 -1.87332,2.11078 -2.5329,1.4776 -2.71762,0.29022 -2.53295,-0.23748 -3.08699,-1.50392 z m -13.30698,-16.06545 c -1.0335,2.08005 -1.87803,4.80122 -0.90274,6.90883 0.4032,0.87116 1.49018,1.31738 2.4179,1.56347 0.67214,0.17793 1.42477,0.1102 2.08233,-0.11548 0.53084,-0.1826 0.97383,-0.5762 1.38432,-0.9593 0.44502,-0.4157 0.85733,-0.8875 1.14176,-1.42582 0.24113,-0.45665 0.44375,-0.93526 0.54404,-1.44168 0.22797,-1.1566 0.3958,-2.3252 0.37043,-3.50371 -0.0204,-0.96413 -0.0869,-2.06387 -0.52631,-2.92259 -0.29054,-0.56679 -0.84946,-0.79259 -1.46826,-0.94463 -0.46761,-0.11559 -0.89829,-0.0686 -1.34322,0.11597 -0.72226,0.30083 -1.38368,0.5859 -2.00879,1.05634 -0.63242,0.4762 -1.33915,0.9593 -1.69146,1.6686 z m 0.72346,-4.75648 c 0,0 2.41951,-1.99358 3.81169,-2.50482 0.79109,-0.29085 3.80953,-0.71977 4.57766,-0.3726 1.6247,0.73503 2.49408,1.73759 3.00274,2.86791 0.50868,1.13043 0.77154,2.86756 0.87911,4.12137 0.14648,1.71007 -0.15092,4.16549 -0.58904,6.34083 -0.33179,1.64636 -1.12383,3.02703 -2.02388,4.32576 -1.17506,1.6957 -2.01178,2.37286 -4.04556,2.72004 -1.09051,0.18629 -2.13814,0.51607 -3.59006,0.10268 -1.5866,-0.45183 -2.59522,-0.89615 -3.74599,-1.8017 -0.79994,-0.62933 -1.28003,-1.6992 -1.28003,-1.6992 l 0,3.11766 -5.39426,0 3.74898,-25.38802 -2.12052,-0.94738 0.0443,-2.62669 8.00657,0.0587 z m -26.22853,2.43167 c 0.32185,1.64663 0.0893,5.33062 -0.9498,7.38781 -0.33781,0.66857 -1.04588,1.46667 -1.7151,1.8733 -1.11975,0.68073 -2.44527,1.33822 -3.7466,1.18729 -0.52883,-0.0601 -1.07036,-0.37888 -1.37203,-0.81791 -0.52601,-0.76478 -0.48121,-1.71012 -0.50128,-2.63848 -0.0263,-1.17893 0.14487,-2.46835 0.42212,-3.6147 0.20635,-0.8543 0.4665,-1.74564 0.94981,-2.48024 0.43067,-0.65433 1.02178,-1.24217 1.71508,-1.60939 0.60504,-0.32004 1.32025,-0.42437 2.00521,-0.44854 0.70197,-0.0251 1.4374,0.0425 2.08446,0.31654 0.4274,0.18153 1.01882,0.3888 1.10813,0.84432 z m 1.42642,-10.68922 -0.70874,6.75362 c 0,0 -1.85753,-1.06838 -2.8735,-1.38048 -0.80562,-0.24744 -1.65802,-0.40424 -2.49984,-0.37318 -1.07069,0.0382 -2.10882,0.24369 -3.1078,0.62968 -1.01321,0.39157 -1.96724,1.04315 -2.75039,1.79572 -0.97095,0.93248 -1.67003,2.10085 -2.23897,3.3208 -0.43738,0.93753 -0.76677,1.93354 -0.9704,2.94777 -0.2523,1.26016 -0.4899,2.63324 -0.48461,3.91802 0.011,1.59795 0.0683,3.19329 0.59661,4.70144 0.28155,0.80417 0.79028,1.55058 1.41822,2.127 0.62695,0.57587 1.4292,0.96634 2.23856,1.23121 0.45301,0.14881 0.94135,0.19054 1.41828,0.18685 1.10615,-0.011 2.24705,-0.0973 3.28346,-0.48539 0.73352,-0.2745 1.34304,-0.80959 1.97773,-1.2687 0.83064,-0.60085 2.38786,-2.05176 2.38786,-2.05176 l 0,1.79104 -0.63429,0 0,1.64147 7.57478,0 0,-3.13415 -2.12721,0 3.54494,-26.00772 -8.13411,0 0,2.57462 z m -103.24702,8.33671 2.57413,17.18493 6.87304,0 4.45903,-12.51049 1.79414,12.51049 6.49065,0 7.78353,-18.07772 0,-2.2217 -6.8073,0 0,3.11449 2.08446,0 -4.45903,11.21783 -0.8179,0 -1.42488,-13.85193 -5.93654,0 -5.2242,13.79919 -1.71497,-14.27958 -7.57246,0 0,3.11449 z m -13.4021,0.79586 c -0.62064,0.0982 -1.14194,0.19148 -1.68866,0.50127 -0.813,0.46118 -1.61192,1.05641 -2.11077,1.84697 -0.48673,0.77268 -0.58683,1.73821 -0.73875,2.63846 -0.1932,1.14723 -0.22134,2.31976 -0.21116,3.48281 0.011,0.90024 -0.0148,1.83747 0.39579,2.63847 0.21,0.41165 0.58324,0.89285 0.97623,1.13455 0.61796,0.38003 1.17622,0.61214 1.89972,0.6596 0.80077,0.0533 1.64141,-0.20792 2.32189,-0.63318 0.65546,-0.40892 1.13978,-1.07441 1.53029,-1.7414 0.50878,-0.86864 0.78215,-1.86707 1.00265,-2.84964 0.22477,-1.00044 0.37039,-2.03585 0.31663,-3.06058 -0.0541,-1.02274 -0.20091,-2.07854 -0.63327,-3.00784 -0.3009,-0.64731 -0.78264,-1.11143 -1.42476,-1.42485 -0.48983,-0.23858 -1.09705,-0.26912 -1.63583,-0.18464 z m -7.30711,-0.81171 c 0.72143,-0.735 1.55219,-1.38409 2.46282,-1.86591 1.1367,-0.60125 2.38729,-1.02309 3.65678,-1.23104 1.66908,-0.27366 3.41222,-0.314 5.07446,0 0.97135,0.18342 1.96702,0.49352 2.76107,1.08223 0.85389,0.63222 1.49219,1.55466 1.97771,2.49999 0.47321,0.92057 0.7531,1.95483 0.85808,2.98495 0.18274,1.78675 0.0263,3.63055 -0.41031,5.37303 -0.36757,1.47539 -0.97545,2.92034 -1.82825,4.17929 -0.74509,1.09959 -1.68654,2.10982 -2.79871,2.8359 -0.99227,0.64796 -2.175,0.96671 -3.32055,1.26856 -0.96139,0.25333 -1.95426,0.4517 -2.94774,0.44756 -1.33549,-0.011 -2.73559,-0.0897 -3.9555,-0.63431 -1.21174,-0.53936 -2.09278,-1.46419 -2.87295,-2.53723 -0.67423,-0.92645 -1.13131,-1.76457 -1.45532,-3.17146 -0.2344,-1.0184 -0.44126,-2.42572 -0.41044,-3.47012 0.0365,-1.28547 0.39349,-3.02371 0.92005,-4.19644 0.57967,-1.29168 1.29729,-2.5548 2.2888,-3.565 z m 104.73744,15.24778 c -2.43247,1.12251 -5.0899,1.87126 -7.74734,1.87126 -5.87626,0 -7.97147,-3.44315 -7.97147,-7.97158 0,-7.8594 5.0154,-12.35035 11.11569,-12.35035 4.11711,0 6.13803,1.87105 6.13803,4.94016 0,5.35189 -5.65129,6.92425 -11.48983,7.52281 0.11219,1.90916 0.89836,3.66755 3.7054,3.66755 1.3477,0 3.18121,-0.41165 5.42682,-1.34689 z m -3.55513,-12.98704 c 0,-0.89823 -0.63635,-1.42181 -1.79655,-1.42181 -2.09568,0 -3.81712,1.83342 -4.37899,4.79047 1.60937,-0.22468 6.17554,-1.01053 6.17554,-3.36866 z m -33.46028,12.98704 c -2.4327,1.12251 -5.09006,1.87126 -7.74751,1.87126 -5.87553,0 -7.97151,-3.44315 -7.97151,-7.97158 0,-7.8594 5.01539,-12.35035 11.11645,-12.35035 4.11635,0 6.13722,1.87105 6.13722,4.94016 0,5.35189 -5.65062,6.92425 -11.48908,7.52281 0.11182,1.90916 0.89812,3.66755 3.70494,3.66755 1.34748,0 3.1815,-0.41165 5.42704,-1.34689 z m -3.55514,-12.98704 c 0,-0.89823 -0.63578,-1.42181 -1.79674,-1.42181 -2.09539,0 -3.81683,1.83342 -4.37881,4.79047 1.60951,-0.22468 6.17555,-1.01053 6.17555,-3.36866 z m -90.84852,22.6422 -0.0749,-0.14971 1.08546,-6.25004 2.31984,-16.73008 c 0.0757,-0.44854 -0.0367,-0.67336 -0.33673,-0.78554 l -1.83388,-0.67411 0.41228,-2.84425 7.48486,0 -0.44853,2.99397 0.11182,0.0371 c 2.2079,-2.05871 4.52887,-3.40563 6.88646,-3.40563 3.21901,0 5.46427,2.05807 5.46427,7.48491 0,5.16501 -2.02094,12.8373 -8.98192,12.8373 -2.43264,0 -3.78014,-0.93565 -5.16516,-1.90869 l -0.82311,5.61357 c -0.0376,0.41212 0.0356,0.56148 0.52347,0.59873 l 3.78017,0.37469 -0.41234,2.8069 -9.9925,0 z m 7.48553,-13.28615 c 0.93528,0.78598 2.17068,1.45946 3.55568,1.45946 3.03118,0 4.15411,-4.26682 4.15411,-7.56009 0,-2.2083 -0.52366,-3.66812 -1.94612,-3.66812 -1.49686,0 -3.40583,1.6095 -4.75323,2.80736 z m 89.44624,5.35147 0.37469,-2.80694 1.72154,-0.2248 c 0.52388,-0.0753 0.5988,-0.1869 0.67374,-0.74827 l 1.57152,-11.41514 c 0.0365,-0.41155 -0.0368,-0.67336 -0.3741,-0.78554 l -1.87181,-0.67411 0.41215,-2.84425 7.41037,0 -0.48647,3.36865 0.11241,0.0749 c 1.45966,-2.09562 3.55581,-3.81702 5.95085,-3.81702 0.8232,0 2.2457,0.14982 2.88225,0.33688 l -0.93613,6.81148 -4.37882,-0.14982 -0.11196,-1.94633 c -0.0371,-0.33677 -0.11284,-0.44891 -0.41252,-0.44891 -0.71092,0 -1.87116,0.86067 -2.91921,1.94635 l -1.30904,9.50637 c -0.0757,0.59903 -0.0368,0.71124 0.52367,0.74874 l 3.55571,0.29932 -0.41234,2.76961 -11.9765,0 z"
+ style="fill:url(#linearGradient5134);fill-opacity:1;stroke:none"
+ id="path5080" /></g><path
+ fill="#E2E2E2"
+ d="M256.023,135.437H196.36c-16.432,0-29.8,13.368-29.8,29.8v73.527c0,16.432,13.368,29.8,29.8,29.8h59.663 c16.433,0,29.801-13.368,29.801-29.8v-73.527C285.824,148.805,272.456,135.437,256.023,135.437z M191.561,165.236 c0-2.646,2.153-4.8,4.8-4.8h59.663c2.647,0,4.801,2.153,4.801,4.8v73.527c0,2.646-2.153,4.8-4.801,4.8H196.36 c-2.646,0-4.8-2.153-4.8-4.8V165.236z"
+ id="path3" /><path
+ d="m 531.664,250.155 h 18.498 l -2.809,18.064 h 5.59 37.586 l 2.6,-17.718 c 4.98,-1.091 9.133,-3.455 12.512,-6.693 3.084,4.075 8.566,7.37 18.252,7.37 6.338,0 12.775,-1.807 17.174,-3.687 4.254,2.399 9.463,3.687 15.459,3.687 3.088,0 6.236,-0.355 9.426,-1.023 h 67.135 l 3.354,-24.827 -5.445,-0.764 1.879,-13.356 c 0.371,-2.386 0.449,-4.66 0.449,-6.156 l -0.008,-0.375 c -0.457,-12.191 -8.139,-19.765 -20.045,-19.765 -2.404,0 -4.623,0.314 -6.676,0.852 h -34.189 l -0.035,0.244 c -2.527,-0.701 -5.41,-1.096 -8.686,-1.096 -3.801,0 -7.406,0.555 -10.76,1.598 l 0.105,-0.746 h -12.467 l 1.826,-12.951 H 615.08 l -1.846,7.658 c -1.373,5.704 -2.213,5.793 -4.453,6.03 l -4.508,0.477 c -3.049,-1.424 -6.357,-2.065 -9.602,-2.065 -2.135,0 -4.275,0.284 -6.416,0.852 h -19.291 c 0.502,-1.772 0.775,-3.674 0.775,-5.678 0,-9.601 -6.846,-16.305 -16.646,-16.305 -11.055,0 -18.775,7.721 -18.775,18.776 0,0.951 0.082,1.869 0.219,2.764 -2.135,-0.288 -4.277,-0.409 -5.553,-0.409 -2.053,0 -4.072,0.288 -6.045,0.852 h -31.342 c -2.74,-0.553 -5.641,-0.852 -8.537,-0.852 -7.138,0 -13.492,1.674 -18.808,4.723 l -3.451,-1.461 c -3.711,-1.571 -11.232,-3.262 -18.979,-3.262 -8.933,0 -16.383,2.56 -21.576,7.016 -3.265,-4.473 -8.523,-7.016 -15.228,-7.016 -4.822,0 -9.021,1.477 -12.572,3.44 -2.996,-2.204 -6.796,-3.44 -11.115,-3.44 -2.327,0 -4.48,0.315 -6.476,0.852 h -33.963 l -0.035,0.245 c -2.526,-0.702 -5.41,-1.097 -8.687,-1.097 -20.458,0 -35.307,16.031 -35.307,38.117 0,17.363 10.785,28.149 28.148,28.149 3.087,0 6.236,-0.356 9.426,-1.023 h 88.816 c 3.706,0.676 7.669,1.023 11.154,1.023 8.907,0 16.278,-2.375 21.51,-6.593 4.872,4.252 11.585,6.593 19.728,6.593 3.053,0 6.206,-0.368 9.286,-1.023 h 44.664 2.069 z"
+ id="path5"
+ inkscape:connector-curvature="0"
+ style="fill:#e2e2e2" /><path
+ fill="#F5F5F5"
+ d="M255.023,133.437H195.36c-16.432,0-29.8,13.368-29.8,29.8v73.527c0,16.432,13.368,29.8,29.8,29.8h59.663 c16.433,0,29.801-13.368,29.801-29.8v-73.527C284.824,146.805,271.456,133.437,255.023,133.437z M190.561,163.236 c0-2.646,2.153-4.8,4.8-4.8h59.663c2.647,0,4.801,2.153,4.801,4.8v73.527c0,2.646-2.153,4.8-4.801,4.8H195.36 c-2.646,0-4.8-2.153-4.8-4.8V163.236z"
+ id="path7" /><g
+ id="g9"><g
+ id="g11"><path
+ fill="#FBFDF8"
+ d="M195.361,251.626c-8.161,0-14.8-6.64-14.8-14.8v-73.527c0-8.161,6.639-14.8,14.8-14.8h59.663 c8.161,0,14.8,6.639,14.8,14.8v73.527c0,8.16-6.639,14.8-14.8,14.8H195.361z"
+ id="path13" /><path
+ fill="#F0F4E1"
+ d="M255.024,152.499c5.964,0,10.8,4.835,10.8,10.8v73.527c0,5.965-4.835,10.8-10.8,10.8h-59.663 c-5.964,0-10.8-4.835-10.8-10.8v-73.527c0-5.964,4.835-10.8,10.8-10.8H255.024 M255.024,144.499h-59.663 c-10.366,0-18.8,8.434-18.8,18.8v73.527c0,10.366,8.434,18.8,18.8,18.8h59.663c10.366,0,18.8-8.434,18.8-18.8v-73.527 C273.824,152.933,265.391,144.499,255.024,144.499L255.024,144.499z"
+ id="path15" /></g><defs
+ id="defs17"><filter
+ id="Adobe_OpacityMaskFilter"
+ filterUnits="userSpaceOnUse"
+ x="176.562"
+ y="144.499"
+ width="97.263"
+ height="111.127"><feColorMatrix
+ type="matrix"
+ values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
+ color-interpolation-filters="sRGB"
+ result="source"
+ id="feColorMatrix20" /></filter></defs><mask
+ maskUnits="userSpaceOnUse"
+ x="176.562"
+ y="144.499"
+ width="97.263"
+ height="111.127"
+ id="SVGID_1_"><g
+ filter="url(#Adobe_OpacityMaskFilter)"
+ id="g23"><image
+ overflow="visible"
+ width="422"
+ height="480"
+ xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEBLAEsAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA EAMCAwYAAAg2AAAQ4QAAF1b/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAeMBqQMBIgACEQEDEQH/ xACjAAEAAgMBAQAAAAAAAAAAAAAABQYBAwQHAgEBAQAAAAAAAAAAAAAAAAAAAAEQAAEDAQQKAwAC AwEAAAAAAAABAwQCMRMUBRBQEjMVJQYWNgcgESEwI5AiMkARAAEBAwsEAQIFAwUBAAAAAAABMQID EFAycqOz0wQ0RaURIXGRIEFRMGEiExRAgRKh0SMzQxUSAQAAAAAAAAAAAAAAAAAAAJD/2gAMAwEA AhEDEQAAANUJsrZYFfFgV8WBXxYEL0ki5fo6GjJuaRuaRuaRuaRuaRuaRuaRuaRuaRuaRuaRuaRu aRuaMHQ5dR3ojnJ9XxYFfFgV8WD0jxf2AodbslbAD6mDhlpLvI/qkuiovZL7CGzNfRCJwQacEGnB Bp0QSdEEnRBJ0QSdEEnRBJ3BBpwQacEHidwQXzPfBA6bBqK5w2nlKVH3iJitt+gAeweP+wFDrdkr Y+vmaN02k6+e3d2Gjo6N0c2zoyaM7xozuGluGluGluGluGluGluGluGluGluGluGluGnG8c/z1YO PVIfJF80xoIGPsfBVVrl6hIrD7+B7B4/7AUOt2StnXaYyxHTJ6ZKvrqb4x9MgAAAAAAAAAAAAAAA DGR8692Dh4pbkIKJscTVNiLdVY1+weP+wFDgJ+JLJORs3XbIc3dGz6ZAAAAAAAAAAAAAAAAAAAPn R0ayMi5uLqv1S51eIT2Dx/2AofB38Ra5uIm6kOzm6o+gAAAAAAAAAAAAAAAAAAAPj7+TkjJWNIOt 2et1WfYPH/YIofH2cZcJyEnKkenn6IyAAAAAAAAAAAAAAAAAAABjODmjZONIWt2WtVWPYPH/AGCK Hx9nIXGcg5ypLfo3xkAAAAAAAAAAAAAAAAAAADGcHPGyUaQ1astaqseweP8AsEUPk6+QuM7BTtSW 7TujIAAAAAAAAAAAAAAAAAAAGM4OeOkY4hqzZqzVY9g8f9gih8nXyFxnYKdqS3ad0ZAAAAAAAAAA AAAAAAAAAAxnBzx0jHENWbNWarHsHj/sEUPk6+QuM7BTtSW7TujIAAAAAAAAAAAAAAAAAAAGM4Oe OkY4hqzZqzVY9g8f9gih8nXyFxnYKdqS3ad0ZAAAAAAAAAAAAAAAAAAAAxnBzx0jHENWbNWarHsH j/sEUPk6+QuM7BTtSW7TujIAAAAAAAAAAAAAAAAAAAGM4OeOkY4hqzZqzVY9g8f9gih8nXyFxnYK dqS3ad0ZAAAAAAAAAAAAAAAAAAAAxnBzx0jHENWbNWarHsHj/sEUPk6+QuM7BTtSW7TujIAAAAAA AAAAAAAAAAAAAGM4OeOkY4hqzZqzVY9g8f8AYIofJ18hcZ2Cnakt2ndGQAAAAAAAAAAAAAAAAAAA MZwc8dIxxDVmzVmqx7B4/wCwRQ+Tr5C4zsFO1JbtO6MgAAAAAAAAAAAAAAAAAAAYzg546RjiGrNm rNVj2Dx/2CKHydfIXGdgp2pLdp3RkAAAAAAAAAAAAAAAAAAADGcHPHSMcQ1Zs1ZqseweP+wRQ+Tr 5C4zsFO1JbtO6MgAAAAAAAAAAAAAAAAAAAYzg546RjiGrNmrNVj2Dx/2CKHydfIXGdgp2pLdp3Rk AAAAAAAAAAAAAAAAAAADGcHPHSMcQ1Zs1ZqseweP+wRQ+Tr5C4zsFO1JbtO6MgAAAAAAAAAAAAAA AAAAAYzg546RjiGrNmrNVj2Dx/2CKHydfIXGdgp2pLdp3RkAAAAAAAAAAAAAAAAAAADGcHPHSMcQ 1Zs1ZqseweP+wRQ+Tr4y5TkHOVJb9G+MgAAAAAAAAAAAAAAAAAAAYzg542SjSGrVlrVVj2Dx/wBg ih8fZxlxnIKcqT6ObpjIAAAAAAAAAAAAAAAAAAAGM4OeNkY0h61Za1VY9g8f9gih8Xbwlxm4GbqW 6uLrj7AAAAAAAAAAAAAAAAAAAA+fr5OaNkI0ia1Y61Vb9g8f9gihxknCl1m65N1OdsZ3x0ZxkAAA AAAAAAAAAAAAAAAAx8fek5ozui6jazYKsRPsHj/sEUOu2Ktlqn6XZ6scjBSRLbOPpjYxkAAAAAAA AAAAAAAAAAYfJjm+uM0xXVE1xVOZr0Y9g8f9gKHW7JWz7s1W6i9SdYlasXXB9pLbI7fHY5/s3NeT 7fGT6fI+nyPp8j6fI+nyPp8j6fI+nyPp8j6fI+nyPp8D7x8fJtxp1m7Tp5jbw/MfWIjbXTk5SHsH j/sBQ63ZK2AdthqO8vXbUZWrJ0V/oJ7ZB7Sa+ofJMIkS6IySyJRLIkSyJEsiRLIkSyJEsiRLIkSy JVLYiRLYicEr8xfwSemN0kjy8PIdkfxQp0xWEAPYPH/YCh1uyVsAAz08ome2si37qZkumaULspIu 2aRkuyki7KSLspIuyki7KSLspIuyki7KSLtilC6qSLtilC6fNNFu5qz8k7wcI+vkAAHsHj/sBWoQ AAAAAAAAAAAAAAAAAAAAAAAAAHpAf//aAAgBAgABBQD/ACi//9oACAEDAAEFAP8AKL//2gAIAQEA AQUA6w6rz/LM+776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvv qs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qz vvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++qzvvqs776rO++ qzvvqs776rMfLPYHlHyRFUbivuDeUv1FOSVKJkRwE4CcAOAHADgBwA4AcAOAHADgBwA4AcAOAHAD gBwA4AcAOAHADgBwA4AcAOAnARciFyRUK8ndQcgyGxaaqf4fYHlHwRFUjZe68RsqbpGoKIUQkKYY kISEYJDAmBMCYEwJgTAmBMCYEwJgTAmBMCYEwJgTAmBMCYEwJgTAmCQWELCKoSFcNByEhIyxusk5 VVQV0VUL8vYHlGltupyqDlaIMREQaijcUoilMUSKgkZDDIYZDDIYZDDIYZDDIYZDDIYZDDIYZDDI YZDDIYZDDIYZDDIYZDDIYZDDIYZDDIYZDDILGQWKVRSuKORR2KPRCZltDiSYrjFXx9geUaG26nKs vy9KEjxhmONRxuOUMFLAjIjJdF0XRdIXSF0hdF0XRdF0XRdF0XRdF0XRdF0XRdIXSF0hdIXRdCsi sisFTBXHHY49GH4xMhU10y4tTFfw9geUCJ9rlcL6SNHGGBlgbZKGilsShDZQ+kPr/wBX0fSGygtC CtoVNDjI6wPsElgzCGjlLrdTden2B5QZfGvnYbCIkdkYZGmihsSn61ItJXQOtD7JIZJTBm0X6+Hs DyhP1cpjbLcVojtDLY3QIn1qZU+yugebJDRKaJ7CVUvtq27o9geURaLx6C19JFbI7Y1QU0/WqFQd oH6CS2TG/wAzZrZd0ewPKMqo2n4VH5FoGKBunVTifj9JJpJdBnVH+mj2B5RkqfdcOki0jFJQn5qm pPx5CTSS6TOKf6tHsDyjI0/2hIRU/GUKbNU1DyfklCWhm6f06PYHlGRf9QkIqfjKCWapWx4kkszj daPYHlGQ2wrItjImqlseJJMM43Wj2B5RkNsEjWNarUeJJMM43Oj2B5RkNsEjWNarUeJJMM43Oj2B 5RkNsGyLY1qtR6ySTDONzo9geUZDbBsi2NarUesk2TDON1o9geUZDbBsjWNarUesk2TDON1o9geU ZDbBsjWNarUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDb BsjWNarUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsj WNarUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNa rUeskkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUe skkwzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUeskk wzjdaPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUeskkwzj daPYHlGQ2wbI1jWq1HrJJMM43Wj2B5RkNsGyNY1qtR6ySTDON1o9geUZDbBsjWNarUeskkwzjdaP YHlGQ2wbI1jWq1HrJNkwzjdaPYHlGQ2wbItjWq1HrJNkwzjdaPYHlGQ2wbItjWq1HrJJMM43Oj2B 5RkNsGyNY1qtR4kkwzjc6PYHlGQ2wSNY1qtR4kkwzjc6PYHlGQ2wrItjImqlseJJMM43Wj2B5RkV sJSKv4yolmqVseJJLM43Wj2B5Rkf/UJSKv4ypTZqmoeX8kqS1M43Oj2B5Rki/wC0Koi1DKlC/mqa h5SSpLUzdf6tHsDyjJ6/p2HURaxiobX81TWv4/USaiXUZy59N6PYHlGXubEiE5+RaxisaqEXVCjl Q/WSayXX+Zy59ro9geUUVbNeXPpVRFdI7gzWUVfeqK6h2skOElwmu/ST3bx/R7A8oMpk/SxHiM8M OjThTX9iLqWqr6HHB50kOkp4zSVsUVKqro9geUDLit15fLSumM+MPjTw26UuCVH2moPsWoqcK3R1 4feJD5MkIiTpKvO6fYHlGiFLViuHLSpGJAzIGnyh8peKXRHEEcQ20NtDbQ2kNpDaQ2kNpDaQ2kNp DaQ2kNpDaQ2kNpDaQ2kNpDaQ2kNpDaQ20NtDbQVxBXEFdKnit8cfHpA/IJMn6TMp+0vw9geUaYU+ pmqJNprRmUNSRuSUSSmQgkgSQI+X5fl+X5fl+X5fl+X5fl+X5fl+X5fl+X5fl+X5fl+X4r4sgWQV SCuSOSR2SPSiRLREzDMlUVVVfh7A8o+EeW4wsTNKKxmYijcsollMspliSxJZjDGIYxDGIYxDGIYx DGIYxDGIYxDGIYxDGIYxDGIYxDGIYxDGIYxDGIYxDGIYxBZYssqllUsrljksdmISsxooSVmLjyqq r8vYHlHxRVRWZ77QznNI3mzSlGZUKU5hSJmKHEUOIocRQ4jScRQ4ihxFDiKHEUOIocRQ4ihxFDiK HEUOIocRQ4ihxFDiKHEUOIocRpOIocRQ4ihxFBcxQXMEKsxpHM1aQezmhB/M3nCquqtfn7A8o/hS utC9dL50vnS/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/eL94v3i/ eL50vnS9dLytT7X+PrDhvHuTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOT HJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY5McmOTHJjkxyY/pP/aAAgBAgIGPwBR f//aAAgBAwIGPwBRf//aAAgBAQEGPwCPk8jmv2su47DV1z9uE90V5xHl7vuKrTXWMHDNdYwcM11j BwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHD NdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11 jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMH DNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDNdYwcM11jBwzXWMHDP+z/AEd/2MzUhXbvz7H6XVO/ Y7vFJSkpSUpKUlKSlJSkpSUpKUlKSlJSkpSUpKUlKSlJSkpSUpKUlKSlJSkpSUpKUlKSlJSkp+le p3d6ndOn4OZqQrt349EOqp0QT9PVfzGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGC9X RVh9/wAjo8nRfnmakK7d+H+LqdVEefTqonYYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBgwYMGDBg wYMGDBeqd/uKip2+/wAszUhXbsqOutURVT9SidhgwYMlZ/XsGDBgvYVFQVOnb6fHM1IV27J0QR95 O6idhOwyaWC9hU6d/oK6v0+GZqQrt2RFVOyCdhBJrUU/cRO6N+GZqQrt06CL07qIJNiijydGjzsu ZqQrt0dd/MRBBJsUUU/y+8uZqQrt06/YQQSbFFFOv2WXM1IV26KIJNyij0uZqQrt0e8iCTcoo/Lm akK7dHvIggk2KKKPy5mpCu3R7yIJNyij8uZqQrt0e8iCTcoo/LmakK7dHvIgk3KKPy5mpCu3R7yI JNyij8uZqQrt0e8iCTaooo/LmakK7dHvIgk3KKPy5mpCu3R7yIJNyij8uZqQrt0e8iCCTaoo/Lma kK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu3R7y IIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCCTaoo /LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu 3R7yIIJNqij8uZqQrt0e8iCCTaoo/LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCC Taoo/LmakK7dHvIggk2qKPy5mpCu3R7yIIJNqij8uZqQrt0e8iCTcoo/LmakK7dHvIgk2qKKPy5m pCu3R7yIJNyij8uZqQrt0e8iCTcoo/LmakK7dHvIgk3KKPy5mpCu3R7yIJNyij8uZqQrt0e8iCCT aoo/LmakK7dHvIgk3KKPy5mpCu3R4QSblFHpczUhXboqfcQQSbVFFT7y5mpCu3RPzEEEmxRRRHZc zUhXbojyfRR1RBJsUUUX7JLmakK7dk/bVfAgk2KKL37qwVV+suZqQrt2RHk+giook2L3F7i9GJ8M zUhXbsqItFRFRRO40aNmVo0aL3FhuL5+OZqQrt34I69REVFGjRo0aNGjf6po0aNGjRo0XuK5DXv9 zqrV+OZqQrt349UXt9hEVeijRo0aNGjRo0aNGjRo0aNGjRo0aNGjRo0aNGjRo0aNGjRo0Xq9/YVH V6OnVflmakK7d+XVOw3qh0e7FM7PJ7KQ0aNGjRo0aNGjRo0aNGjRo0aNGjRo0aNGjRpSKaH6V6nR 3sh1eXr+BmakK7d/C7KqFJfZTX2U19lNfZTX2U19lN72U3vZTe9lN72U3vZTe9lN72U3vZTe9lN7 2U3vZTe9lN72U3vZTe9lN72U3vZTe9lN72U19lNfZTX2U19lNfZSX2d3l/Ej/wAj/wCf+7/jD6/y f5/7tBOnX+L/AMfr+5tPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPK m08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptP Km08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKm08qbTyptPKn/jan//Z"
+ transform="matrix(0.24 0 0 0.24 174.5615 142.499)"
+ id="image25"></image></g></mask><g
+ opacity="0.09"
+ mask="url(#SVGID_1_)"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ id="g27"><path
+ fill="#1D2915"
+ a:adobe-blending-mode="normal"
+ a:adobe-opacity-share="0"
+ d="M195.361,251.626 c-8.161,0-14.8-6.64-14.8-14.8v-73.527c0-8.161,6.639-14.8,14.8-14.8h59.663c8.161,0,14.8,6.639,14.8,14.8v73.527 c0,8.16-6.639,14.8-14.8,14.8H195.361z"
+ id="path29" /><path
+ fill="#1D2915"
+ a:adobe-blending-mode="normal"
+ a:adobe-opacity-share="0"
+ d="M255.024,152.499 c5.964,0,10.8,4.835,10.8,10.8v73.527c0,5.965-4.835,10.8-10.8,10.8h-59.663c-5.964,0-10.8-4.835-10.8-10.8v-73.527 c0-5.964,4.835-10.8,10.8-10.8H255.024 M255.024,144.499h-59.663c-10.366,0-18.8,8.434-18.8,18.8v73.527 c0,10.366,8.434,18.8,18.8,18.8h59.663c10.366,0,18.8-8.434,18.8-18.8v-73.527C273.824,152.933,265.391,144.499,255.024,144.499 L255.024,144.499z"
+ id="path31" /></g></g><g
+ id="g33"><g
+ id="g35"><linearGradient
+ id="SVGID_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="225.1929"
+ y1="152.499"
+ x2="225.1929"
+ y2="247.6265"><stop
+ offset="0.0123"
+ style="stop-color:#C1D72F"
+ id="stop38" /><stop
+ offset="0.1394"
+ style="stop-color:#BCD631"
+ id="stop40" /><stop
+ offset="0.5859"
+ style="stop-color:#AFD136"
+ id="stop42" /><stop
+ offset="1"
+ style="stop-color:#ABD037"
+ id="stop44" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#C1D72F" /><a:midPointStop
+ offset="0.3086"
+ style="stop-color:#C1D72F" /><a:midPointStop
+ offset="1"
+ style="stop-color:#ABD037" /></linearGradient><path
+ d="M184.562,236.826c0,5.965,4.835,10.8,10.8,10.8h59.663c5.964,0,10.8-4.835,10.8-10.8v-73.527 c0-5.964-4.835-10.8-10.8-10.8h-59.663c-5.964,0-10.8,4.835-10.8,10.8V236.826z"
+ id="path46"
+ fill="url(#SVGID_2_)" /></g><defs
+ id="defs48"><filter
+ id="Adobe_OpacityMaskFilter_1_"
+ filterUnits="userSpaceOnUse"
+ x="184.562"
+ y="152.499"
+ width="81.263"
+ height="95.127"><feColorMatrix
+ type="matrix"
+ values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
+ color-interpolation-filters="sRGB"
+ result="source"
+ id="feColorMatrix51" /></filter></defs><mask
+ maskUnits="userSpaceOnUse"
+ x="184.562"
+ y="152.499"
+ width="81.263"
+ height="95.127"
+ id="SVGID_3_"><g
+ filter="url(#Adobe_OpacityMaskFilter_1_)"
+ id="g54"><image
+ overflow="visible"
+ width="356"
+ height="414"
+ xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEBLAEsAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA EAMCAwYAAAXBAAALIQAAEOP/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAaEBawMBIgACEQEDEQH/ xACYAAEAAgMBAQAAAAAAAAAAAAAABAcBBQYDAgEBAAAAAAAAAAAAAAAAAAAAABAAAAMIAwEAAgMB AAAAAAAAAAIGATIDBBQFFjZQMwcRECKQMRMSEQABAgQEBgEBBwQDAQAAAAAAAQIxcgMEEFCRsyGC M6PTNBFBIGFxEiIyE1GB0UKhscFiEgEAAAAAAAAAAAAAAAAAAACQ/9oADAMBAAIRAxEAAADy0npz Z0Dnx0DS7Q9kr0IKcIKeICeICeICeICeICeICeICeICeICeICeICeICfggp2CElQD1aXxOgc+O1s um7kKj5vpObG6d2Q9zspRA9JmSGmCHmWIiWIiWIiWIiWIiWIiWIiWIiWIiWIiWIiWIaYIeJo1sPe 4OK5C2tCVS3OmN5clN3IVHod9EOv6zWb0zkAAAAAAAAAAAAAAAAAMRJnwcVXltVuetyU3chUfp5+ 5YexhTgAAAAAAAAAAAAAAAAABjODUVxZNbnjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwaut rJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAA AAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjy Cx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1t ZNbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAA AAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQ WPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautr JrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyCx5sKaAAAAAAAAAA AAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZNbHjclN3IVHIjyC x5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAAAAAAAAABjODV1tZ NbHjclN3IVHIjyCx5sKaAAAAAAAAAAAAAAAAAAMZwautrJrY8bkpu5Co5EeQWPNhTQAAAAAAAAAA AAAAAAABjODV1tZNbHjclN3IVH7+HqWTO1uxMgAAAAAAAAAAAAAAAAAYzg1Vb2NXB5XJTdyFRx5G jLc3XG9SS2MgAAAAAAAAAAAAAAAAD4+ohqq47GvTa3JTdyFR830nNm/7qp+gLVk8fuDcZgehLRBL RBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBLRBKQohP0MbkT40OcG8uSm7kKj5vpObAJm45sd n98SO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3cQO3xxI7PX84JcQAN5 clN3IAAAAAAAAAAAAAAAAAAAAAAAf//aAAgBAgABBQD+G3//2gAIAQMAAQUA/ht//9oACAEBAAEF AFgq7/bL9narGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxn arGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qxnarGdqsZ2qx narGdqsZ2qxnarCYVyhn78PQNo/MCUmJhssm48QEScNrGJGEMQgjEIIxCCMQgjEIIxCCMQgjEIIx CCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIIxCCMQgjEIQakYQOlI bGTCajw2R5SPLm/KK2gegbR+LVYzzDZGzFKyBaysYS3FYGSBBQkFCQUJBQkFCQUJBQkFCQUJBQkF CQUJBQkFCQUJBQkFCQUJBQkFCQUJBQkFCQUJBQkFCQUJBQkFCQNkCA9uK0R7WVrJ+ykMy6WI8BrW NY0IraB6BtAsdqbMHtttYxkvKFKxhCs4JpCtExKFMy5W5jWX22NgRAitoHoG0SsBsePZZFhSSkuw peFm5dhi3qRKYk1BbAjoraB6BtCcl/8ASYtUBjCkL8Lwp2fS3WCxpVDA/wA5lFbQPQNoShGNLbif CcM3+roX9VQz4ZFbQPQNoSLP0t7P04e5uql5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW 0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5F bQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnk VtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqe RW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp 5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6q nkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubq qeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5u qp5FbQPQNoSPXIOcPc3VU8itoHoG0JHrkHOHubqqeRW0D0DaEj1yDnD3N1VPIraB6BtCR65Bzh7m 6qnkVtA9A2hI9cg5w9zdVTyK2gegbQkeuQc4e5uqp5FbQPQNoSLlvb+nD3N1UvIraB6BtCTN8Jbj /ScM3+rob9VQ36ZFbQPQNoTUx/xGtcdjSlb9ZwsRvwt1jMYVRR/+5hFbQPQNokZinmbPOsaWVjsM XhZuOwpbxOsYWcjtjzCK2gegbQLDdv8ANtuuDGsgTJTMYZjeCaZjBHmSlZcbgxjL9dGxDBFbQPQN oDGtK2z31pBJXYrWQLmVrCz5Whk8QVpBWkFaQVpBWkFaQVpBWkFaQVpBWkFaQVpBWkFaQVpBWkFa QVpBWkFaQVpBWkFaQVpBWkFaQVpBWkDZ4gNPkYI9zKxk7dysZdr80zTGaZoRW0D0DaPzK3Oalmyy oYwEVEv8yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGV S4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXGVS4yqXB1RL/JlUMMyauU1Mt/KK2gegbRxaK2jj/wD/ 2gAIAQICBj8AG3//2gAIAQMCBj8AG3//2gAIAQEBBj8Ar2djdfxW7G01az+Ok74VzEcvF7FWJ73Z o+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+ M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M9 7s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+M97s 0fGe92aPjPe7NHxnvdmj4z3uzR8Z73Zo+Ms7O7u/5Leq5yVGfx0m/KIxzotYixTC5kpbbfsfFJir 9/0EWo74+5qHH8y/3IO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1U g7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1Ug7VSDtVIO1U4fmT+5803fP3Kn+D4qsVP v+n2LCd22/C5kpbbcUqVkX4+jf8AIiI34QTgQIECBAgQIECBAgQIECBAgQIECBAgQIECBAgQIEBe AqK1FRfuFqUE/SkWf4PhY4WE7tt+FzJS224JWqJw+f0ov/YnATgcMi4i8BeAtdifpX9yf+4WE7tt +FzJS22jKSfVeP4DUROCCcMmXgORU4KPpL/qvD8CwndtvwuZKW20dUVIcEE4Hxkyi8BHon7uC/2L Cd22/C5kpbbT5/8AoTKFG/iWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttp zKJlCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+Fz JS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzKJlCjZiwndtvwuZKW205lEyhRsxYTu 234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFG zFhO7bfhcyUttpzKJlCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZ RMoUbMWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzKJlCjZiwndtvwuZK W205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+FzJS22nMomUKNmLCd22 /C5kpbbTmUTKFGzFhO7bfhcyUttpzKJlCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2Y sJ3bb8LmSlttOZRMoUbMWE7tt+FzJS22nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzKJ lCjZiwndtvwuZKW205lEyhRsxYTu234XMlLbacyiZQo2YsJ3bb8LmSlttOZRMoUbMWE7tt+FzJS2 2nMomUKNmLCd22/C5kpbbTmUTKFGzFhO7bfhcyUttpzCZQo38SwndtvwuZKW20dTVfvQQ+cmUXiI xFhxUsJ3bb8LmSlttGVPp8/C/go1fkTjky8RyqsB9T6KvD8CwndtvwuZKW23BKNR3wqftX+qCcRO JwyLiLxF4i0Ka8V/cuFhO7bfhcyUttuCKi/CpBRtOs74cnBF/qJ+oiRIkSJEiRIkSJEiRIkSJEiR IkSJEiRIkSJEiRIkReIv6hadFfl31d9EFc5flViuFhO7bfhcyUttv2ERrvzNT/VT4qIrf+TqIdVD qodVDqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTqpqdVNTq pqdVNTqpqdVNTqpqdVDqodVDqC/xorl0F/O74av+qfYsJ3bb8LmSlttyywndtvzD/9k="
+ transform="matrix(0.24 0 0 0.24 182.5615 150.499)"
+ id="image56"></image></g></mask><g
+ opacity="0.35"
+ mask="url(#SVGID_3_)"
+ a:adobe-opacity-share="1"
+ id="g58"><path
+ a:adobe-opacity-share="0"
+ d="M184.562,236.826c0,5.965,4.835,10.8,10.8,10.8h59.663 c5.964,0,10.8-4.835,10.8-10.8v-73.527c0-5.964-4.835-10.8-10.8-10.8h-59.663c-5.964,0-10.8,4.835-10.8,10.8V236.826z"
+ id="path60"
+ fill="#1D2915" /></g></g><linearGradient
+ id="SVGID_4_"
+ gradientUnits="userSpaceOnUse"
+ x1="226.1924"
+ y1="159.7139"
+ x2="226.1924"
+ y2="200"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop63" /><stop
+ offset="0.3788"
+ style="stop-color:#F8FBF3"
+ id="stop65" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop67" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.4383"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></linearGradient><polygon
+ fill="url(#SVGID_4_)"
+ points="221.189,159.714 214.142,180.951 224.048,180.951 214.142,200 238.243,173.61 227.655,173.61 236.978,159.714 "
+ id="polygon69" /><g
+ id="g71"><g
+ id="g73"><g
+ id="g75"><image
+ overflow="visible"
+ opacity="0.75"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="392"
+ height="242"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYwAAAD2CAYAAADF97BZAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAHohJREFUeNrsnYlu40gSBZMU5Z75 /4+dbUsiFwtY2JrqvIqHSEoRACFZPtqk3BV8WVcvAAAACXouAQAAIAwAAEAYAADwWgYuwSp0XAKA wzJxCRAGIgCANf8fIxaE8RIxIBaA8yeMDokgjLkNfLfyzwOAfWTRNX49EkEY5h9N6+sIAuC8/++n mXKZjJ/5UfIYPuyPRXut9WOEAXDuxOGJYEqKZPpEebyjMOYKoTO+BmEAfIYwSjG0JJFaHm8rjncS RkYE2uutwkAgAO8liezzTPqY3jl1vIMwooa+fi0SRvQzshIBgHMKYwpez5Su3jJ1nFUYLWWlznne KpHW5AEAx5fF5Aijfi0jDy91nFocZxRGJgnUMvDkkf3arDiQCMD+YshIwxKE93xy5CGJ1HFqcZxJ GEsE4b0WHa3JA2EAHEcYU8PjlJREdESp47TiOIMwIlG0yqEPPl4iDmQBcCxpZMtOmWNs+Fy2n6M7 kzSOLIy5oogk0SsfZwWCNADeSxhZMYzGYy2I8uslIY5TpY2jCiMzsikjCO2xDz4fiaNFGggDYD9h LJGF9uh9rq8+7hxxWLI4vDiOJozsKCdPFJoc5ry2JG0gDYDzJouxOrTXLJHUsuiKz4uROurS1GHL VEcShpcqNGFoZSZLBBfla6zXO0MeGXGQMgCOkyyyopgCMfzveDifs44yRdQlLKtEdei0cRRhaLKI UkXZoFtCeH7uUn3dJfF9UV8HwgA4tzDG6nktjYfy/OF8zhJLZ0hjEns01SHTxt7C8EpQmdKTlhQu lSguxmu1TLSfNac8hTQAji+MMZEsahHUx6g8743v1aQxOudzSGnsKYyoBOUlCk0StQQGRRrW4aUO bWRVpj8DYQDsI4xaFJEwPFk8FGHcDYGUR1/Jon7uzf84bIlqL2FkS1BWP8XFSRKDIozBEclgiMPq CJ8rDSQCsI0cWmWRTRaWDO7BYy2OXhFH2SE+BudymLSxhzAsWbSkCk8S3vNBkUdGGJE06pTUIgTE AbCOKLRylCYNqxyVTRV347gYX9sr4nhUotDKVPXw292l8WphtMrCSxWeEOrjqghDE0hUlrKkYaUL ZACwj1S8lBGli1oYWpL433Eznl8qWdxFL2trfRsiev/GIaTxSmFkJ99po5+0RBHJoXy8Bt+j9WmU /743qU/E7vxGGgD7JBBrCRCvs9sqRd2NZHErRDEY4iiTxV1p72ppiPx/IqDVr7GbNF4ljBZZaKnC E0UtBu3jq5E0PGFcgpJUH8gCcQDsJworXWQTRiSMWyWM5/Oheu3ZltzFLmk/lPbhkCOoXiEMreHM 9FVYsrhWz8vjS3lNE8dglKiyHd9ewqAsBbB/KcoThjbvwhpCG6WL8vgu2pRb0XbdnGpFKY26vbCG 3u4mja2Fkemz8EpQZWOulZq+gkdNIlFZaq4wBGkAHFYWIm2d3lG6uFeiKNPFt9Ku3ESfEOyJY3TS xi7S2FIYc2ThpQpLFF/Bx6U4auFckiWpFlkgCoBjiCPb8T01Jow6WVx/JHEtZPEt+oCaaD6XRUYa b1OSapXFEJSdsodVporKUZlRUpEsEAbAcaWhpYx6WK02lPamSKOWxVBIo1UY3QJpbC6PrYTROhLK SxW1LH5VUvhlvG5JQ0sXWv/FReYNp0UaAPvKYq4wxoQwvIQRlbojYayRNDaVxhbCaFmKXJNFPcrp q5LFL0UUGWlE6UJ7Y7MT9hAGwDmFEaUMb/5F3X/hjb70hulnZVFL4/Sd3l2iLNUHsrBKUL+M48v4 2EoX0ZvqlaIEYQCcWhalNKwNkrz5GPeftuRWtCk30ed8aUsYzU0WdZoo25ZaHJsJZMuSVMs8i6iv opbEX4FAnt+jdXZnZaEtby6IAuBtUsac/oxaGoPy6A2mWZoupiJldK8uTa0pjLmlKK2DOxLFX8br WllKG5Lbsn4UO+0BII1B/uzLqG9Av+XPKQHZNsU7H22IcF2e0qRx2ISRkYU1g3sISlB/KY9/OUlD 67vIyOKSKEO1JAzEAbCfKFqF4c0CL1PGUKSNm9hr1LXchHYJWYjoy4RYZSnZQhxbz8OIRDEYwvhl SOIvQxh/KenC6+hu7eSOpIEwAM4hjCXSuBRp47lW1F1p16wtoFvShSYLa++MUV7Un7GGMFpKUV66 qPssaln8bUijFoY1u9vbOGnp8NkucX0A4LWyEGmbCT6KvnzIWMjiUcgjsyGbdQOa+V0nyW/p2r2i NLVmSWqJLLR0Ycnib6ck5U3S85JFy8KCSzq5kQfA9pJokUX52AdJo6/EkVmwdM6ci2nG0TmyWE0c S4URDaPN9ltkZPG3U5bS5l1kFhecu2w55SeAfcl0FncJgXh9G30hivqxXIE2Gl3ZO6KIymPZo0xI m/VjrFWSmjsqanBkYfVd/K2kC6uj25JFZ7yxraJAEADHF8pUvTYFjbZUd+5T0UY8hfEQfapAZnRl lCpG0eeHaB/XKcOS5CriGFZ6Qyx5aPMuhiBZ/FJkoaUMTRblMNpoFvfS3fOQBcB55DEp/3e9DuJa GE9ZWO1bpvRkNeZWp7u1Z0emNDUp579YGsOCNyBKF9HIqEFp7K1U4Q2lteZcWOu4tM6xoAQF8H7S EKN0Uz9qd/B90Xh3ku+r6IxUMTpHuWWsdvRGacrr09g9YWTnW7RM0rPKU9oyIN7CgpYs1twxD3EA HJcp+f9UuxPvFGnMFUUXpANLGJ5Qyu+t/+1Ddnp3iXKUNu/iy0gYvyQ/Qa8cGaUt+5FJFiJtI5+Q A8D50kVGIpNy0zgtkIYY/0b5PLOnuHZcqpTRK0nIK0+9TBjZLVfnzOrOJI0vQxbafAuvzyJbfmK4 LMB7JAzv/+zU8H+9lEZL2zApopgMcURHVJrqRO+72a0Pw0oX0YZIVsKIylDWkuVav0UpK2upj7mi QA4A504YnkCmoLpQfm/r3hbWarmRHJ5rV3kpwytNaalqljiGhRc+U4qKNkb6ctJFnSa0uRaaLC7J ZEEZCgCBRCOoLHFMxd19JuVEndyeMLIpo98yZcwtSWWXL5/bf/El9kioL7H3tYhmW1rpYm4pCgDe RyCt4pCigRaxZ297w2fHIFWU6aJ8HOTf61uVbd5mKWOYcVFb08Wc/bm1RQTrVFH3WViy6INUgSgA oEUcWn9HL7kFEOtS1BiIojy+5P97cdSlqUfVDnspYzZLh9Vq+3Rn5mBcE6KwtlgtReEli16YiAcA 64vDayt65XszQ2ejhFFu3FTuxfFQksYo+kitXfowOrFHSnmlqGgLVi9daEt9ZCbmibAzHgBsK46u kIFUlY3pp416CmNIlqNulShuRVtYbuB0r26aR6MsNYm/d8aqwpi7DEhm74urU36K9rTQ1p23Fg9E FgCwpjjqmeFdlTK8ctS1eNT2DP+qZPFVSOMm+grcUV/G4s7v1j6MOcuYe3MwNGl8KV8b7cFd/w4i /pR8RAEAc8QRSUOqlPH8+jpljEVJqZbGl5Iq6qPc7e9eScPry5AlKWONeRjeUNpLUI7SEsUg9sxt bwZ3L/RVAMBr04bXCT5Wpam6XF+WpK7y7z6Ka5EqynQxiL2DaC/xaKnNJ+5Fayi1jpQagtKTNXN7 SKSLaClhZAEAa6cNSxrlXX5fpYyxaNdqadyVdnBuyli187ufeaG0foJMyhgMMdSlp0wZykoXIu3b qAIAzE0b2nNtBGl2YdbBaRsHJ2W0rMg9q23sGy5My2S9PnExhsTFyG6BmHkDAQBeLRFNGpeqNOXt RJppG7Wb6i6Qxiz6hpP3RNIHCSNj0swF6WaUopAFALwyZWRvri1xXIL2sWVqQbR67qrCaEkaLUNr 6wtxCWRh7ZVryQFJAMAe0ojazWe7dWlsI6/JhKG1l6KUoma1lf3Ci2RdiGyyuIg+CspbRLA3TD7n jQQA2EIe0Y21Nw1hUB6z0sgkDC8dLRZGNlVkR0hZpSdLFpfkBVhkTgCADVJGZoM5qyLjyaN1o7hV +jH6mTHL2gcjugjWBfHKUN1WJw8AsFG6iGSRLeNn2spoFOlqbWXfeDG6IHK1ysI76cyOeaQLADhr maqfIY2L5Pt5rQ7vzYfVZspUfXC0CsLq5LbGEgMAnC1laP0Z1giqls7ubBl/k07vaOiYtp6TdjKa JKJJJ9n5FqQLADhj2vCG20Y33NlSVNfwu62SMLqkNb2E0SviyMzgXrUOBwDw4pThrY6R6QPOVmo2 7fvNTNzrgs9F9bhIHH3ihC07C+kCAE4mE00ctUCiakymhN+vfZPdz4gm2fHFXSALK0V409pFWPID AM6XNrwUklnANSpZzRlS29x+zllLqiVpZBKHNwoqE6OQBgAcXRTeIoCd0x564siW8K2RUs0MMy9E 9tBOwNv4KFtjQxwA8C5C8drOLlmlya4h5a21Fy513q948llbdo48okglQn8FAJxLCt68Ma1Bt9pD 7fW1O7q7LYQRxausLaPaGivPAsC7yyTbZnZiTznIyENk4UipfuZJtp68VXLyxJGZoEfaAIAzSaJl TtuaCWOVdrJ18UHrJCNZRFErU3ZCCgDwjglDa+u6GQkjszjr5sLIJI2oA8dLGtKYMBAHAJxVDJ4s Mmv1ZWURlaNeKgxJnmBmT9kueZFFKEEBwGdJJjui9CU7j/YrnJTX6Gcn3m1SbwMAOEnyyDT4SxNF tGrtLGF4nc3euN7MbMKsGDIlKMQCAO8kjeyNdIs0Vm0vt+jDiGQS2TVbtgIAOKMkoopMa5uaEc4q 9C+8EF4UmyMpAIB3Tx4tfcGb32T3G52sVzN7iQkBAA4ogJYbbetjbxe9zFp8s8v8/Y4XCQAAkeiN uwSJQiQ3qbn1Jn/zhNHNuDCR5RAKAHyKLDKfjxJG9t/YpdNbpH1/7ZY4BgDw6TKJSvWtW0Espt/g ROes/eQtxYtQAAAOsJFc/6KTmxPJAADAF8RL29F+5xMHAEAGfz5fvHfFFu1tf8ILCgDwbrLIrAi+ xs/+CGEAACCX/FpTm9x4IwwAgPMkka2+/jDCoJwEAPAGbSoJAwDgwxr+owuDlAEAcHJIGAAAgDAA AD6At5jpDQAAJAwAAPikdIEwAAAAYQAAAMIAAACEAQAACAMAABAGAAAgDAAAAIQBAAAIAwAAEAYA ACAMAABAGAAAgDAAAABhAAAAIAwAAEAYAACAMAAAAGEAAADCAAAAhAEAAAgDAAAAYQAAAMIAAACE AQAACAMAABAGAAAgDAAAQBgAAAAIAwAAEAYAACAMAABAGAAAgDAAAABhAAAAwgAAAEAYAACAMAAA AGEAAADCAAAAhAEAAAgDAAAQBgAAAMIAAACEAQDwMUwIAwAASBgAAHDOlIEwAADgUMKYuNQAAOdu F0kYAABwGGGQLgAA1mtHd2tTSRgAAOeThvX58vhYYZBSAOBTJDAl0sXU0EauJhESBgDA/tKoG/U1 GvnVk0a/08UhNQAArJtENqff4KQydbTpyBcFAODA0titA7xf+MtPM09YuwDT1nEKAOCEaSLqw5he 1Wb2K51c5hedErYkUQDAJ0ohalen4KZ9esXN9h4zvefIBQDgE6QxSVyJmSRXllq9xN9vdBEiM2ai FwDAp0hjMm6sWxKGN9oqandTbW+/0clnkkXr8DFkAgBnl8KcG+dJ/AFFU9DGZqUQ3uT3G1yUKGJ5 1pyEkVIA8BkCySSOKHVMiTZ2tfazn3liU/IEopPPXBhkAQDvKIu5N9JTcGx2o903xpLopDIXyJNB JIgp+XsCAJxBHNkb6czN+ZT8Ppl7Q96vcNItJxHZUoKTRBAA8K4CiYbIPp+PDW1t5qb+ZcKQwIxZ C3oJA2kAwLumi0w7OiqSGKWtI3yV9rNPntyc2KQdkRk9cQAAvIscJidZWG3mqHy89IZ804SR6Zix RDFWJzlK23Axz4zIBQDOJBCRuDQ/OqLItKOrDx5asw/DkoRmxFH5mlH8OhzDbQHg3WQRtZuZhDE6 clky9201YURlqDFIGGODGT0rAwCcVRxRKX9MtJ8tJarF7WffcIJZY3mmtKJVFK+s+AYAcBYxRJ+L Sk5jcMzp12iq2myVMFpO0CpXtdoRgQDAGSQSdW5bCePRII1R8h3tL1lLaq4kyhN/SNwhHtkaUQDA UdOFVRXxkoUmh0fQfmZK/SILy/t94mS9dUsiI3on6J209jNF4o5w5AEAZxFHNM/iURxLZbFKGT+7 ltSUSBjRCKjoRB/BBaQjHADOKAmvKqP1UTyM9jFqQz2BaL/D6sJoPenROdHoKC+EVdfLCAJ5AMCR xJGpzHg32I9EW9pSltosYXiiECNWRXW4R0PUmrOoFgDAEdOFJpEoSTyPe/U4VxpzfvdFCSNKGi1W fF6Au7T1a7SsagsAsHe6EMmVo7yb63tSFF5ZalHq6Gc2utnRUZEkshdgSpw8ogCAI6YLWUEUd+fj pQkj3W6uMXEvEkdWEnfR63abxSsAgBeki7k32Hfj0BJH3W5uMlqqbzh5TyCtUSpzEVpKU6QMADhi uvCE8VBuqj1R3IMb72iY7WLmrlabnXuRsWXGng/xZ4KTMgDgiOlCGiowLdKIOr6jzetm7ZGx1bDa TN/F87glLkhLR44IczQAYL90kZnYbI2EqtvEW4M8Mqt/L2of+4YLEfVfaOb0TvJWXIybcWE8e86Z owEAsJUsrOkGmVLUXZFG1D5mb7BXm4vRz7worQkjEsVNsanVqROtzLjYogAAM2URdXA/GtrIW0Ic L524Nyy4UJm+jEdwEerj+vM4/DxeiuN/P6P7kdz487z7ed4rF6P7ea0rfueOv3EA2KAMJZLbEygr iqjNbE0X2u/YfEM9JC9MV/3gLlGWsmpz1vH98/uUx70QRl8cXXFIJY5IGoI4AGBFWbR0cFtTDeo2 8ltpH7W+jUyHt7fH92YJY3JEkZFFfVG+fxLFd5EsbkXCGKqEEQmjThmlLOp0QdoAgLVkUYujbrSt AUC3QBLWa9mEYW0V8fKSVH1xygbbGjJWlppuijQG5Yhk0SmJoa+k4EmDtAEAS0RRPnorz1ojoer2 sD40aUQDgzJbts5KGUPDxeoco0bjiy9KuhgUWVyLz1+MhOEJoyt+v1H5Gk0SpA0AyIoiksUYVFse jizqR00ac6YeTMnzWj1haHfpVsdOb0SwoUgadbK4FsmiTBnZhNFVKUNDEwdpAwCyohCZtyzSwyhD 1cdvI2lEKcOTxSpTEJb0YZSNb1mailLGUxpRGWqoRKHJonMa+k7aO8ERBwCiiEShVVesEaLlTbM1 2Oe3IwpLGLdkyvDKaZsnDE0cXSGLTMrISKNMFhdHFpYwpkIWnZM4InEgDwBEYcnCWnVWW+LDE0Ut jUgcmc7uVdeQWiIMcS5iJmXcqpLTt/w5IqpFFlGjXs/b6BrEQeoAQBTRpLxphiwsUXji8EpSWv+F yEqd3XOFMTl34V7KuFelpUtwaGWovlEW5UXqg5SRKU1NhmQA4NyCyIpCjGShDZ3V5lV8B3L4bXzu OyhFeSOkWs5/s4RhDVEt7+QfRUNfSqNMGV6qqKXRBymjlsTFKFPV3zsVH7eUpqagzAUAxxRDNmFk k8XDSBfaCKhaCv/5OTxpRB3eXt/FquvtrdGHUd+p18t2PIqGXytNXZTk4U3Sy7zxtTiespjEHmk1 JctVmWQDAOcSibXQamYDJGvobCmL34njP+L3YWRLUasOpS25zPy+srPZKhFpX+Md3pDZqA+j5Y9k 6UXrFn4eAPZPGNnyU3borCaLm1KG+k+VLLzDG17rSWOTdLFEGCJ+B7IllEgCEryWbaCjWZlrxVlE AXA+cSyRxST6sFlNFjdHFnU5yhPGb0cW1gipTSofwwpvRl3S0dZ+19JEn0waljCiIW7Px6EqS12K z2n9IyL+pEBGTQGcUxaZ5T2iDm5v8yNtUp7VZ/FPQ7Lw9gpqWdJ8t+XNPVlIUhqZklSXSBGj2JNn roU0xh9ZjIU4ns9HRxzWo9dBjlAAjlOGmgJJiCzbz8KSxbfofRSRLH47Zaho7oXIhpvKrTUPo1N+ wbFoOLPSyAgjMw66vJClLMpjlD9HYdXikMSjJocu+SYhFYBlMmhJFa2y0EZCZWRxE33IbC2Hf6rH WhatI6M230RurZKUNcy2FkerNLw33lvw6/mmXos3tlyj6iH6aKw+WRaLZIEgAPYTSKs0rEUEvdFQ 1uZH2qQ8r5/iH4k7uVtGRmlltdVYM2FYb9RYNbgZaXiNq/amWtseatJ4iD9JcKk0WjrnAWB7aXhr QXk3oJP4o6G0mdzakh9WZ/c/Ys/DiFanrTdM8q7BoUpSUWmqbOSz0rB+flSGeiSkcRF7rw1vhrlI bhgx0gDYVxhT0GjWd+FjsmJxF31TuGg2dzSk9rdRjlpj7+7DJYxsaapMG1oDG02Es5ZR90RRvsHP pdOfW79mpZFdUh1hABxfGN5EvKws6r6Let8Kq/8imt3tLWWe2fNis1LUFgnDeyNHpeF8JGThJYxo 8kx5J3AtJHFVUoa1LIkmjH6mMJAFwPbCyHZyjzOqFlay0Pa1aJnR7Y2KinbV82SxujS2Kklpo4Qm RRwtPzsShZUqvooL/0wX9QZN1gq5njhE2kZSIQ2A7WQxNT5qZai6P3SU3G559RIgVsqwEoW1wGA0 jFacEtQpEoYnjXLOQ7bxzAyh9UYtfBXiuMq/d/UbnKShiWOuNJAFwHGkYQnj0ZAublU5yts5L1qy /DuQRVSCispzpyhJlfLwImGLLKw+DC8yluIYKnFo0uiN8hTSAHgfYYwSz+HKlqIyW61qaULbqzsq Q2X7LTaTx7DRm9gF4sjKQpKi8IRx/XkjalnUfRmeNCxhRP0ZCAPgGMLwZDGJP4imlsXdKEdF+3Pf xO+rqDu4DyWLLRNG1J8RScMaAjc69UUrXVyrhOGVpYbGlIEwAM6TLsZkwshULW4N0rgpj9oM7nr4 bKss3qIkNVcaIvl16LWRUc9SVJkwhiphWH0ZLSlj7dngANAuCi1R1M+z6WIUe85FnTK+FWnclBRR J4rspLwWWWwujuGFb3KLNDL9F1Z0/DJKUbUwWstSnjSQBcDxpRHJIprRHaWMmyEIL1FEqSLb0X36 Tu9SFFlpTOKvSZ8dVntVRKEJo+78tvYWvyQSBsIAOFZJKhKG1p6MTtXCGimlPY9E8RB9BvdDkdok L1qN9ggJo0Ua2T0vvIRxlT/7MKwSVDS8NprINzdlIA6AdUQRJYy6HOUtLGi1KZnSlCWSjChaS1C7 yGKPklQkDS1teEnjUr3JQ/H4nKh3q4RxUaRxCRJGZngtHd8Ax0oYmXJUZq+LaB0p77WHxP0UD4nX htqlz2IvYWSkMUnbHhhjII5aCjcjTXjlqOxcjEgaiAJge3FkN0NqmYORKU9ZcmhJFNYM7sPI4tXC mFue0t703hFH+ca2pIkoXWRkkU0ZHogFoK1BbNk9L+rH8OZ5ZYRgPc+Iwis/7S6LPYThSUOTxyh/ 7hNei6N+oy/y7z0v7skk4fVdZIWxRBaIAmC+OLKyyHZ+eyth3wOpRENkWzc/OoQs9hJGNmlMSmNc v+F9lTZ6+fduehdFHPXn+oQoMsIQsffKQAwA24ukRRqZlOF1hkevWf0To1IWkzPIYk9hlCffGc8l SBudkjaejXmdNHrjMRLEnHSBMAD2k4WIP2CmRRqePEbxl/Cw0kRUftp1nsWRhdFaotI6xbW00RWl qmfi0NJDS5pAGADnF4ZIbk0pSxjWx1lJjOL3URwyVRxNGFrasGRRp43668dKFmVD/0gKwtqiNdrn m/kXAPsJQyS3rPmkNN7185bDks00s/R0WFkcSRiiJAxLIJNxh1+nkzFICr3zemY01JzlzZEGwD7C kERpKtv4j4mUUm9L3ZImpqNe+OHAfwzRwoWROLoqcXTiL1MepYmlu+0hCoDXlaZapZFJHlMghslJ FJnf7dCyOKoworSREYcYAukqeWTkQKoAeO+kIQl5eK+PkptDccpUcRZhiPgjqTKd4p2TRGSGIJYI A2kAbC+LrDBE8qOpWo45SWI6y0UfTvbHEZWp6mSSafQzH4vkJ+chDIB9hRHdxWdGKUWL/0Wd2G8l irMJQ5OBKOnDk4bX6GdSw1qLCyINgNcKo0UakUhE5o1yOrUozioMcWTRkjqyKSGbJOjgBjiuSLyG u6V/YU5fxFuI4szC0N6MOaljmiGDTOkJUQAcM31MM59PC37GW4jiXYShiUMkP7JK+16SBMBnp45s w9/6McI48B9GlDrq2eNTQjgIA+D9hLH11yCME6cOCdJHy89AGADnFEbm89PCr0UYb5A6ZIFAsn8o SATguIJo+fppxX8HYZz8D6n75DcfAGE0ff3HtxEDf1ipdNDyh9LxhwVwOmkgB4Sx6h9Kxx8aAGJB GLDmHxb9FwCIAGEAf6gA8Ln0XAIAAEAYAACAMAAAAGEAAADCAACAs/JfAQYAL3iXmIlSiu4AAAAA SUVORK5CYII="
+ transform="matrix(0.24 0 0 0.24 179.2061 198.1514)"
+ id="image77"></image><g
+ id="g79"><radialGradient
+ id="SVGID_5_"
+ cx="225.1929"
+ cy="226.1387"
+ r="30.8299"
+ gradientTransform="matrix(1 0 0 0.75 0 56.5347)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop82" /><stop
+ offset="0.4828"
+ style="stop-color:#FDFEFB"
+ id="stop84" /><stop
+ offset="0.7611"
+ style="stop-color:#F8FBF3"
+ id="stop86" /><stop
+ offset="0.989"
+ style="stop-color:#F2F8E8"
+ id="stop88" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop90" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.8025"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><path
+ fill="url(#SVGID_5_)"
+ d="M186.706,235.825c0,5.965,4.835,10.801,10.799,10.801h55.374c5.965,0,10.801-4.836,10.801-10.801 v-19.373c0-5.965-4.836-10.801-10.801-10.801h-55.374c-5.964,0-10.799,4.836-10.799,10.801V235.825z"
+ id="path92" /><path
+ fill="none"
+ stroke="#EDF5E5"
+ stroke-width="5"
+ stroke-miterlimit="10"
+ d="M186.706,235.825 c0,5.965,4.835,10.801,10.799,10.801h55.374c5.965,0,10.801-4.836,10.801-10.801v-19.373c0-5.965-4.836-10.801-10.801-10.801 h-55.374c-5.964,0-10.799,4.836-10.799,10.801V235.825z"
+ id="path94" /></g></g><path
+ opacity="0.74"
+ fill="#FFFFFF"
+ a:adobe-blending-mode="lighten"
+ d="M263.623,229.595c0.037-0.364,0.057-0.734,0.057-1.107 v-13.375c0-5.965-4.836-10.799-10.801-10.799h-55.374c-5.964,0-10.799,4.834-10.799,10.799v7.324 c7.545-1.012,15.699-1.566,24.213-1.566C231.959,220.87,250.812,224.252,263.623,229.595z"
+ id="path96" /><linearGradient
+ id="SVGID_6_"
+ gradientUnits="userSpaceOnUse"
+ x1="225.1929"
+ y1="204.3135"
+ x2="225.1929"
+ y2="246.626"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF;stop-opacity:0"
+ id="stop99" /><stop
+ offset="0.0141"
+ style="stop-color:#FDFDFC;stop-opacity:2.231669e-04"
+ id="stop101" /><stop
+ offset="0.1344"
+ style="stop-color:#BEBEAF;stop-opacity:0.0148"
+ id="stop103" /><stop
+ offset="0.2565"
+ style="stop-color:#94957C;stop-opacity:0.0297"
+ id="stop105" /><stop
+ offset="0.3796"
+ style="stop-color:#747759;stop-opacity:0.0446"
+ id="stop107" /><stop
+ offset="0.5029"
+ style="stop-color:#5D633F;stop-opacity:0.0596"
+ id="stop109" /><stop
+ offset="0.6263"
+ style="stop-color:#4D552E;stop-opacity:0.0746"
+ id="stop111" /><stop
+ offset="0.75"
+ style="stop-color:#414B23;stop-opacity:0.0896"
+ id="stop113" /><stop
+ offset="0.8742"
+ style="stop-color:#3B461E;stop-opacity:0.1047"
+ id="stop115" /><stop
+ offset="1"
+ style="stop-color:#38441C;stop-opacity:0.12"
+ id="stop117" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF;stop-opacity:0" /><a:midPointStop
+ offset="0.2901"
+ style="stop-color:#FFFFFF;stop-opacity:0" /><a:midPointStop
+ offset="1"
+ style="stop-color:#38441C;stop-opacity:0.12" /></linearGradient><path
+ fill="url(#SVGID_6_)"
+ a:adobe-blending-mode="darken"
+ d="M263.68,221.954v13.871c0,5.965-4.836,10.801-10.801,10.801 h-55.374c-5.964,0-10.799-4.836-10.799-10.801v-13.871l0.038-7.704c0,0,0.923-9.937,11.173-9.937h54.962 c0,0,10.063,0.328,10.801,10.799V221.954z"
+ id="path119" /></g><g
+ id="g121"><g
+ id="g123"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAuJJREFUeNrsl9trE0EUxjO7m5vW tKFN1RqLCmqlIvjgkz5I/cOFIqLggw9KsRHxUo1IdEtactG9+A1+A8dxNrsxK/rgwI9lt5ueb875 ZuZspfJ//Bhqjvc0AfCIHClIQEzSMkUoBqyCJbAKWrxXQoBmBL6AQzChmGQREWbmNQY/DS6Aa6AL mtZvdcDPoEcOQEgxUV5mVMYzH5wCZ8FFcJ0CLoN1UHeIGII34AV4BvbBW4qbzsqKctzruq+ALXAL 3ABXwAafNyjS9sQ3cAwG4BXYA0/AU/AejLOE+I4MtME22AH3wE2wyedNivSFQT3eB/y79kwHnGE2 v4IjinCaNrBEtJiBu2SLs686VkRWGRt8/wTL5jFwxIxMbSGB+Ac1qtcluEMBbWslFDV7QBFdlmBE bwxZtthVDn1dpgF3WIIOhakF9iCf2ajQK32W5hcRJgvnmYHb9ECzQAnyhif8o7PxkWImsiQeRSyJ fWCjJAGy5G2usKtgzc6wx5dWxT6wYhm2jKNBm/UcV90m/aLsdLVoonX+QJV8RvmcXNflNVOOKktQ Fz4p+6AMrBg/GUeeFWUHd51HyuXevz7+GRELNSRzjMwYnmhI5Laa/gEBYxEjskVE7Ih67AeOi3ZE BYc55j+xxzjgpBMpImZL1mNDMuDxm5aYBT2x1+wx+vZJ6lt94kl2Ux1uWl4JWZhy9g/AQ/DOPjt8 q0ULuLebhiRYYO8wPUTIdm+X1zDrKE/FKjH95TL3eP83MiIF7FHAY2ZkYpfadxhoRE80WJ66EKIK BE9YAiPgPkW8dPUSFUfDGnMpHVmKvQJCEoofcsamBLs0fOgSUMnomo2QQ66UAbMTi4+hmOk2mGZW B39OE+rgj5iBcNb3h5qxk9boDb1SLrEh2c75+NlnCfT1A4OP8nZiVeAT0IhZY0Ni+gHP8oEpQ59Z HHP2uRtfkeUnxTj7AWHqMU0ZiRVX2ld5kZ4jnSewHN8FGACSOOKkAlOGAAAAAABJRU5ErkJggg=="
+ transform="matrix(0.24 0 0 0.24 199.0298 216.5547)"
+ id="image125"></image><g
+ id="g127"><radialGradient
+ id="SVGID_7_"
+ cx="202.6289"
+ cy="219.7041"
+ r="2.9995"
+ gradientTransform="matrix(1 0 0 0.75 0 54.926)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop130" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop132" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop134" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_7_)"
+ cx="202.629"
+ cy="219.704"
+ r="2.999"
+ id="circle136" /></g></g><g
+ id="g138"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtFJREFUeNrsmP1LFEEYx292Ts3V 9ujFrCiwFyPShH4I+imoiPqbhYKIoKigN0W8SulNIrOU63S921u/A9+BYdm9mbndg4IGPiynuzOf eea52WeuVvvf/Joo8VwA6rxm+0lBD3R5TYctpu6XYBRE4DiYzMhpqRbYBDtgHyQ+gsIzQmMUOg3O gzkwzciZTUXqO1gCH8E3CsauERSOUiOgAc6AC2ABXAYXwZECsV/gPVgBb8AH8AVsg45NTjhKTYGr 4Aa4AmYZqYjLmpdj+4ySilwTLIOn4C34YZOTjlLXwH1wC8xzKSMureQym0g+O85ITxP1uU3hPS6r t5j63zFK3QM3uYwNQ0g45KUSPMSJNLjsLS71blHUZJ9Ox5lDSuo2k32SHYsBvslKcAIc5jJvUK7r I1ZntK6Du8yryBJhW9P73hi3jg2ym7ek0hKtO0z4E5xx2RYYOany7DPYyotaUPCwyoVL3KemKpLS TX+h5jhGI88jT0x9/U9yrzoHwoL7ykQtZN8LHGvURUxy05xhntWH8I7WOTzDsaSLmOAMQl6DIYgF mTGEi5iWEyWqD9dtpHCMoPaXtn9KrHSR59CsYxSJ6SKv1e9FW6L1MmM4iXWMIu8ri7u04mjF7HuJ Y3VcxLqciaqfVlnYJRWKJexzlWNs5r2SZMGMNOp1cRYc5atEVBCtPVazD8AzHzHdQUKZUyzywoIT kY9Uh9XrC4o1WTimPmI9ouv9iAXfIHKm1GtKvSyKlq2C1Una5sMTLBRHPN4MOvIxpV6BRfCEJU/s W8Ganf4xzoaCf5dGaS36JHnMKnWNUg/BY35uD1rza7ku5bY4658cMDHkEt6nUZP4TQG1dI/Ic/CJ /SVVHHglS2J94pnluXLecuB9x3Nlk5+3jUlV9hOBMAQjCpn1lMikgFrCdQrtGEKp62CDlCtaMLQc eNu+QmV/7XGp2cyN2rsdCDAAoyXZx8WJpTUAAAAASUVORK5CYII="
+ transform="matrix(0.24 0 0 0.24 213.9448 216.5547)"
+ id="image140"></image><g
+ id="g142"><radialGradient
+ id="SVGID_8_"
+ cx="217.5439"
+ cy="219.7041"
+ r="2.9995"
+ gradientTransform="matrix(1 0 0 0.75 0 54.926)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop145" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop147" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop149" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_8_)"
+ cx="217.544"
+ cy="219.704"
+ r="2.999"
+ id="circle151" /></g></g><g
+ id="g153"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAttJREFUeNrsmO9r00Acxptc1m6d Fn9M125sU4RVpyjiSwXB/9wXulciiE4dhpUMpwzFUa02XdP4HDwHR7hcLk0mCh58WOnI9548973k uTYa/0e54c15nQ8E8TJ1UpKQ2Z8QJgUtgDa4CC6AliZOiYrBCfgGfoLTsgK9OQStgE2wDa6DDv+v hhQwBAdgH0TgS1mBLsIEBV0F18BNcJvC1sCyQdgIHFHYG/AODMAxBSZVhQXgHJ15AO5T2Aa4TMHC 0GMJBXwFhxT2Erygkz/AtGhim1NS1A3wCDwGO+AKBS3QKS+nrlp6eQProKe5G4LvNucCS0+1uXQP wRNwj6JaFkH6SgitNxeJ0BwNueSzMsIC3ulduiX/roJmpp9cWkVQ1CrrqB17ws+TPGdM3y3Rftnk fTpVVlS2ZpN1+qy7znl8V2HSrUvcdbKnutryVRk+63RZd5vzBC7ClFvyMXALbHEDiJreNGpDbbH+ Wp5rJmEd7sQ+n13NCq8uU881WbfPeTquwtq0u1ezW1nXepyn7SJM9dgSCc4oPBTO4Rus9jKJwatZ lGeZy+rYXzH+GWEpXxEq5Kl8VecwBcnURVjMgCcZn5GwsTZH7CJMD3khL5zWLGzKuiHnGZpe5CZh I6bO9wx7v+bN7YYxY70j1o/yEoZpKSdMmntMoMq1tIYlVG7ts/4x50tddmXCEDfgxRETZ1JRWMI6 EesObGFRWCyfaa+oDl8jQd4DscApJUr21S54Dj7wu1JBUW2Ct1rybDDRntditUtPnWor8Aw8Zd2h rXdFQdGYd6WfbPTYnOeeEiSv/cTDyC5FvbL1luspSSXPFUYUmaHu8KS0yfjdMpySYp6QIop6TZdC njEnRTvdpVc8Lt0yBW4wS+04HHj3+Fg4pKARnUxdJnVNBL7hSNal4OxPBFLAZ/CRzumn8NR1wrKR xdfy1KLlwDvmw3RaRlDVX3s8h8dGWiUE/BZgAMf82R9IYLF+AAAAAElFTkSuQmCC"
+ transform="matrix(0.24 0 0 0.24 228.8599 216.5547)"
+ id="image155"></image><g
+ id="g157"><radialGradient
+ id="SVGID_9_"
+ cx="232.459"
+ cy="219.7041"
+ r="2.9995"
+ gradientTransform="matrix(1 0 0 0.75 0 54.926)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop160" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop162" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop164" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_9_)"
+ cx="232.459"
+ cy="219.704"
+ r="2.999"
+ id="circle166" /></g></g><g
+ id="g168"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAt9JREFUeNrsl91rE0EUxTOzm69a 05YmVWsUFdRKRfDBJ32Q+ocLRUTBBx+UYiOitlqRaEos2UT3w3P1jIzrbHZNVuiDAz9CNru5Z+69 M3O2Uvk/fg414zOCDzSxRwJiEJGkTBGKAatgEayCFr8rS4AwAp/BIRhTTDyPCDPzGoOfAhfANdAF zdT/SMBPoEf2wYBiQldmVAEBHjgJzoCL4DoFXAZroO4QMQRvwAvwDOyCtxQ3SWdF5QiQui+DDXAL 3ABXwDqvNygy3RPfwBHog1dgBzwBT8E7ENhCvJwMrIBNsAXugZvgPK83KdKzGlTzu8/fpWc64DSz +RV8oYhfTetPEdFiBu6SDc6+6lgRWZNo8P4Flk0zcMiMSGkSP+MPalQvJbhDASuplVB0RfkU0WUJ RuyNIcsWucoh15bYgFssQYfC1Bz7kcdsVNgrByzNHyJMFs4xA7fZA80CJcgb2uofycYHihlrh4hF ax9YL0mAGT7LKivsKmjLpLXjplVrH1ie0ryzlkWa9SxXnWR5QTv6ocUmWuMDqlLu8Di5ruk1Vzmq LEGdD5QtQln7yI8YespZUXbwzBi6cgzGsRTx14ZkxvFbDJeI9Laa/AMBgRUjTIsI6Yh69ANH0xzR DMMc8x/pMcTwjNIiIlqyHg1Jn8dvUmIWZGKv6THk/Jh4GWqFE3RTHW5auoQsTDj7B+Ah2JOzI8vU RNxQ2pYh8efYO4yHGNDubfNzkHWUJ9YqMf5yiZ7AmyEjtoAdCnjMjIj5TbycBhqxJxosT90SogoE j1kCI+A+Rbw0XmKaxzQlCXjz2GpOXUBITPFDztiUYJsNPzAC8kQklpBDrpQ+sxNZL0MR020wZlaC P2cTSvBHzMAg/f6hCu6qNfaGrJRLNCSbOS8/uyyBfL5n8JFrJy7a7Solpk1DYrynTvWBKcMBsxhw 9nEZL8S2GNtzuJo6YFOG1oor7a28iOdI8gLb47sAAwCDFN6m03jgxgAAAABJRU5ErkJggg=="
+ transform="matrix(0.24 0 0 0.24 243.7749 216.5547)"
+ id="image170"></image><g
+ id="g172"><radialGradient
+ id="SVGID_10_"
+ cx="247.374"
+ cy="219.7041"
+ r="2.9995"
+ gradientTransform="matrix(1 0 0 0.75 0 54.926)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop175" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop177" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop179" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_10_)"
+ cx="247.374"
+ cy="219.704"
+ r="2.999"
+ id="circle181" /></g></g><g
+ id="g183"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAn9JREFUeNrsl+lrE0EYxvdKjSZW YxEPxBsVrNdHQTxA/KMFBRGPDwoVVIpoq3jUeJUG25qk2fVZ+A28WTabxG4lHzrwgxw78z7zzMw7 73reBDR/jOcCUREhn21LRCy6osfn0kT4BN0h9oiDoiGmTN8Efoum+CHWEBRvRoSbeZXgR8QZcVEc F7syfTcI/kq8Fgviu1jlv3hcET627xXHxFlxWZwXJ8RMxgmPIKkTn8UbMSdeinfiq1hnmUYS4QTs F5fENQSc4rfUgahgT7TFivgk5sVj8VQs4kqukGiAgCviDiKOijr/BUOWL7t/9uGaVyTEighYggsI uI79NQYfdY9FPF8x/WL2xiJLk9hOoelcJehtcYslqI8hYNDGrvP9G5t1PbtRQ+NIg/W/KWaxNNpk DnK5JZ35TzbuCq70ibAu3BBXxWHW1i8hGbpc0+akNLNuBDAtTopz4kBJAuxEC8cPzIlI88BpOoQl Xw1TuDtLsqvZkxbwUA2FjZxEVJYbdROj4mWOpVuzCMoWYGPlxggm4SrfFmFFJOTzDUi2KFY8KIYT sUoSWRadLRDSM0XPMgVPn4guOT0tSN6KVtHd/w8tYWJfqDHeM+m+jBkTeIEaoEmKTUp0oXD80Kjt kU4PkVSqJWTOhIDpFf5APBFLOOPliYhxZgYR00MKmVEEuKWeQ8Q8ruRe5Xb3po7s5CqvDSjnxhVw XzzjFu3k5XTbuuziNYLvZolCk+KHBU8n8QcBL8Rd8VB8yCto8kTEDNBCTIdBg4wQvyD4L6rsdOb3 xKNhhW44IKm4wZaghSAnoIdrHWhz/m3wlOfiI86OXPJPzMvPxLwG/tcX4u3m2l8BBgBQ/dU5d1Za tAAAAABJRU5ErkJggg=="
+ transform="matrix(0.24 0 0 0.24 199.0298 230.2217)"
+ id="image185"></image><g
+ id="g187"><radialGradient
+ id="SVGID_11_"
+ cx="202.6289"
+ cy="233.3711"
+ r="2.999"
+ gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop190" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop192" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop194" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_11_)"
+ cx="202.629"
+ cy="233.37"
+ r="2.999"
+ id="circle196" /></g></g><g
+ id="g198"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNrsmM9r1EAUx3cz2XW1 il2wLLagIh5aeilUBC967EX/XA/1It5aUaiC2JNY/EWp0lZkG3c3id+Bz0AIaXayibKHDnzIJfPm s29eZl/Sas3paNeYZ0SHaz5OKmIx5pr+azF7fyh6oi+WxXURZGJZiUScim/iWERiUkWwXTFDlxG6 I1bFBnKd3P1jpPbEvviE4JlvBtueUl1xQ9wVa2ITsdtkzOTmxGTsALE34oP4KH6I0TS5tofUJXFT PBCPxToZ67OlZTUWkSmbsffipXglvos/ZXLGI1N2qx6Kp+KRuFcgVYRh/oJYEgNxle08EUNqsbJY SDAnZa8r1FlYoQzc02sFF5n/W/wskzMlAReopydkaoVtDWocL1bqGtv8Bblx0YSgJFt9xNbJXLfG uZctjQEx11gj9M2YDXCFiVviflmAGeQCYtlt/MxTOvbJmEFkFZqSyu9GNr7xEXNP4gbnVK/mFhZl rUdsd0B3fcQCDs3lcw7PJobJrRH4iE37g24qa6VrBK05HRdiTYjVbvI8xtQ1isSyTd4pE5secW6N xEdslGnyDmhd0oazFRF7j7VGPmIxPdQ+HNMWNzUmBfFj3+7C1YDtMG7RT3UaONMS+jErtC1e05tV EksyPdkAyToHbsqW2e51R7ygs42qNooJaU/oPF2TF8wgl2SkdsVz8Y5sJVXFUvryX6TfNXld5HwE U37cWUbqGdfDsto1njVxQjscQ8jc8+SckO25jqipHTK1i+Ro1peR7FM6pKH7StAhC7uam7CQI+J+ J7RNTb0lU7Vf3+b6hXeuPxH8948qF6Pq+CvAAGGezDColMK7AAAAAElFTkSuQmCC"
+ transform="matrix(0.24 0 0 0.24 213.9448 230.2217)"
+ id="image200"></image><g
+ id="g202"><radialGradient
+ id="SVGID_12_"
+ cx="217.5439"
+ cy="233.3711"
+ r="2.999"
+ gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop205" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop207" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop209" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_12_)"
+ cx="217.544"
+ cy="233.37"
+ r="2.999"
+ id="circle211" /></g></g><g
+ id="g213"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAhCAYAAAC1ONkWAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAlRJREFUeNrsmM9LG0EUx5PdjTTW otDYWmoOQm2M/YGXnrxI/3IvnnoRW7TagocotqjQtLYp5pffgc/CECc7u+uGpuDAB2Y32Tff9+bN 7Jstlaa0lXM+E4gIAsd/BqIHpj+cpLBY0Ix4JBbhwYg4I+SvOIdf4jqrwHIOQUvihXgtVsWCQ9gP 8UV8El/Ft6wCyyl+DxH0XLwUb8UbxD0V1RE7ZtCO+I6oj2JPHIlTBPZ94sqe3yIi0hCb4h1Reibm iOK4HDPRuRJnRO+D2BGHRLSXJC7yRGpeNMV7sYXAeQSFCU6FRHIGB56IGveMI/uIGxu5JGFzTN0W wpqIijIsmpDFYZ55hah4xRpxP7MIM4NWWHEbTGGDKY1ybi8VKyVM/l2wYjtM+S1xrvww9x6KulgX K0QqvOOeGafGCnbrjOPScOtmnPA1Hm7Sr+TcjF2Rq2F3nb4zNVzCZsWyWMOr2XFe5WgB9urYX+ba KywkF1bJh8d4WWSrYLdhbdBhmohVrddNtYApLOUZI0jxgp6EMO8YQWlK272wuwobFlHkeVqqMVzC OlaR15mQMO8Yo8L6VpFnypNL0S1YWBe7h4wTVxneiP0RJ+KzaHE9KEjUAHst7J9wnWoqe7z9TVly QL9bwJQOsXOB3X36vbTVhfHqN16Zh49F2xXujK2PnWPsthhnkLYeiz0ziblrVZ55CkV7Ftrk1Q52 z5NmIkowdsUBIrIqz7SltR2la0vUNhxhP3PNP7RCf4CouPIs4jDS9p2U/svj21QfeKf6E8E/+ahy 37K2GwEGAJb/2mQI89WQAAAAAElFTkSuQmCC"
+ transform="matrix(0.24 0 0 0.24 228.8599 230.2217)"
+ id="image215"></image><g
+ id="g217"><radialGradient
+ id="SVGID_13_"
+ cx="232.459"
+ cy="233.3711"
+ r="2.999"
+ gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop220" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop222" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop224" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_13_)"
+ cx="232.459"
+ cy="233.37"
+ r="2.999"
+ id="circle226" /></g></g><g
+ id="g228"><image
+ overflow="visible"
+ opacity="0.25"
+ a:adobe-blending-mode="multiply"
+ a:adobe-opacity-share="1"
+ width="30"
+ height="30"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAnpJREFUeNrsl2lrE1EUhmdLjSZ2 sYgL4lqsYN0+CuIC4o8WFERcPii0YEsQtYpL3cVgW7PMjO+F55ZhmMlMzATyoRceSDKZc957zplz zzjOBCz3P+/xRE34fE6uWESiJ0I+VybCxekeMSMOizkxlbATwx/xRXwXWwiKRhFhd17H+TFxVlwU J8W+lJ0+zlfFmngjvolNrkXDinAJ+6w4IRbFZXFenBLzqUg4ODGR+CheimXxQrwWn8U2aSolwgo4 KC6Jawg4w28mAsGAmuiI3+KDaInH4qlYJyo7QoISAq6IO4g4Lppc8wrSl66fA0TNSQvJE+GRggsI uE74GxgvW8gB/68l7ouojXVSE/s5N9dxelvcIgXNIQTkFXaT718pViMiyjIa8OiZ/N8US4Q0GLEf 2d5iauYHhWtqpu8PiMINcVUcJbduBY3R9poOT4rpJdteRi1Mi9PinDhUkQC7/Cz7aRH2iTB9YIEb /IqPiSmiu0Sza3gZf2qgcC6jEVUVjWbCR83LOR8CqFpAMu07PrxJOMp3ReSJiOnnfYjH5DdK+sgS sUkT+SW6YxASJoYe46OXFtGjp5uB5JVop8/+EVfMxj4xY7w1m/YywtRmGmqhtlNhNMIs+36O2pB2 fYSmUq+gc8ZsyBzhD8QTsWEikyciomjnETFdMMiUEWBTvYyIFlGJ/ILqNRHZy1HeyBnnhhVwXzzj FO06BSHuUcVbON9Piuy7hlvCudnEXwSsiLvioXhnB5oiEREG2ojpYtRLCXEHOP/JlG12fk88yhp0 /RJNxRrbgDaCrICQqHWhw/OfdG54Lt4T2dIj/8S8/EzMa+DYX4h3l13/BBgABM7SO70ZkkMAAAAA SUVORK5CYII="
+ transform="matrix(0.24 0 0 0.24 243.7749 230.2217)"
+ id="image230"></image><g
+ id="g232"><radialGradient
+ id="SVGID_14_"
+ cx="247.374"
+ cy="233.3711"
+ r="2.999"
+ gradientTransform="matrix(1 0 0 0.75 0 58.3428)"
+ gradientUnits="userSpaceOnUse"><stop
+ offset="0.0123"
+ style="stop-color:#FFFFFF"
+ id="stop235" /><stop
+ offset="0.4235"
+ style="stop-color:#FAFCF6"
+ id="stop237" /><stop
+ offset="1"
+ style="stop-color:#F2F7E8"
+ id="stop239" /><a:midPointStop
+ offset="0.0123"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="0.6235"
+ style="stop-color:#FFFFFF" /><a:midPointStop
+ offset="1"
+ style="stop-color:#F2F7E8" /></radialGradient><circle
+ fill="url(#SVGID_14_)"
+ cx="247.374"
+ cy="233.37"
+ r="2.999"
+ id="circle241" /></g></g></g></g><path
+ d="m 529.664,248.155 h 18.498 l -2.809,18.064 h 5.59 37.586 l 2.6,-17.718 c 4.98,-1.091 9.133,-3.455 12.512,-6.693 3.084,4.075 8.566,7.37 18.252,7.37 6.338,0 12.775,-1.807 17.174,-3.687 4.254,2.399 9.463,3.687 15.459,3.687 3.088,0 6.236,-0.355 9.426,-1.023 h 67.135 l 3.354,-24.827 -5.445,-0.764 1.879,-13.356 c 0.371,-2.386 0.449,-4.66 0.449,-6.156 l -0.008,-0.375 c -0.457,-12.191 -8.139,-19.765 -20.045,-19.765 -2.404,0 -4.623,0.314 -6.676,0.852 h -34.189 l -0.035,0.244 c -2.527,-0.701 -5.41,-1.096 -8.686,-1.096 -3.801,0 -7.406,0.555 -10.76,1.598 l 0.105,-0.746 h -12.467 l 1.826,-12.951 H 613.08 l -1.846,7.658 c -1.373,5.704 -2.213,5.793 -4.453,6.03 l -4.508,0.477 c -3.049,-1.424 -6.357,-2.065 -9.602,-2.065 -2.135,0 -4.275,0.284 -6.416,0.852 h -19.291 c 0.502,-1.772 0.775,-3.674 0.775,-5.678 0,-9.601 -6.846,-16.305 -16.646,-16.305 -11.055,0 -18.775,7.721 -18.775,18.776 0,0.951 0.082,1.869 0.219,2.764 -2.135,-0.288 -4.277,-0.409 -5.553,-0.409 -2.053,0 -4.072,0.288 -6.045,0.852 h -31.342 c -2.74,-0.553 -5.641,-0.852 -8.537,-0.852 -7.138,0 -13.492,1.674 -18.808,4.723 l -3.451,-1.461 c -3.711,-1.571 -11.232,-3.262 -18.979,-3.262 -8.933,0 -16.383,2.56 -21.576,7.016 -3.265,-4.473 -8.523,-7.016 -15.228,-7.016 -4.822,0 -9.021,1.477 -12.572,3.44 -2.996,-2.204 -6.796,-3.44 -11.115,-3.44 -2.327,0 -4.48,0.315 -6.476,0.852 h -33.963 l -0.035,0.245 c -2.526,-0.702 -5.41,-1.097 -8.687,-1.097 -20.458,0 -35.307,16.031 -35.307,38.117 0,17.363 10.785,28.149 28.148,28.149 3.087,0 6.236,-0.356 9.426,-1.023 h 88.816 c 3.706,0.676 7.669,1.023 11.154,1.023 8.907,0 16.278,-2.375 21.51,-6.593 4.872,4.252 11.585,6.593 19.728,6.593 3.053,0 6.206,-0.368 9.286,-1.023 h 44.664 2.069 z"
+ id="path243"
+ inkscape:connector-curvature="0"
+ style="fill:#f5f5f5" /><g
+ id="g245"
+ transform="translate(0,16)"><g
+ id="g247"><path
+ d="m 340.308,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.095,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
+ id="path249"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 394.07,221.7 -0.171,-0.255 1.789,-10.055 2.642,-18.063 c 0.512,-3.749 0.341,-5.623 -1.96,-5.623 -2.642,0 -5.794,2.727 -9.372,5.879 l -2.727,19.512 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 -0.852,6.305 h -18.404 l -0.171,-0.341 1.875,-10.82 2.471,-17.212 c 0.512,-3.237 0.682,-5.453 -1.789,-5.453 -3.238,0 -7.413,3.664 -9.714,5.709 l -2.642,19.512 c -0.17,1.363 -0.17,1.534 1.108,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.767,-1.789 l -4.176,-1.534 0.938,-6.476 h 16.871 l -0.938,6.987 0.256,0.085 c 4.43,-3.749 9.116,-7.924 15.592,-7.924 4.687,0 7.839,2.641 8.18,7.753 l 0.256,0.086 c 4.175,-3.664 9.202,-7.839 15.252,-7.839 6.22,0 8.775,3.152 8.946,9.202 0,1.618 -0.171,3.493 -0.426,5.538 l -3.067,21.897 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.175,0.597 -0.852,6.305 H 394.07 z"
+ id="path251"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 443.995,190.771 -0.17,-4.431 c 0,-0.682 -0.085,-1.108 -1.022,-1.363 -1.022,-0.256 -2.642,-0.427 -4.771,-0.427 -3.579,0 -6.391,1.108 -6.391,4.09 0,2.727 2.982,3.749 6.731,5.027 6.05,2.045 13.888,4.431 13.888,13.463 0,11.076 -9.372,15.592 -20.193,15.592 -8.009,0 -14.91,-1.959 -16.273,-2.981 l 1.618,-12.355 8.691,0.512 0.255,4.941 c 0,0.597 0.171,1.108 0.938,1.363 1.278,0.427 3.238,0.768 6.05,0.768 4.687,0 7.327,-1.79 7.327,-4.687 0,-3.408 -3.152,-4.175 -8.009,-5.624 -6.135,-1.874 -12.78,-4.26 -12.78,-13.206 0,-10.48 9.116,-14.996 19.597,-14.996 6.646,0 12.866,1.533 15.081,2.471 l -1.704,12.354 -8.863,-0.511 z"
+ id="path253"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 489.748,218.548 c -4.175,2.386 -10.395,4.175 -16.444,4.175 -13.036,0 -18.575,-7.583 -18.575,-18.574 0,-18.83 11.588,-27.691 25.988,-27.691 6.475,0 11.843,1.874 14.229,3.578 l -1.874,13.377 -8.691,-0.426 -0.255,-5.794 c 0,-0.597 -0.086,-0.938 -0.597,-1.192 -1.022,-0.427 -2.557,-0.597 -4.175,-0.597 -5.624,0 -11.418,4.601 -11.418,17.382 0,7.839 3.493,10.395 8.436,10.395 4.346,0 8.436,-1.448 11.247,-2.556 l 2.129,7.923 z"
+ id="path255"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 491.364,221.7 0.853,-6.39 3.919,-0.512 c 1.193,-0.17 1.363,-0.426 1.534,-1.704 l 3.578,-25.987 c 0.086,-0.938 -0.085,-1.534 -0.852,-1.789 l -4.261,-1.534 0.938,-6.476 h 16.87 l -1.107,7.669 0.256,0.17 c 3.323,-4.771 8.095,-8.69 13.548,-8.69 1.874,0 5.112,0.341 6.561,0.767 l -2.13,15.507 -9.969,-0.341 -0.256,-4.431 c -0.086,-0.767 -0.256,-1.022 -0.938,-1.022 -1.619,0 -4.26,1.96 -6.646,4.431 l -2.981,21.643 c -0.171,1.363 -0.085,1.619 1.192,1.704 l 8.095,0.682 -0.938,6.305 h -27.266 z"
+ id="path257"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 536.094,221.7 -0.17,-0.426 2.045,-11.503 3.152,-22.749 c 0.17,-0.938 -0.086,-1.534 -0.853,-1.79 l -4.175,-1.448 0.852,-6.476 h 18.149 l -5.027,35.786 c -0.171,1.363 -0.085,1.534 1.192,1.704 l 4.09,0.597 -0.852,6.305 h -18.403 z m 5.879,-57.598 c 0,-5.453 3.238,-8.775 8.776,-8.775 4.175,0 6.646,2.215 6.646,6.305 0,5.368 -3.322,8.861 -8.861,8.861 -4.176,-0.001 -6.561,-2.387 -6.561,-6.391 z"
+ id="path259"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 556.796,239.764 -0.17,-0.341 2.471,-14.229 5.282,-38.087 c 0.171,-1.022 -0.085,-1.534 -0.767,-1.789 l -4.175,-1.534 0.938,-6.476 h 17.041 l -1.022,6.816 0.255,0.085 c 5.027,-4.686 10.311,-7.753 15.678,-7.753 7.328,0 12.44,4.686 12.44,17.041 0,11.758 -4.601,29.225 -20.449,29.225 -5.538,0 -8.605,-2.13 -11.759,-4.345 l -1.874,12.78 c -0.085,0.938 0.085,1.278 1.192,1.363 l 8.606,0.853 -0.938,6.39 h -22.749 z m 17.041,-30.247 c 2.13,1.789 4.942,3.322 8.095,3.322 6.901,0 9.458,-9.713 9.458,-17.211 0,-5.027 -1.193,-8.351 -4.431,-8.351 -3.408,0 -7.754,3.664 -10.821,6.391 l -2.301,15.849 z"
+ id="path261"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 635.777,219.4 c -3.749,1.789 -9.458,3.322 -14.229,3.322 -8.521,0 -12.099,-2.981 -12.099,-9.969 0,-1.107 0.085,-2.386 0.256,-3.749 l 3.066,-22.323 c 0.086,-0.512 0.086,-0.853 -0.511,-0.853 h -5.879 l 1.107,-7.839 c 7.242,-0.767 10.906,-4.431 13.122,-13.633 h 7.924 l -1.704,12.1 c -0.085,0.596 -0.085,0.852 0.597,0.852 h 11.758 l -1.193,8.521 h -12.439 l -2.812,20.364 c -0.171,1.107 -0.256,1.96 -0.256,2.727 0,2.982 1.278,4.26 4.942,4.26 2.385,0 4.771,-0.596 6.816,-1.363 l 1.534,7.583 z"
+ id="path263"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 671.817,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.094,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
+ id="path265"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /><path
+ d="m 703.596,221.7 -0.17,-0.255 1.874,-10.396 2.471,-17.723 c 0.512,-3.578 0.341,-5.879 -2.215,-5.879 -3.664,0 -8.18,3.578 -11.077,6.135 l -2.641,19.512 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.768,-1.789 l -4.175,-1.534 0.938,-6.476 h 16.87 l -0.937,6.987 0.255,0.085 c 4.771,-4.09 9.373,-7.924 16.02,-7.924 6.475,0 9.798,3.322 10.054,10.139 0,1.363 -0.085,3.067 -0.341,4.687 l -3.067,21.812 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 L 722,221.7 h -18.404 z"
+ id="path267"
+ inkscape:connector-curvature="0"
+ style="fill:#383838" /></g><g
+ id="g269"><linearGradient
+ id="SVGID_15_"
+ gradientUnits="userSpaceOnUse"
+ x1="324.1611"
+ y1="239.7637"
+ x2="324.1611"
+ y2="155.3275"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop272" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop274" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 340.308,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.095,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
+ id="path276"
+ style="fill:url(#SVGID_15_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_16_"
+ gradientUnits="userSpaceOnUse"
+ x1="377.45459"
+ y1="239.7637"
+ x2="377.45459"
+ y2="155.3277"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop279" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop281" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 394.07,221.7 -0.171,-0.255 1.789,-10.055 2.642,-18.063 c 0.512,-3.749 0.341,-5.623 -1.96,-5.623 -2.642,0 -5.794,2.727 -9.372,5.879 l -2.727,19.512 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 -0.852,6.305 h -18.404 l -0.171,-0.341 1.875,-10.82 2.471,-17.212 c 0.512,-3.237 0.682,-5.453 -1.789,-5.453 -3.238,0 -7.413,3.664 -9.714,5.709 l -2.642,19.512 c -0.17,1.363 -0.17,1.534 1.108,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.767,-1.789 l -4.176,-1.534 0.938,-6.476 h 16.871 l -0.938,6.987 0.256,0.085 c 4.43,-3.749 9.116,-7.924 15.592,-7.924 4.687,0 7.839,2.641 8.18,7.753 l 0.256,0.086 c 4.175,-3.664 9.202,-7.839 15.252,-7.839 6.22,0 8.775,3.152 8.946,9.202 0,1.618 -0.171,3.493 -0.426,5.538 l -3.067,21.897 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.175,0.597 -0.852,6.305 H 394.07 z"
+ id="path283"
+ style="fill:url(#SVGID_16_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_17_"
+ gradientUnits="userSpaceOnUse"
+ x1="435.17719"
+ y1="239.7637"
+ x2="435.17719"
+ y2="155.3275"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop286" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop288" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 443.995,190.771 -0.17,-4.431 c 0,-0.682 -0.085,-1.108 -1.022,-1.363 -1.022,-0.256 -2.642,-0.427 -4.771,-0.427 -3.579,0 -6.391,1.108 -6.391,4.09 0,2.727 2.982,3.749 6.731,5.027 6.05,2.045 13.888,4.431 13.888,13.463 0,11.076 -9.372,15.592 -20.193,15.592 -8.009,0 -14.91,-1.959 -16.273,-2.981 l 1.618,-12.355 8.691,0.512 0.255,4.941 c 0,0.597 0.171,1.108 0.938,1.363 1.278,0.427 3.238,0.768 6.05,0.768 4.687,0 7.327,-1.79 7.327,-4.687 0,-3.408 -3.152,-4.175 -8.009,-5.624 -6.135,-1.874 -12.78,-4.26 -12.78,-13.206 0,-10.48 9.116,-14.996 19.597,-14.996 6.646,0 12.866,1.533 15.081,2.471 l -1.704,12.354 -8.863,-0.511 z"
+ id="path290"
+ style="fill:url(#SVGID_17_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_18_"
+ gradientUnits="userSpaceOnUse"
+ x1="474.83691"
+ y1="239.7637"
+ x2="474.83691"
+ y2="155.3275"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop293" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop295" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 489.748,218.548 c -4.175,2.386 -10.395,4.175 -16.444,4.175 -13.036,0 -18.575,-7.583 -18.575,-18.574 0,-18.83 11.588,-27.691 25.988,-27.691 6.475,0 11.843,1.874 14.229,3.578 l -1.874,13.377 -8.691,-0.426 -0.255,-5.794 c 0,-0.597 -0.086,-0.938 -0.597,-1.192 -1.022,-0.427 -2.557,-0.597 -4.175,-0.597 -5.624,0 -11.418,4.601 -11.418,17.382 0,7.839 3.493,10.395 8.436,10.395 4.346,0 8.436,-1.448 11.247,-2.556 l 2.129,7.923 z"
+ id="path297"
+ style="fill:url(#SVGID_18_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_19_"
+ gradientUnits="userSpaceOnUse"
+ x1="512.28223"
+ y1="239.7637"
+ x2="512.28223"
+ y2="155.3277"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop300" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop302" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 491.364,221.7 0.853,-6.39 3.919,-0.512 c 1.193,-0.17 1.363,-0.426 1.534,-1.704 l 3.578,-25.987 c 0.086,-0.938 -0.085,-1.534 -0.852,-1.789 l -4.261,-1.534 0.938,-6.476 h 16.87 l -1.107,7.669 0.256,0.17 c 3.323,-4.771 8.095,-8.69 13.548,-8.69 1.874,0 5.112,0.341 6.561,0.767 l -2.13,15.507 -9.969,-0.341 -0.256,-4.431 c -0.086,-0.767 -0.256,-1.022 -0.938,-1.022 -1.619,0 -4.26,1.96 -6.646,4.431 l -2.981,21.643 c -0.171,1.363 -0.085,1.619 1.192,1.704 l 8.095,0.682 -0.938,6.305 h -27.266 z"
+ id="path304"
+ style="fill:url(#SVGID_19_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_20_"
+ gradientUnits="userSpaceOnUse"
+ x1="546.65918"
+ y1="239.7637"
+ x2="546.65918"
+ y2="155.32719"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop307" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop309" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 536.094,221.7 -0.17,-0.426 2.045,-11.503 3.152,-22.749 c 0.17,-0.938 -0.086,-1.534 -0.853,-1.79 l -4.175,-1.448 0.852,-6.476 h 18.149 l -5.027,35.786 c -0.171,1.363 -0.085,1.534 1.192,1.704 l 4.09,0.597 -0.852,6.305 h -18.403 z m 5.879,-57.598 c 0,-5.453 3.238,-8.775 8.776,-8.775 4.175,0 6.646,2.215 6.646,6.305 0,5.368 -3.322,8.861 -8.861,8.861 -4.176,-0.001 -6.561,-2.387 -6.561,-6.391 z"
+ id="path311"
+ style="fill:url(#SVGID_20_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_21_"
+ gradientUnits="userSpaceOnUse"
+ x1="580.69629"
+ y1="239.7637"
+ x2="580.69629"
+ y2="155.32719"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop314" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop316" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 556.796,239.764 -0.17,-0.341 2.471,-14.229 5.282,-38.087 c 0.171,-1.022 -0.085,-1.534 -0.767,-1.789 l -4.175,-1.534 0.938,-6.476 h 17.041 l -1.022,6.816 0.255,0.085 c 5.027,-4.686 10.311,-7.753 15.678,-7.753 7.328,0 12.44,4.686 12.44,17.041 0,11.758 -4.601,29.225 -20.449,29.225 -5.538,0 -8.605,-2.13 -11.759,-4.345 l -1.874,12.78 c -0.085,0.938 0.085,1.278 1.192,1.363 l 8.606,0.853 -0.938,6.39 h -22.749 z m 17.041,-30.247 c 2.13,1.789 4.942,3.322 8.095,3.322 6.901,0 9.458,-9.713 9.458,-17.211 0,-5.027 -1.193,-8.351 -4.431,-8.351 -3.408,0 -7.754,3.664 -10.821,6.391 l -2.301,15.849 z"
+ id="path318"
+ style="fill:url(#SVGID_21_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_22_"
+ gradientUnits="userSpaceOnUse"
+ x1="622.7832"
+ y1="239.7637"
+ x2="622.7832"
+ y2="155.3268"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop321" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop323" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 635.777,219.4 c -3.749,1.789 -9.458,3.322 -14.229,3.322 -8.521,0 -12.099,-2.981 -12.099,-9.969 0,-1.107 0.085,-2.386 0.256,-3.749 l 3.066,-22.323 c 0.086,-0.512 0.086,-0.853 -0.511,-0.853 h -5.879 l 1.107,-7.839 c 7.242,-0.767 10.906,-4.431 13.122,-13.633 h 7.924 l -1.704,12.1 c -0.085,0.596 -0.085,0.852 0.597,0.852 h 11.758 l -1.193,8.521 h -12.439 l -2.812,20.364 c -0.171,1.107 -0.256,1.96 -0.256,2.727 0,2.982 1.278,4.26 4.942,4.26 2.385,0 4.771,-0.596 6.816,-1.363 l 1.534,7.583 z"
+ id="path325"
+ style="fill:url(#SVGID_22_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_23_"
+ gradientUnits="userSpaceOnUse"
+ x1="655.6709"
+ y1="239.7637"
+ x2="655.6709"
+ y2="155.3275"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop328" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop330" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 671.817,218.463 c -5.538,2.556 -11.588,4.26 -17.638,4.26 -13.377,0 -18.148,-7.839 -18.148,-18.148 0,-17.893 11.418,-28.117 25.307,-28.117 9.372,0 13.973,4.26 13.973,11.247 0,12.184 -12.865,15.763 -26.157,17.126 0.255,4.346 2.045,8.35 8.435,8.35 3.068,0 7.243,-0.937 12.355,-3.067 l 1.873,8.349 z m -8.094,-29.567 c 0,-2.045 -1.448,-3.237 -4.09,-3.237 -4.771,0 -8.69,4.175 -9.969,10.906 3.664,-0.511 14.059,-2.3 14.059,-7.669 z"
+ id="path332"
+ style="fill:url(#SVGID_23_)"
+ inkscape:connector-curvature="0" /><linearGradient
+ id="SVGID_24_"
+ gradientUnits="userSpaceOnUse"
+ x1="697.92969"
+ y1="239.7637"
+ x2="697.92969"
+ y2="155.3277"><stop
+ offset="0"
+ style="stop-color:#000000"
+ id="stop335" /><stop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0"
+ id="stop337" /><a:midPointStop
+ offset="0"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="0.6933"
+ style="stop-color:#000000" /><a:midPointStop
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0" /></linearGradient><path
+ d="m 703.596,221.7 -0.17,-0.255 1.874,-10.396 2.471,-17.723 c 0.512,-3.578 0.341,-5.879 -2.215,-5.879 -3.664,0 -8.18,3.578 -11.077,6.135 l -2.641,19.512 c -0.171,1.363 -0.171,1.534 1.107,1.704 l 4.26,0.597 -0.852,6.305 h -23.347 l 0.853,-6.39 3.749,-0.512 c 1.107,-0.17 1.363,-0.426 1.533,-1.704 l 3.579,-25.987 c 0.17,-0.938 0,-1.534 -0.768,-1.789 l -4.175,-1.534 0.938,-6.476 h 16.87 l -0.937,6.987 0.255,0.085 c 4.771,-4.09 9.373,-7.924 16.02,-7.924 6.475,0 9.798,3.322 10.054,10.139 0,1.363 -0.085,3.067 -0.341,4.687 l -3.067,21.812 c -0.171,1.363 -0.171,1.534 1.022,1.704 l 4.26,0.597 L 722,221.7 h -18.404 z"
+ id="path339"
+ style="fill:url(#SVGID_24_)"
+ inkscape:connector-curvature="0" /></g></g><g
+ id="g4141"
+ transform="matrix(0.81856441,0,0,0.81856441,79.234731,-94.128741)"><g
+ id="g4143"></g><g
+ id="g4165"><linearGradient
+ y2="155.3275"
+ x2="324.1611"
+ y1="239.7637"
+ x1="324.1611"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4167"><stop
+ id="stop4169"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4171"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3277"
+ x2="377.45459"
+ y1="239.7637"
+ x1="377.45459"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4175"><stop
+ id="stop4177"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4179"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3275"
+ x2="435.17719"
+ y1="239.7637"
+ x1="435.17719"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4183"><stop
+ id="stop4185"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4187"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3275"
+ x2="474.83691"
+ y1="239.7637"
+ x1="474.83691"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4191"><stop
+ id="stop4193"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4195"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3277"
+ x2="512.28223"
+ y1="239.7637"
+ x1="512.28223"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4199"><stop
+ id="stop4201"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4203"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.32719"
+ x2="546.65918"
+ y1="239.7637"
+ x1="546.65918"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4207"><stop
+ id="stop4209"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4211"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.32719"
+ x2="580.69629"
+ y1="239.7637"
+ x1="580.69629"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4215"><stop
+ id="stop4217"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4219"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3268"
+ x2="622.7832"
+ y1="239.7637"
+ x1="622.7832"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4223"><stop
+ id="stop4225"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4227"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3275"
+ x2="655.6709"
+ y1="239.7637"
+ x1="655.6709"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4231"><stop
+ id="stop4233"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4235"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient><linearGradient
+ y2="155.3277"
+ x2="697.92969"
+ y1="239.7637"
+ x1="697.92969"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4239"><stop
+ id="stop4241"
+ style="stop-color:#000000"
+ offset="0" /><stop
+ id="stop4243"
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0" /><a:midPointStop
+ style="stop-color:#000000"
+ offset="0.6933" /><a:midPointStop
+ style="stop-color:#000000;stop-opacity:0"
+ offset="1" /></linearGradient></g></g></svg>
+ </a>
+
+ <div class="spinner" id='spinner'></div>
+ <div class="emscripten" id="status">Downloading...</div>
+
+<span id='controls'>
+ <span><input type="checkbox" id="resize">Resize canvas</span>
+ <span><input type="checkbox" id="pointerLock" checked>Lock/hide mouse pointer &nbsp;&nbsp;&nbsp;</span>
+ <span><input type="button" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked,
+ document.getElementById('resize').checked)">
+ </span>
+</span>
+
+ <div class="emscripten">
+ <progress value="0" max="100" id="progress" hidden=1></progress>
+ </div>
+
+
+ <div class="emscripten_border">
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ </div>
+ <textarea id="output" rows="8"></textarea>
+
+ <script type='text/javascript'>
+ var statusElement = document.getElementById('status');
+ var progressElement = document.getElementById('progress');
+ var spinnerElement = document.getElementById('spinner');
+
+ var Module = {
+ TOTAL_MEMORY: $GODOTTMEM,
+ preRun: [],
+ postRun: [],
+ print: (function() {
+ var element = document.getElementById('output');
+ if (element) element.value = ''; // clear browser cache
+ return function(text) {
+ if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+ // These replacements are necessary if you render to raw HTML
+ //text = text.replace(/&/g, "&amp;");
+ //text = text.replace(/</g, "&lt;");
+ //text = text.replace(/>/g, "&gt;");
+ //text = text.replace('\n', '<br>', 'g');
+ console.log(text);
+ if (element) {
+ element.value += text + "\n";
+ element.scrollTop = element.scrollHeight; // focus on bottom
+ }
+ };
+ })(),
+ printErr: function(text) {
+ if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+ if (0) { // XXX disabled for safety typeof dump == 'function') {
+ dump(text + '\n'); // fast, straight to the real console
+ } else {
+ console.error(text);
+ }
+ },
+ canvas: (function() {
+ var canvas = document.getElementById('canvas');
+
+ // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+ // application robust, you may want to override this behavior before shipping!
+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+ canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+ return canvas;
+ })(),
+ setStatus: function(text) {
+ if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
+ if (text === Module.setStatus.text) return;
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var now = Date.now();
+ if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
+ if (m) {
+ text = m[1];
+ progressElement.value = parseInt(m[2])*100;
+ progressElement.max = parseInt(m[4])*100;
+ progressElement.hidden = false;
+ spinnerElement.hidden = false;
+ } else {
+ progressElement.value = null;
+ progressElement.max = null;
+ progressElement.hidden = true;
+ if (!text) spinnerElement.style.display = 'none';
+ }
+ statusElement.innerHTML = text;
+ },
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+ }
+ };
+ Module.setStatus('Downloading...');
+ window.onerror = function(event) {
+ // TODO: do not warn on ok events like simulating an infinite loop or exitStatus
+ Module.setStatus('Exception thrown, see JavaScript console');
+ spinnerElement.style.display = 'none';
+ Module.setStatus = function(text) {
+ if (text) Module.printErr('[post-exception status] ' + text);
+ };
+ };
+ </script>
+ <script type="text/javascript" src="$GODOTFS"></script>
+ <script>
+
+ (function() {
+ var memoryInitializer = '$GODOTMEM';
+ if (typeof Module['locateFile'] === 'function') {
+ memoryInitializer = Module['locateFile'](memoryInitializer);
+ } else if (Module['memoryInitializerPrefixURL']) {
+ memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
+ }
+ var xhr = Module['memoryInitializerRequest'] = new XMLHttpRequest();
+ xhr.open('GET', memoryInitializer, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.send(null);
+ })();
+
+ var script = document.createElement('script');
+ script.src = "$GODOTJS";
+ document.body.appendChild(script);
+
+</script>
+ </body>
+</html>
diff --git a/tools/html_fs/filesystem.js b/tools/html_fs/godotfs.js
index 93cc30556b..93cc30556b 100644
--- a/tools/html_fs/filesystem.js
+++ b/tools/html_fs/godotfs.js
diff --git a/version.py b/version.py
index c723dd2935..284bda9520 100644
--- a/version.py
+++ b/version.py
@@ -1,7 +1,8 @@
short_name="godot"
name="Godot Engine"
-major=1
-minor=1
-status="stable"
+major=2
+minor=0
+status="alpha"
+