summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub2
-rw-r--r--core/allocators.h2
-rw-r--r--core/array.cpp2
-rw-r--r--core/array.h2
-rw-r--r--core/balloon_allocator.h2
-rw-r--r--core/bind/SCsub2
-rw-r--r--core/bind/core_bind.cpp283
-rw-r--r--core/bind/core_bind.h62
-rw-r--r--core/color.cpp6
-rw-r--r--core/color.h2
-rw-r--r--core/command_queue_mt.cpp2
-rw-r--r--core/command_queue_mt.h6
-rw-r--r--core/compressed_translation.cpp2
-rw-r--r--core/compressed_translation.h2
-rw-r--r--core/core_string_names.cpp3
-rw-r--r--core/core_string_names.h3
-rw-r--r--core/dictionary.cpp4
-rw-r--r--core/dictionary.h2
-rw-r--r--core/dvector.cpp2
-rw-r--r--core/dvector.h19
-rw-r--r--core/error_list.h3
-rw-r--r--core/error_macros.cpp2
-rw-r--r--core/error_macros.h20
-rw-r--r--core/event_queue.cpp20
-rw-r--r--core/event_queue.h2
-rw-r--r--core/fpstr.cpp2
-rw-r--r--core/fpstr.h2
-rw-r--r--core/func_ref.cpp3
-rw-r--r--core/global_constants.cpp4
-rw-r--r--core/global_constants.h2
-rw-r--r--core/globals.cpp28
-rw-r--r--core/globals.h3
-rw-r--r--core/hash_map.h2
-rw-r--r--core/hashfuncs.h2
-rw-r--r--core/image.cpp251
-rw-r--r--core/image.h13
-rw-r--r--core/image_quantize.cpp2
-rw-r--r--core/input_map.cpp22
-rw-r--r--core/input_map.h4
-rw-r--r--core/int_types.h4
-rw-r--r--core/io/SCsub2
-rw-r--r--core/io/aes256.cpp718
-rw-r--r--core/io/aes256.h92
-rw-r--r--core/io/compression.cpp6
-rw-r--r--core/io/compression.h52
-rw-r--r--core/io/config_file.cpp4
-rw-r--r--core/io/config_file.h2
-rw-r--r--core/io/file_access_buffered.cpp2
-rw-r--r--core/io/file_access_buffered.h2
-rw-r--r--core/io/file_access_buffered_fa.h2
-rw-r--r--core/io/file_access_compressed.cpp2
-rw-r--r--core/io/file_access_compressed.h148
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_memory.cpp52
-rw-r--r--core/io/file_access_memory.h3
-rw-r--r--core/io/file_access_network.cpp3
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.cpp25
-rw-r--r--core/io/file_access_pack.h7
-rw-r--r--core/io/file_access_zip.cpp21
-rw-r--r--core/io/http_client.cpp62
-rw-r--r--core/io/http_client.h10
-rw-r--r--core/io/image_loader.cpp13
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/ioapi.h1
-rw-r--r--core/io/ip.cpp4
-rw-r--r--core/io/ip.h2
-rw-r--r--core/io/ip_address.cpp4
-rw-r--r--core/io/ip_address.h2
-rw-r--r--core/io/json.cpp16
-rw-r--r--core/io/json.h2
-rw-r--r--core/io/marshalls.cpp10
-rw-r--r--core/io/marshalls.h2
-rw-r--r--core/io/packet_peer.cpp26
-rw-r--r--core/io/packet_peer.h10
-rw-r--r--core/io/resource_format_binary.cpp407
-rw-r--r--core/io/resource_format_binary.h18
-rw-r--r--core/io/resource_format_xml.cpp468
-rw-r--r--core/io/resource_format_xml.h29
-rw-r--r--core/io/resource_loader.cpp114
-rw-r--r--core/io/resource_loader.h24
-rw-r--r--core/io/resource_saver.cpp2
-rw-r--r--core/io/resource_saver.h4
-rw-r--r--core/io/stream_peer.cpp2
-rw-r--r--core/io/stream_peer.h2
-rw-r--r--core/io/stream_peer_tcp.cpp4
-rw-r--r--core/io/stream_peer_tcp.h2
-rw-r--r--core/io/tcp_server.cpp2
-rw-r--r--core/io/tcp_server.h2
-rw-r--r--core/io/translation_loader_po.cpp11
-rw-r--r--core/io/translation_loader_po.h4
-rw-r--r--core/io/unzip.c2
-rw-r--r--core/io/xml_parser.cpp2
-rw-r--r--core/io/xml_parser.h2
-rw-r--r--core/io/zip.c4
-rw-r--r--core/io/zip.h2
-rw-r--r--core/io/zip_io.h3
-rw-r--r--core/list.h68
-rw-r--r--core/map.h2
-rw-r--r--core/math/SCsub2
-rw-r--r--core/math/aabb.cpp2
-rw-r--r--core/math/aabb.h14
-rw-r--r--core/math/bezier_curve.cpp2
-rw-r--r--core/math/bezier_curve.h2
-rw-r--r--core/math/bsp_tree.cpp2
-rw-r--r--core/math/bsp_tree.h2
-rw-r--r--core/math/camera_matrix.cpp21
-rw-r--r--core/math/camera_matrix.h2
-rw-r--r--core/math/face3.cpp2
-rw-r--r--core/math/face3.h2
-rw-r--r--core/math/geometry.cpp2
-rw-r--r--core/math/geometry.h16
-rw-r--r--core/math/math_2d.cpp59
-rw-r--r--core/math/math_2d.h197
-rw-r--r--core/math/math_defs.cpp6
-rw-r--r--core/math/math_defs.h66
-rw-r--r--core/math/math_funcs.cpp13
-rw-r--r--core/math/math_funcs.h8
-rw-r--r--core/math/matrix3.cpp2
-rw-r--r--core/math/matrix3.h2
-rw-r--r--core/math/octree.h2
-rw-r--r--core/math/plane.cpp2
-rw-r--r--core/math/plane.h2
-rw-r--r--core/math/quat.cpp2
-rw-r--r--core/math/quat.h4
-rw-r--r--core/math/quick_hull.cpp2
-rw-r--r--core/math/quick_hull.h2
-rw-r--r--core/math/transform.cpp2
-rw-r--r--core/math/transform.h2
-rw-r--r--core/math/triangle_mesh.cpp1082
-rw-r--r--core/math/triangle_mesh.h144
-rw-r--r--core/math/triangulate.cpp2
-rw-r--r--core/math/triangulate.h2
-rw-r--r--core/math/triangulator.cpp1550
-rw-r--r--core/math/triangulator.h306
-rw-r--r--core/math/vector3.cpp21
-rw-r--r--core/math/vector3.h32
-rw-r--r--core/message_queue.cpp21
-rw-r--r--core/message_queue.h2
-rw-r--r--core/method_bind.cpp6
-rw-r--r--core/method_bind.h7
-rw-r--r--core/multi_bucket_array.h2
-rw-r--r--core/object.cpp166
-rw-r--r--core/object.h109
-rw-r--r--core/object_type_db.cpp88
-rw-r--r--core/object_type_db.h26
-rw-r--r--core/os/SCsub2
-rw-r--r--core/os/copymem.cpp2
-rw-r--r--core/os/copymem.h2
-rw-r--r--core/os/dir_access.cpp22
-rw-r--r--core/os/dir_access.h6
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/file_access.h2
-rw-r--r--core/os/input.cpp279
-rw-r--r--core/os/input.h74
-rw-r--r--core/os/input_event.cpp12
-rw-r--r--core/os/input_event.h4
-rw-r--r--core/os/keyboard.cpp107
-rw-r--r--core/os/keyboard.h3
-rw-r--r--core/os/main_loop.cpp32
-rw-r--r--core/os/main_loop.h4
-rw-r--r--core/os/memory.cpp9
-rw-r--r--core/os/memory.h19
-rw-r--r--core/os/memory_pool_dynamic.cpp2
-rw-r--r--core/os/memory_pool_dynamic.h2
-rw-r--r--core/os/memory_pool_dynamic_prealloc.cpp178
-rw-r--r--core/os/memory_pool_dynamic_prealloc.h66
-rw-r--r--core/os/memory_pool_dynamic_static.cpp2
-rw-r--r--core/os/memory_pool_dynamic_static.h2
-rw-r--r--core/os/memory_pool_static.cpp2
-rw-r--r--core/os/memory_pool_static.h2
-rw-r--r--core/os/mutex.cpp2
-rw-r--r--core/os/mutex.h2
-rw-r--r--core/os/os.cpp30
-rw-r--r--core/os/os.h57
-rw-r--r--core/os/pc_joystick_map.h2
-rw-r--r--core/os/semaphore.cpp2
-rw-r--r--core/os/semaphore.h2
-rw-r--r--core/os/shell.cpp2
-rw-r--r--core/os/shell.h2
-rw-r--r--core/os/thread.cpp2
-rw-r--r--core/os/thread.h2
-rw-r--r--core/os/thread_dummy.cpp2
-rw-r--r--core/os/thread_dummy.h2
-rw-r--r--core/os/thread_safe.cpp2
-rw-r--r--core/os/thread_safe.h2
-rw-r--r--core/packed_data_container.cpp2
-rw-r--r--core/packed_data_container.h2
-rw-r--r--core/pair.cpp2
-rw-r--r--core/pair.h2
-rw-r--r--core/path_db.cpp33
-rw-r--r--core/path_db.h7
-rw-r--r--core/path_remap.cpp322
-rw-r--r--core/path_remap.h80
-rw-r--r--core/pool_allocator.cpp2
-rw-r--r--core/pool_allocator.h2
-rw-r--r--core/print_string.cpp3
-rw-r--r--core/print_string.h3
-rw-r--r--core/ref_ptr.cpp2
-rw-r--r--core/ref_ptr.h2
-rw-r--r--core/reference.cpp6
-rw-r--r--core/reference.h6
-rw-r--r--core/register_core_types.cpp9
-rw-r--r--core/register_core_types.h2
-rw-r--r--core/res_ptr.cpp2
-rw-r--r--core/res_ptr.h2
-rw-r--r--core/resource.cpp16
-rw-r--r--core/resource.h8
-rw-r--r--core/rid.cpp2
-rw-r--r--core/rid.h2
-rw-r--r--core/ring_buffer.h10
-rw-r--r--core/safe_refcount.cpp2
-rw-r--r--core/safe_refcount.h2
-rw-r--r--core/script_debugger_debugger.cpp2
-rw-r--r--core/script_debugger_local.cpp18
-rw-r--r--core/script_debugger_local.h2
-rw-r--r--core/script_debugger_remote.cpp292
-rw-r--r--core/script_debugger_remote.h51
-rw-r--r--core/script_language.cpp10
-rw-r--r--core/script_language.h55
-rw-r--r--core/self_list.h2
-rw-r--r--core/set.h39
-rw-r--r--core/simple_type.h2
-rw-r--r--core/sort.h2
-rw-r--r--core/string_db.cpp24
-rw-r--r--core/string_db.h14
-rw-r--r--core/translation.cpp76
-rw-r--r--core/translation.h2
-rw-r--r--core/typedefs.h6
-rw-r--r--core/undo_redo.cpp165
-rw-r--r--core/undo_redo.h20
-rw-r--r--core/ustring.cpp466
-rw-r--r--core/ustring.h17
-rw-r--r--core/variant.cpp395
-rw-r--r--core/variant.h15
-rw-r--r--core/variant_call.cpp98
-rw-r--r--core/variant_call_bind.h2
-rw-r--r--core/variant_construct_string.cpp433
-rw-r--r--core/variant_op.cpp167
-rw-r--r--core/vector.h23
-rw-r--r--core/vmap.cpp2
-rw-r--r--core/vmap.h2
-rw-r--r--core/vset.cpp2
-rw-r--r--core/vset.h2
244 files changed, 8548 insertions, 2647 deletions
diff --git a/core/SCsub b/core/SCsub
index d04041141c..4ce91c794f 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -63,5 +63,3 @@ SConscript('bind/SCsub');
lib = env.Library("core",env.core_sources)
env.Prepend(LIBS=[lib])
-
-
diff --git a/core/allocators.h b/core/allocators.h
index 42eb4effaf..16e516e87b 100644
--- a/core/allocators.h
+++ b/core/allocators.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/array.cpp b/core/array.cpp
index 728ea5941c..ab9f19d6a0 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/array.h b/core/array.h
index 0b8240558f..904309b257 100644
--- a/core/array.h
+++ b/core/array.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/balloon_allocator.h b/core/balloon_allocator.h
index d99f805f52..177c744669 100644
--- a/core/balloon_allocator.h
+++ b/core/balloon_allocator.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/bind/SCsub b/core/bind/SCsub
index c6ba1fa537..7b4a6acbc0 100644
--- a/core/bind/SCsub
+++ b/core/bind/SCsub
@@ -3,5 +3,3 @@ Import('env')
env.add_source_files(env.core_sources,"*.cpp")
Export('env')
-
-
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index ef943b2f7a..94557d149d 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -5,16 +5,16 @@
#include "io/base64.h"
#include "core/globals.h"
#include "io/file_access_encrypted.h"
-
+#include "os/keyboard.h"
_ResourceLoader *_ResourceLoader::singleton=NULL;
Ref<ResourceInteractiveLoader> _ResourceLoader::load_interactive(const String& p_path,const String& p_type_hint) {
return ResourceLoader::load_interactive(p_path,p_type_hint);
}
-RES _ResourceLoader::load(const String &p_path,const String& p_type_hint) {
+RES _ResourceLoader::load(const String &p_path,const String& p_type_hint, bool p_no_cache) {
- RES ret = ResourceLoader::load(p_path,p_type_hint);
+ RES ret = ResourceLoader::load(p_path,p_type_hint, p_no_cache);
return ret;
}
@@ -59,7 +59,7 @@ void _ResourceLoader::_bind_methods() {
ObjectTypeDB::bind_method(_MD("load_interactive:ResourceInteractiveLoader","path","type_hint"),&_ResourceLoader::load_interactive,DEFVAL(""));
- ObjectTypeDB::bind_method(_MD("load:Resource","path","type_hint"),&_ResourceLoader::load,DEFVAL(""));
+ ObjectTypeDB::bind_method(_MD("load:Resource","path","type_hint", "p_no_cache"),&_ResourceLoader::load,DEFVAL(""), DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_recognized_extensions_for_type","type"),&_ResourceLoader::get_recognized_extensions_for_type);
ObjectTypeDB::bind_method(_MD("set_abort_on_missing_resources","abort"),&_ResourceLoader::set_abort_on_missing_resources);
ObjectTypeDB::bind_method(_MD("get_dependencies"),&_ResourceLoader::get_dependencies);
@@ -176,6 +176,76 @@ bool _OS::is_video_mode_fullscreen(int p_screen) const {
}
+
+int _OS::get_screen_count() const {
+ return OS::get_singleton()->get_screen_count();
+}
+
+int _OS::get_current_screen() const {
+ return OS::get_singleton()->get_current_screen();
+}
+
+void _OS::set_current_screen(int p_screen) {
+ OS::get_singleton()->set_current_screen(p_screen);
+}
+
+Point2 _OS::get_screen_position(int p_screen) const {
+ return OS::get_singleton()->get_screen_position(p_screen);
+}
+
+Size2 _OS::get_screen_size(int p_screen) const {
+ return OS::get_singleton()->get_screen_size(p_screen);
+}
+
+Point2 _OS::get_window_position() const {
+ return OS::get_singleton()->get_window_position();
+}
+
+void _OS::set_window_position(const Point2& p_position) {
+ OS::get_singleton()->set_window_position(p_position);
+}
+
+Size2 _OS::get_window_size() const {
+ return OS::get_singleton()->get_window_size();
+}
+
+void _OS::set_window_size(const Size2& p_size) {
+ OS::get_singleton()->set_window_size(p_size);
+}
+
+void _OS::set_window_fullscreen(bool p_enabled) {
+ OS::get_singleton()->set_window_fullscreen(p_enabled);
+}
+
+bool _OS::is_window_fullscreen() const {
+ return OS::get_singleton()->is_window_fullscreen();
+}
+
+void _OS::set_window_resizable(bool p_enabled) {
+ OS::get_singleton()->set_window_resizable(p_enabled);
+}
+
+bool _OS::is_window_resizable() const {
+ return OS::get_singleton()->is_window_resizable();
+}
+
+void _OS::set_window_minimized(bool p_enabled) {
+ OS::get_singleton()->set_window_minimized(p_enabled);
+}
+
+bool _OS::is_window_minimized() const {
+ return OS::get_singleton()->is_window_minimized();
+}
+
+void _OS::set_window_maximized(bool p_enabled) {
+ OS::get_singleton()->set_window_maximized(p_enabled);
+}
+
+bool _OS::is_window_maximized() const {
+ return OS::get_singleton()->is_window_maximized();
+}
+
+
void _OS::set_use_file_access_save_and_swap(bool p_enable) {
FileAccess::set_backup_save(p_enable);
@@ -186,7 +256,6 @@ bool _OS::is_video_mode_resizable(int p_screen) const {
OS::VideoMode vm;
vm = OS::get_singleton()->get_video_mode(p_screen);
return vm.resizable;
-
}
Array _OS::get_fullscreen_mode_list(int p_screen) const {
@@ -316,6 +385,11 @@ float _OS::get_time_scale() {
return OS::get_singleton()->get_time_scale();
}
+bool _OS::is_ok_left_and_cancel_right() const {
+
+ return OS::get_singleton()->get_swap_ok_cancel();
+}
+
/*
enum Weekday {
DAY_SUNDAY,
@@ -383,9 +457,9 @@ void _OS::set_icon(const Image& p_icon) {
OS::get_singleton()->set_icon(p_icon);
}
-Dictionary _OS::get_date() const {
+Dictionary _OS::get_date(bool utc) const {
- OS::Date date = OS::get_singleton()->get_date();
+ OS::Date date = OS::get_singleton()->get_date(utc);
Dictionary dated;
dated["year"]=date.year;
dated["month"]=date.month;
@@ -396,9 +470,9 @@ Dictionary _OS::get_date() const {
}
-Dictionary _OS::get_time() const {
+Dictionary _OS::get_time(bool utc) const {
- OS::Time time = OS::get_singleton()->get_time();
+ OS::Time time = OS::get_singleton()->get_time(utc);
Dictionary timed;
timed["hour"]=time.hour;
timed["minute"]=time.min;
@@ -406,11 +480,24 @@ Dictionary _OS::get_time() const {
return timed;
}
+
+Dictionary _OS::get_time_zone_info() const {
+ OS::TimeZoneInfo info = OS::get_singleton()->get_time_zone_info();
+ Dictionary infod;
+ infod["bias"] = info.bias;
+ infod["name"] = info.name;
+ return infod;
+}
+
uint64_t _OS::get_unix_time() const {
return OS::get_singleton()->get_unix_time();
};
+uint64_t _OS::get_system_time_msec() const {
+ return OS::get_singleton()->get_system_time_msec();
+}
+
void _OS::delay_usec(uint32_t p_usec) const {
OS::get_singleton()->delay_usec(p_usec);
@@ -426,6 +513,10 @@ uint32_t _OS::get_ticks_msec() const {
return OS::get_singleton()->get_ticks_msec();
}
+uint32_t _OS::get_splash_tick_msec() const {
+
+ return OS::get_singleton()->get_splash_tick_msec();
+}
bool _OS::can_use_threads() const {
@@ -607,6 +698,17 @@ bool _OS::is_debug_build() const {
}
+void _OS::set_screen_orientation(ScreenOrientation p_orientation) {
+
+ OS::get_singleton()->set_screen_orientation(OS::ScreenOrientation(p_orientation));
+}
+
+_OS::ScreenOrientation _OS::get_screen_orientation() const {
+
+ return ScreenOrientation(OS::get_singleton()->get_screen_orientation());
+}
+
+
String _OS::get_system_dir(SystemDir p_dir) const {
return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir));
@@ -616,6 +718,25 @@ String _OS::get_custom_level() const {
return OS::get_singleton()->get_custom_level();
}
+
+String _OS::get_scancode_string(uint32_t p_code) const {
+
+ return keycode_get_string(p_code);
+}
+bool _OS::is_scancode_unicode(uint32_t p_unicode) const {
+
+ return keycode_has_unicode(p_unicode);
+}
+int _OS::find_scancode_from_string(const String& p_code) const {
+
+ return find_keycode(p_code);
+}
+
+void _OS::alert(const String& p_alert,const String& p_title) {
+
+ OS::get_singleton()->alert(p_alert,p_title);
+}
+
_OS *_OS::singleton=NULL;
void _OS::_bind_methods() {
@@ -632,6 +753,29 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
+
+ ObjectTypeDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
+ ObjectTypeDB::bind_method(_MD("get_current_screen"),&_OS::get_current_screen);
+ ObjectTypeDB::bind_method(_MD("set_current_screen","screen"),&_OS::set_current_screen);
+ ObjectTypeDB::bind_method(_MD("get_screen_position","screen"),&_OS::get_screen_position,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_screen_size","screen"),&_OS::get_screen_size,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
+ ObjectTypeDB::bind_method(_MD("set_window_position","position"),&_OS::set_window_position);
+ ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
+ ObjectTypeDB::bind_method(_MD("set_window_size","size"),&_OS::set_window_size);
+ ObjectTypeDB::bind_method(_MD("set_window_fullscreen","enabled"),&_OS::set_window_fullscreen);
+ ObjectTypeDB::bind_method(_MD("is_window_fullscreen"),&_OS::is_window_fullscreen);
+ ObjectTypeDB::bind_method(_MD("set_window_resizable","enabled"),&_OS::set_window_resizable);
+ ObjectTypeDB::bind_method(_MD("is_window_resizable"),&_OS::is_window_resizable);
+ ObjectTypeDB::bind_method(_MD("set_window_minimized", "enabled"),&_OS::set_window_minimized);
+ ObjectTypeDB::bind_method(_MD("is_window_minimized"),&_OS::is_window_minimized);
+ ObjectTypeDB::bind_method(_MD("set_window_maximized", "enabled"),&_OS::set_window_maximized);
+ ObjectTypeDB::bind_method(_MD("is_window_maximized"),&_OS::is_window_maximized);
+
+ ObjectTypeDB::bind_method(_MD("set_screen_orientation","orientation"),&_OS::set_screen_orientation);
+ ObjectTypeDB::bind_method(_MD("get_screen_orientation"),&_OS::get_screen_orientation);
+
+
ObjectTypeDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_OS::set_iterations_per_second);
ObjectTypeDB::bind_method(_MD("get_iterations_per_second"),&_OS::get_iterations_per_second);
ObjectTypeDB::bind_method(_MD("set_target_fps","target_fps"),&_OS::set_target_fps);
@@ -642,7 +786,7 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("has_touchscreen_ui_hint"),&_OS::has_touchscreen_ui_hint);
-
+ ObjectTypeDB::bind_method(_MD("set_window_title","title"),&_OS::set_window_title);
ObjectTypeDB::bind_method(_MD("set_low_processor_usage_mode","enable"),&_OS::set_low_processor_usage_mode);
ObjectTypeDB::bind_method(_MD("is_in_low_processor_usage_mode"),&_OS::is_in_low_processor_usage_mode);
@@ -662,15 +806,18 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_cmdline_args"),&_OS::get_cmdline_args);
ObjectTypeDB::bind_method(_MD("get_main_loop"),&_OS::get_main_loop);
- ObjectTypeDB::bind_method(_MD("get_date"),&_OS::get_date);
- ObjectTypeDB::bind_method(_MD("get_time"),&_OS::get_time);
+ ObjectTypeDB::bind_method(_MD("get_date","utc"),&_OS::get_date,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("get_time","utc"),&_OS::get_time,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("get_time_zone_info"),&_OS::get_time_zone_info);
ObjectTypeDB::bind_method(_MD("get_unix_time"),&_OS::get_unix_time);
+ ObjectTypeDB::bind_method(_MD("get_system_time_msec"), &_OS::get_system_time_msec);
ObjectTypeDB::bind_method(_MD("set_icon"),&_OS::set_icon);
ObjectTypeDB::bind_method(_MD("delay_usec","usec"),&_OS::delay_usec);
ObjectTypeDB::bind_method(_MD("delay_msec","msec"),&_OS::delay_msec);
ObjectTypeDB::bind_method(_MD("get_ticks_msec"),&_OS::get_ticks_msec);
+ ObjectTypeDB::bind_method(_MD("get_splash_tick_msec"),&_OS::get_splash_tick_msec);
ObjectTypeDB::bind_method(_MD("get_locale"),&_OS::get_locale);
ObjectTypeDB::bind_method(_MD("get_model_name"),&_OS::get_model_name);
@@ -699,6 +846,8 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_system_dir","dir"),&_OS::get_system_dir);
ObjectTypeDB::bind_method(_MD("get_unique_ID"),&_OS::get_unique_ID);
+ ObjectTypeDB::bind_method(_MD("is_ok_left_and_cancel_right"),&_OS::is_ok_left_and_cancel_right);
+
ObjectTypeDB::bind_method(_MD("get_frames_per_second"),&_OS::get_frames_per_second);
ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);
@@ -709,9 +858,13 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("native_video_stop"),&_OS::native_video_stop);
ObjectTypeDB::bind_method(_MD("native_video_pause"),&_OS::native_video_pause);
+ ObjectTypeDB::bind_method(_MD("get_scancode_string","code"),&_OS::get_scancode_string);
+ ObjectTypeDB::bind_method(_MD("is_scancode_unicode","code"),&_OS::is_scancode_unicode);
+ ObjectTypeDB::bind_method(_MD("find_scancode_from_string","string"),&_OS::find_scancode_from_string);
ObjectTypeDB::bind_method(_MD("set_use_file_access_save_and_swap","enabled"),&_OS::set_use_file_access_save_and_swap);
+ ObjectTypeDB::bind_method(_MD("alert","text","title"),&_OS::alert,DEFVAL("Alert!"));
BIND_CONSTANT( DAY_SUNDAY );
@@ -735,6 +888,14 @@ void _OS::_bind_methods() {
BIND_CONSTANT( MONTH_NOVEMBER );
BIND_CONSTANT( MONTH_DECEMBER );
+ BIND_CONSTANT( SCREEN_ORIENTATION_LANDSCAPE );
+ BIND_CONSTANT( SCREEN_ORIENTATION_PORTRAIT );
+ BIND_CONSTANT( SCREEN_ORIENTATION_REVERSE_LANDSCAPE );
+ BIND_CONSTANT( SCREEN_ORIENTATION_REVERSE_PORTRAIT );
+ BIND_CONSTANT( SCREEN_ORIENTATION_SENSOR_LANDSCAPE );
+ BIND_CONSTANT( SCREEN_ORIENTATION_SENSOR_PORTRAIT );
+ BIND_CONSTANT( SCREEN_ORIENTATION_SENSOR );
+
BIND_CONSTANT( SYSTEM_DIR_DESKTOP);
BIND_CONSTANT( SYSTEM_DIR_DCIM );
BIND_CONSTANT( SYSTEM_DIR_DOCUMENTS );
@@ -838,6 +999,12 @@ Variant _Geometry::segment_intersects_triangle( const Vector3& p_from, const Vec
return Variant();
}
+
+bool _Geometry::point_is_inside_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c) const {
+
+ return Geometry::is_point_in_triangle(s,a,b,c);
+}
+
DVector<Vector3> _Geometry::segment_intersects_sphere( const Vector3& p_from, const Vector3& p_to, const Vector3& p_sphere_pos,real_t p_sphere_radius) {
DVector<Vector3> r;
@@ -938,6 +1105,7 @@ void _Geometry::_bind_methods() {
ObjectTypeDB::bind_method(_MD("segment_intersects_sphere","from","to","spos","sradius"),&_Geometry::segment_intersects_sphere);
ObjectTypeDB::bind_method(_MD("segment_intersects_cylinder","from","to","height","radius"),&_Geometry::segment_intersects_cylinder);
ObjectTypeDB::bind_method(_MD("segment_intersects_convex","from","to","planes"),&_Geometry::segment_intersects_convex);
+ ObjectTypeDB::bind_method(_MD("point_is_inside_triangle","point","a","b","c"),&_Geometry::point_is_inside_triangle);
ObjectTypeDB::bind_method(_MD("triangulate_polygon","polygon"),&_Geometry::triangulate_polygon);
@@ -1121,6 +1289,7 @@ String _File::get_as_text() const {
text+=l+"\n";
l = get_line();
}
+ text+=l;
return text;
@@ -1542,12 +1711,89 @@ Variant _Marshalls::base64_to_variant(const String& p_str) {
return v;
};
+String _Marshalls::raw_to_base64(const DVector<uint8_t> &p_arr) {
+
+ int len = p_arr.size();
+ DVector<uint8_t>::Read r = p_arr.read();
+
+ int b64len = len / 3 * 4 + 4 + 1;
+ DVector<uint8_t> b64buff;
+ b64buff.resize(b64len);
+ DVector<uint8_t>::Write w64 = b64buff.write();
+
+ int strlen = base64_encode((char*)(&w64[0]), (char*)(&r[0]), len);
+ w64[strlen] = 0;
+ String ret = (char*)&w64[0];
+
+ return ret;
+};
+
+DVector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
+
+ int strlen = p_str.length();
+ CharString cstr = p_str.ascii();
+
+ int arr_len;
+ DVector<uint8_t> buf;
+ {
+ buf.resize(strlen / 4 * 3 + 1);
+ DVector<uint8_t>::Write w = buf.write();
+
+ arr_len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen);
+ };
+ buf.resize(arr_len);
+
+ // conversion from DVector<uint8_t> to raw array?
+ return buf;
+};
+
+String _Marshalls::utf8_to_base64(const String& p_str) {
+
+ CharString cstr = p_str.utf8();
+ int len = cstr.length();
+
+ int b64len = len / 3 * 4 + 4 + 1;
+ DVector<uint8_t> b64buff;
+ b64buff.resize(b64len);
+ DVector<uint8_t>::Write w64 = b64buff.write();
+
+ int strlen = base64_encode((char*)(&w64[0]), (char*)cstr.get_data(), len);
+
+ w64[strlen] = 0;
+ String ret = (char*)&w64[0];
+
+ return ret;
+};
+
+String _Marshalls::base64_to_utf8(const String& p_str) {
+
+ int strlen = p_str.length();
+ CharString cstr = p_str.ascii();
+
+ DVector<uint8_t> buf;
+ buf.resize(strlen / 4 * 3 + 1 + 1);
+ DVector<uint8_t>::Write w = buf.write();
+
+ int len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen);
+
+ w[len] = 0;
+ String ret = String::utf8((char*)&w[0]);
+
+ return ret;
+};
+
void _Marshalls::_bind_methods() {
ObjectTypeDB::bind_method(_MD("variant_to_base64:String","variant"),&_Marshalls::variant_to_base64);
ObjectTypeDB::bind_method(_MD("base64_to_variant:Variant","base64_str"),&_Marshalls::base64_to_variant);
+ ObjectTypeDB::bind_method(_MD("raw_to_base64:String","array"),&_Marshalls::raw_to_base64);
+ ObjectTypeDB::bind_method(_MD("base64_to_raw:RawArray","base64_str"),&_Marshalls::base64_to_raw);
+
+ ObjectTypeDB::bind_method(_MD("utf8_to_base64:String","utf8_str"),&_Marshalls::utf8_to_base64);
+ ObjectTypeDB::bind_method(_MD("base64_to_utf8:String","base64_str"),&_Marshalls::base64_to_utf8);
+
};
@@ -1631,9 +1877,12 @@ _Mutex::~_Mutex(){
void _Thread::_start_func(void *ud) {
- _Thread *t=(_Thread*)ud;
+ Ref<_Thread>* tud=(Ref<_Thread>*)ud;
+ Ref<_Thread> t=*tud;
+ memdelete(tud);
Variant::CallError ce;
const Variant* arg[1]={&t->userdata};
+
t->ret=t->target_instance->call(t->target_method,arg,1,ce);
if (ce.error!=Variant::CallError::CALL_OK) {
@@ -1658,6 +1907,7 @@ void _Thread::_start_func(void *ud) {
default: {}
}
+
ERR_EXPLAIN("Could not call function '"+t->target_method.operator String()+"'' starting thread ID: "+t->get_id()+" Reason: "+reason);
ERR_FAIL();
}
@@ -1678,9 +1928,11 @@ Error _Thread::start(Object *p_instance,const StringName& p_method,const Variant
userdata=p_userdata;
active=true;
+ Ref<_Thread> *ud = memnew( Ref<_Thread>(this) );
+
Thread::Settings s;
s.priority=(Thread::Priority)p_priority;
- thread = Thread::create(_start_func,this,s);
+ thread = Thread::create(_start_func,ud,s);
if (!thread) {
active=false;
target_method=StringName();
@@ -1741,5 +1993,8 @@ _Thread::_Thread() {
_Thread::~_Thread() {
+ if (active) {
+ ERR_EXPLAIN("Reference to a Thread object object was lost while the thread is still running..");
+ }
ERR_FAIL_COND(active==true);
}
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index a76b4aa81f..24ea810767 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -21,7 +21,7 @@ public:
static _ResourceLoader *get_singleton() { return singleton; }
Ref<ResourceInteractiveLoader> load_interactive(const String& p_path,const String& p_type_hint="");
- RES load(const String &p_path,const String& p_type_hint="");
+ RES load(const String &p_path,const String& p_type_hint="", bool p_no_cache = false);
DVector<String> get_recognized_extensions_for_type(const String& p_type);
void set_abort_on_missing_resources(bool p_abort);
StringArray get_dependencies(const String& p_path);
@@ -108,6 +108,26 @@ public:
bool is_video_mode_resizable(int p_screen=0) const;
Array get_fullscreen_mode_list(int p_screen=0) const;
+
+ 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) const;
+ virtual Size2 get_screen_size(int p_screen=0) const;
+ virtual Point2 get_window_position() const;
+ virtual void set_window_position(const Point2& p_position);
+ virtual Size2 get_window_size() const;
+ virtual void set_window_size(const Size2& p_size);
+ virtual void set_window_fullscreen(bool p_enabled);
+ virtual bool is_window_fullscreen() const;
+ virtual void set_window_resizable(bool p_enabled);
+ virtual bool is_window_resizable() const;
+ virtual void set_window_minimized(bool p_enabled);
+ virtual bool is_window_minimized() const;
+ virtual void set_window_maximized(bool p_enabled);
+ virtual bool is_window_maximized() const;
+
+
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
bool native_video_is_playing();
void native_video_pause();
@@ -158,6 +178,11 @@ public:
String get_unique_ID() const;
+ String get_scancode_string(uint32_t p_code) const;
+ bool is_scancode_unicode(uint32_t p_unicode) const;
+ int find_scancode_from_string(const String& p_code) const;
+
+
/*
struct Date {
@@ -179,9 +204,11 @@ public:
void set_use_file_access_save_and_swap(bool p_enable);
void set_icon(const Image& p_icon);
- Dictionary get_date() const;
- Dictionary get_time() const;
+ Dictionary get_date(bool utc) const;
+ Dictionary get_time(bool utc) const;
+ Dictionary get_time_zone_info() const;
uint64_t get_unix_time() const;
+ uint64_t get_system_time_msec() const;
int get_static_memory_usage() const;
int get_static_memory_peak_usage() const;
@@ -190,6 +217,7 @@ public:
void delay_usec(uint32_t p_usec) const;
void delay_msec(uint32_t p_msec) const;
uint32_t get_ticks_msec() const;
+ uint32_t get_splash_tick_msec() const;
bool can_use_threads() const;
@@ -212,20 +240,40 @@ public:
SYSTEM_DIR_RINGTONES,
};
+ enum ScreenOrientation {
+
+ SCREEN_ORIENTATION_LANDSCAPE,
+ SCREEN_ORIENTATION_PORTRAIT,
+ SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
+ SCREEN_ORIENTATION_REVERSE_PORTRAIT,
+ SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
+ SCREEN_ORIENTATION_SENSOR_PORTRAIT,
+ SCREEN_ORIENTATION_SENSOR,
+ };
+
String get_system_dir(SystemDir p_dir) const;
String get_data_dir() const;
+ void alert(const String& p_alert,const String& p_title="ALERT!");
+
+
+ void set_screen_orientation(ScreenOrientation p_orientation);
+ ScreenOrientation get_screen_orientation() const;
+
void set_time_scale(float p_scale);
float get_time_scale();
+ bool is_ok_left_and_cancel_right() const;
+
static _OS *get_singleton() { return singleton; }
_OS();
};
VARIANT_ENUM_CAST(_OS::SystemDir);
+VARIANT_ENUM_CAST(_OS::ScreenOrientation);
class _Geometry : public Object {
@@ -248,6 +296,8 @@ public:
Vector3 get_closest_point_to_segment(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b);
Variant ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
Variant segment_intersects_triangle( const Vector3& p_from, const Vector3& p_to, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
+ bool point_is_inside_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c) const;
+
DVector<Vector3> segment_intersects_sphere( const Vector3& p_from, const Vector3& p_to, const Vector3& p_sphere_pos,real_t p_sphere_radius);
DVector<Vector3> segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, float p_height,float p_radius);
DVector<Vector3> segment_intersects_convex(const Vector3& p_from, const Vector3& p_to,const Vector<Plane>& p_planes);
@@ -405,6 +455,12 @@ public:
String variant_to_base64(const Variant& p_var);
Variant base64_to_variant(const String& p_str);
+ String raw_to_base64(const DVector<uint8_t>& p_arr);
+ DVector<uint8_t> base64_to_raw(const String& p_str);
+
+ String utf8_to_base64(const String& p_str);
+ String base64_to_utf8(const String& p_str);
+
_Marshalls() {};
};
diff --git a/core/color.cpp b/core/color.cpp
index 1528db6aaa..32f3df6d4b 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -161,7 +161,7 @@ void Color::invert() {
r=1.0-r;
g=1.0-g;
- g=1.0-b;
+ b=1.0-b;
}
void Color::contrast() {
@@ -225,7 +225,7 @@ Color Color::inverted() const {
Color Color::contrasted() const {
Color c=*this;
- c.contrasted();
+ c.contrast();
return c;
}
diff --git a/core/color.h b/core/color.h
index 491c72d449..d5d5a4ea09 100644
--- a/core/color.h
+++ b/core/color.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp
index 78151b858f..f28617b33c 100644
--- a/core/command_queue_mt.cpp
+++ b/core/command_queue_mt.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index 8b74b3b561..113199869b 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "os/mutex.h"
#include "os/memory.h"
#include "simple_type.h"
+#include "print_string.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -174,7 +175,7 @@ class CommandQueueMT {
R* ret;
SyncSemaphore *sync;
- virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
+ virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); print_line("post"); sync->in_use=false; ; }
};
template<class T,class M,class P1,class P2,class R>
@@ -675,6 +676,7 @@ public:
if (sync) sync->post();
ss->sem->wait();
+ print_line("wait");
}
template<class T, class M, class P1, class P2,class R>
diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp
index 0c97f459f8..45fd4b5080 100644
--- a/core/compressed_translation.cpp
+++ b/core/compressed_translation.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/compressed_translation.h b/core/compressed_translation.h
index a0b94116de..c41e2afb53 100644
--- a/core/compressed_translation.h
+++ b/core/compressed_translation.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index 75cb48137b..d0cd19768f 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,6 +42,7 @@ CoreStringNames::CoreStringNames() {
_iter_init=StaticCString::create("_iter_init");
_iter_next=StaticCString::create("_iter_next");
_iter_get=StaticCString::create("_iter_get");
+ get_rid=StaticCString::create("get_rid");
}
diff --git a/core/core_string_names.h b/core/core_string_names.h
index e2982acc1a..8bda1f3f79 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,6 +56,7 @@ public:
StringName _iter_init;
StringName _iter_next;
StringName _iter_get;
+ StringName get_rid;
};
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index 16ee397382..b2d31f230d 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -186,10 +186,12 @@ Error Dictionary::parse_json(const String& p_json) {
String errstr;
int errline=0;
+ if (p_json != ""){
Error err = JSON::parse(p_json,*this,errstr,errline);
if (err!=OK) {
ERR_EXPLAIN("Error parsing JSON: "+errstr+" at line: "+itos(errline));
ERR_FAIL_COND_V(err!=OK,err);
+ }
}
return OK;
diff --git a/core/dictionary.h b/core/dictionary.h
index de5be0fc6b..8cbabfc65d 100644
--- a/core/dictionary.h
+++ b/core/dictionary.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/dvector.cpp b/core/dvector.cpp
index e0a378a427..60aa2e079f 100644
--- a/core/dvector.cpp
+++ b/core/dvector.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/dvector.h b/core/dvector.h
index 72661882cd..2c75bbf9eb 100644
--- a/core/dvector.h
+++ b/core/dvector.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -262,6 +262,23 @@ public:
w[bs+i]=r[i];
}
+
+ Error insert(int p_pos,const T& p_val) {
+
+ int s=size();
+ ERR_FAIL_INDEX_V(p_pos,s+1,ERR_INVALID_PARAMETER);
+ resize(s+1);
+ {
+ Write w = write();
+ for (int i=s;i>p_pos;i--)
+ w[i]=w[i-1];
+ w[p_pos]=p_val;
+ }
+
+ return OK;
+ }
+
+
bool is_locked() const { return mem.is_locked(); }
inline const T operator[](int p_index) const;
diff --git a/core/error_list.h b/core/error_list.h
index 2127938769..92c417154c 100644
--- a/core/error_list.h
+++ b/core/error_list.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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.cpp b/core/error_macros.cpp
index bd08cbb2f5..53bce56626 100644
--- a/core/error_macros.cpp
+++ b/core/error_macros.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/error_macros.h b/core/error_macros.h
index 6cd38755c0..76da88287b 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/event_queue.cpp b/core/event_queue.cpp
index cf6e742f79..1afd686f86 100644
--- a/core/event_queue.cpp
+++ b/core/event_queue.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,28 +56,36 @@ Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method,
buffer_end+=sizeof(Event);
- if (args==1) {
+ if (args>=1) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg1;
- } else if (args==2) {
+ }
+
+ if (args>=2) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg2;
- } else if (args==3) {
+ }
+
+ if (args>=3) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg3;
- } else if (args==4) {
+ }
+
+ if (args>=4) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg4;
- } else if (args==5) {
+ }
+
+ if (args>=5) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
diff --git a/core/event_queue.h b/core/event_queue.h
index 0647c02777..51ed7373eb 100644
--- a/core/event_queue.h
+++ b/core/event_queue.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/fpstr.cpp b/core/fpstr.cpp
index 25784adb15..20b527d88b 100644
--- a/core/fpstr.cpp
+++ b/core/fpstr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/fpstr.h b/core/fpstr.h
index d07ae7d5a2..c8ff80806e 100644
--- a/core/fpstr.h
+++ b/core/fpstr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 0e43112de8..66962710bd 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -31,8 +31,7 @@ void FuncRef::_bind_methods() {
{
MethodInfo mi;
- mi.name="call";
- mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
+ mi.name="call_func";
Vector<Variant> defargs;
for(int i=0;i<10;i++) {
mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index ae4abc627d..9fb45c672a 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -313,6 +313,7 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( KEY_MASK_ALT ),
BIND_GLOBAL_CONSTANT( KEY_MASK_META ),
BIND_GLOBAL_CONSTANT( KEY_MASK_CTRL ),
+ BIND_GLOBAL_CONSTANT( KEY_MASK_CMD ),
BIND_GLOBAL_CONSTANT( KEY_MASK_KPAD ),
BIND_GLOBAL_CONSTANT( KEY_MASK_GROUP_SWITCH ),
@@ -421,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/global_constants.h b/core/global_constants.h
index cd8304bd45..77cd3724c6 100644
--- a/core/global_constants.h
+++ b/core/global_constants.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/globals.cpp b/core/globals.cpp
index a39ace7360..ffd4cf5d5e 100644
--- a/core/globals.cpp
+++ b/core/globals.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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();
@@ -339,7 +339,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) {
//try to load settings in ascending through dirs shape!
//tries to open pack, but only first time
- if (first_time && _load_resource_pack(current_dir+"/data.pck")) {
+ if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) {
if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) {
_load_settings("res://override.cfg");
@@ -1149,6 +1149,12 @@ Error Globals::_save_settings_text(const String& p_file,const Map<String,List<St
return OK;
}
+
+Error Globals::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
+
+ return save_custom(p_file);
+};
+
Error Globals::save_custom(const String& p_path,const CustomMap& p_custom,const Set<String>& p_ignore_masks) {
ERR_FAIL_COND_V(p_path=="",ERR_INVALID_PARAMETER);
@@ -1321,7 +1327,7 @@ Vector<String> Globals::get_optimizer_presets() const {
if (!E->get().name.begins_with("optimizer_presets/"))
continue;
- names.push_back(E->get().name.get_slice("/",1));
+ names.push_back(E->get().name.get_slicec('/',1));
}
names.sort();
@@ -1361,6 +1367,9 @@ void Globals::_bind_methods() {
ObjectTypeDB::bind_method(_MD("has_singleton"),&Globals::has_singleton);
ObjectTypeDB::bind_method(_MD("get_singleton"),&Globals::get_singleton_object);
ObjectTypeDB::bind_method(_MD("load_resource_pack"),&Globals::_load_resource_pack);
+
+ ObjectTypeDB::bind_method(_MD("save_custom"),&Globals::_save_custom_bnd);
+
}
Globals::Globals() {
@@ -1381,7 +1390,7 @@ Globals::Globals() {
set("application/name","" );
set("application/main_scene","");
- custom_prop_info["application/main_scene"]=PropertyInfo(Variant::STRING,"application/main_scene",PROPERTY_HINT_FILE,"xml,res,scn,xscn");
+ custom_prop_info["application/main_scene"]=PropertyInfo(Variant::STRING,"application/main_scene",PROPERTY_HINT_FILE,"scn,res,xscn,xml");
set("application/disable_stdout",false);
set("application/use_shared_user_dir",true);
@@ -1397,6 +1406,13 @@ Globals::Globals() {
set("input/ui_accept",va);
va=Array();
+ key.key.scancode=KEY_SPACE;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_BUTTON_3;
+ va.push_back(joyb);
+ set("input/ui_select",va);
+
+ va=Array();
key.key.scancode=KEY_ESCAPE;
va.push_back(key);
joyb.joy_button.button_index=JOY_BUTTON_1;
@@ -1460,7 +1476,7 @@ Globals::Globals() {
custom_prop_info["display/orientation"]=PropertyInfo(Variant::STRING,"display/orientation",PROPERTY_HINT_ENUM,"landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
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");
- set("display/emulate_touchscreen",false);
+ custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
using_datapack=false;
}
diff --git a/core/globals.h b/core/globals.h
index 580fd0fecd..2ec56966f6 100644
--- a/core/globals.h
+++ b/core/globals.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -86,6 +86,7 @@ protected:
List<Singleton> singletons;
+ Error _save_custom_bnd(const String& p_file);
bool _load_resource_pack(const String& p_pack);
diff --git a/core/hash_map.h b/core/hash_map.h
index da8f038490..eea6d1a153 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/hashfuncs.h b/core/hashfuncs.h
index 3b6715a4cd..b12950f160 100644
--- a/core/hashfuncs.h
+++ b/core/hashfuncs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/image.cpp b/core/image.cpp
index 17ee569b6b..eadb7ecc8b 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,33 @@
#include "print_string.h"
#include <stdio.h>
+
+const char* Image::format_names[Image::FORMAT_MAX]={
+ "Grayscale",
+ "Intensity",
+ "GrayscaleAlpha",
+ "RGB",
+ "RGBA",
+ "Indexed",
+ "IndexedAlpha",
+ "YUV422",
+ "YUV444",
+ "BC1",
+ "BC2",
+ "BC3",
+ "BC4",
+ "BC5",
+ "PVRTC2",
+ "PVRTC2Alpha",
+ "PVRTC4",
+ "PVRTC4Alpha",
+ "ETC",
+ "ATC",
+ "ATCAlphaExp",
+ "ATCAlphaInterp",
+
+};
+
SavePNGFunc Image::save_png_func = NULL;
void Image::_put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data) {
@@ -134,6 +161,18 @@ void Image::get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) con
}
+void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const {
+
+
+ int ofs;
+ _get_mipmap_offset_and_size(p_mipmap,ofs,w,h);
+ int ofs2,w2,h2;
+ _get_mipmap_offset_and_size(p_mipmap+1,ofs2,w2,h2);
+ r_ofs=ofs;
+ r_size=ofs2-ofs;
+
+}
+
void Image::put_pixel(int p_x,int p_y, const Color& p_color,int p_mipmap){
ERR_FAIL_INDEX(p_mipmap,mipmaps+1);
@@ -283,7 +322,7 @@ void Image::set_pallete(const DVector<uint8_t>& p_data) {
DVector<uint8_t>::Write wp = data.write();
unsigned char *dst=wp.ptr() + pal_ofs;
- DVector<uint8_t>::Read r = data.read();
+ DVector<uint8_t>::Read r = p_data.read();
const unsigned char *src=r.ptr();
copymem(dst, src, len);
@@ -388,6 +427,102 @@ Image::Format Image::get_format() const{
return format;
}
+static double _bicubic_interp_kernel( double x ) {
+
+ x = ABS(x);
+
+ double bc = 0;
+
+ if ( x <= 1 )
+ bc = ( 1.5 * x - 2.5 ) * x * x + 1;
+ else if ( x < 2 )
+ bc = ( ( -0.5 * x + 2.5 ) * x - 4 ) * x + 2;
+
+
+ return bc;
+}
+
+template<int CC>
+static void _scale_cubic(const uint8_t* p_src, uint8_t* p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
+
+
+ // get source image size
+ int width = p_src_width;
+ int height = p_src_height;
+ double xfac = (double) width / p_dst_width;
+ double yfac = (double) height / p_dst_height;
+ // coordinates of source points and cooefficiens
+ double ox, oy, dx, dy, k1, k2;
+ int ox1, oy1, ox2, oy2;
+ // destination pixel values
+ // width and height decreased by 1
+ int ymax = height - 1;
+ int xmax = width - 1;
+ // temporary pointer
+
+ for ( int y = 0; y < p_dst_height; y++ ) {
+ // Y coordinates
+ oy = (double) y * yfac - 0.5f;
+ oy1 = (int) oy;
+ dy = oy - (double) oy1;
+
+ for ( int x = 0; x < p_dst_width; x++ ) {
+ // X coordinates
+ ox = (double) x * xfac - 0.5f;
+ ox1 = (int) ox;
+ dx = ox - (double) ox1;
+
+ // initial pixel value
+
+ uint8_t *dst=p_dst + (y*p_dst_width+x)*CC;
+
+ double color[CC];
+ for(int i=0;i<CC;i++) {
+ color[i]=0;
+ }
+
+
+
+ for ( int n = -1; n < 3; n++ ) {
+ // get Y cooefficient
+ k1 = _bicubic_interp_kernel( dy - (double) n );
+
+ oy2 = oy1 + n;
+ if ( oy2 < 0 )
+ oy2 = 0;
+ if ( oy2 > ymax )
+ oy2 = ymax;
+
+ for ( int m = -1; m < 3; m++ ) {
+ // get X cooefficient
+ k2 = k1 * _bicubic_interp_kernel( (double) m - dx );
+
+ ox2 = ox1 + m;
+ if ( ox2 < 0 )
+ ox2 = 0;
+ if ( ox2 > xmax )
+ ox2 = xmax;
+
+ // get pixel of original image
+ const uint8_t *p = p_src + (oy2 * p_src_width + ox2)*CC;
+
+ for(int i=0;i<CC;i++) {
+
+ color[i]+=p[i]*k2;
+ }
+ }
+ }
+
+ for(int i=0;i<CC;i++) {
+ dst[i]=CLAMP(Math::fast_ftoi(color[i]),0,255);
+ }
+ }
+ }
+}
+
+
+
+
template<int CC>
static void _scale_bilinear(const uint8_t* p_src, uint8_t* p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
@@ -547,6 +682,17 @@ void Image::resize( int p_width, int p_height, Interpolation p_interpolation ) {
}
} break;
+ case INTERPOLATE_CUBIC: {
+
+ switch(get_format_pixel_size(format)) {
+ case 1: _scale_cubic<1>(r_ptr,w_ptr,width,height,p_width,p_height); break;
+ case 2: _scale_cubic<2>(r_ptr,w_ptr,width,height,p_width,p_height); break;
+ case 3: _scale_cubic<3>(r_ptr,w_ptr,width,height,p_width,p_height); break;
+ case 4: _scale_cubic<4>(r_ptr,w_ptr,width,height,p_width,p_height); break;
+ }
+
+ } break;
+
}
@@ -1004,10 +1150,10 @@ void Image::create( const char ** p_xpm ) {
String line_str=line_ptr;
line_str.replace("\t"," ");
- size_width=line_str.get_slice(" ",0).to_int();
- size_height=line_str.get_slice(" ",1).to_int();
- colormap_size=line_str.get_slice(" ",2).to_int();
- pixelchars=line_str.get_slice(" ",3).to_int();
+ size_width=line_str.get_slicec(' ',0).to_int();
+ size_height=line_str.get_slicec(' ',1).to_int();
+ colormap_size=line_str.get_slicec(' ',2).to_int();
+ pixelchars=line_str.get_slicec(' ',3).to_int();
ERR_FAIL_COND(colormap_size > 32766);
ERR_FAIL_COND(pixelchars > 5);
ERR_FAIL_COND(size_width > 32767);
@@ -1112,6 +1258,7 @@ void Image::create( const char ** p_xpm ) {
}
#define DETECT_ALPHA_MAX_TRESHOLD 254
#define DETECT_ALPHA_MIN_TRESHOLD 2
+
#define DETECT_ALPHA( m_value )\
{ \
uint8_t value=m_value;\
@@ -1124,6 +1271,82 @@ void Image::create( const char ** p_xpm ) {
}\
}
+#define DETECT_NON_ALPHA( m_value )\
+{ \
+ uint8_t value=m_value;\
+ if (value>0) {\
+ \
+ detected=true;\
+ break;\
+ }\
+}
+
+
+bool Image::is_invisible() const {
+
+ if (format==FORMAT_GRAYSCALE ||
+ format==FORMAT_RGB ||
+ format==FORMAT_INDEXED)
+ return false;
+
+ int len = data.size();
+
+ if (len==0)
+ return true;
+
+ if (format >= FORMAT_YUV_422 && format <= FORMAT_YUV_444)
+ return false;
+
+ int w,h;
+ _get_mipmap_offset_and_size(1,len,w,h);
+
+ DVector<uint8_t>::Read r = data.read();
+ const unsigned char *data_ptr=r.ptr();
+
+ bool detected=false;
+
+ switch(format) {
+ case FORMAT_INTENSITY: {
+
+ for(int i=0;i<len;i++) {
+ DETECT_NON_ALPHA(data_ptr[i]);
+ }
+ } break;
+ case FORMAT_GRAYSCALE_ALPHA: {
+
+
+ for(int i=0;i<(len>>1);i++) {
+ DETECT_NON_ALPHA(data_ptr[(i<<1)+1]);
+ }
+
+ } break;
+ case FORMAT_RGBA: {
+
+ for(int i=0;i<(len>>2);i++) {
+ DETECT_NON_ALPHA(data_ptr[(i<<2)+3])
+ }
+
+ } break;
+ case FORMAT_INDEXED: {
+
+ return false;
+ } break;
+ case FORMAT_INDEXED_ALPHA: {
+
+ return false;
+ } break;
+ case FORMAT_PVRTC2_ALPHA:
+ case FORMAT_PVRTC4_ALPHA:
+ case FORMAT_BC2:
+ case FORMAT_BC3: {
+ detected=true;
+ } break;
+ default: {}
+ }
+
+ return !detected;
+}
+
Image::AlphaMode Image::detect_alpha() const {
if (format==FORMAT_GRAYSCALE ||
@@ -1734,6 +1957,10 @@ Error Image::_decompress_bc() {
return OK;
}
+bool Image::is_compressed() const {
+ return format>=FORMAT_BC1;
+}
+
Image Image::decompressed() const {
@@ -1986,7 +2213,7 @@ void Image::blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2&
}
-Image (*Image::_png_mem_loader_func)(const uint8_t*)=NULL;
+Image (*Image::_png_mem_loader_func)(const uint8_t*,int)=NULL;
void (*Image::_image_compress_bc_func)(Image *)=NULL;
void (*Image::_image_compress_pvrtc2_func)(Image *)=NULL;
void (*Image::_image_compress_pvrtc4_func)(Image *)=NULL;
@@ -2155,7 +2382,13 @@ void Image::fix_alpha_edges() {
}
-Image::Image(const uint8_t* p_png) {
+String Image::get_format_name(Format p_format) {
+
+ ERR_FAIL_INDEX_V(p_format,FORMAT_MAX,String());
+ return format_names[p_format];
+}
+
+Image::Image(const uint8_t* p_png,int p_len) {
width=0;
height=0;
@@ -2163,7 +2396,7 @@ Image::Image(const uint8_t* p_png) {
format=FORMAT_GRAYSCALE;
if (_png_mem_loader_func) {
- *this = _png_mem_loader_func(p_png);
+ *this = _png_mem_loader_func(p_png,p_len);
}
}
diff --git a/core/image.h b/core/image.h
index f4c96703b9..a155823af7 100644
--- a/core/image.h
+++ b/core/image.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -87,14 +87,16 @@ public:
FORMAT_MAX
};
+ static const char* format_names[FORMAT_MAX];
enum Interpolation {
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
+ INTERPOLATE_CUBIC,
/* INTERPOLATE GAUSS */
};
- static Image (*_png_mem_loader_func)(const uint8_t* p_png);
+ static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size);
static void (*_image_compress_bc_func)(Image *);
static void (*_image_compress_pvrtc2_func)(Image *);
static void (*_image_compress_pvrtc4_func)(Image *);
@@ -236,6 +238,7 @@ public:
int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data
void get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) const; //get where the mipmap begins in data
+ void get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const; //get where the mipmap begins in data
/**
* Resize the image, using the prefered interpolation method.
@@ -304,6 +307,7 @@ public:
};
AlphaMode detect_alpha() const;
+ bool is_invisible() const;
void put_indexed_pixel(int p_x, int p_y, uint8_t p_idx,int p_mipmap=0);
uint8_t get_indexed_pixel(int p_x, int p_y,int p_mipmap=0) const;
@@ -334,6 +338,7 @@ public:
Image compressed(int p_mode); /* from the Image::CompressMode enum */
Error decompress();
Image decompressed() const;
+ bool is_compressed() const;
void fix_alpha_edges();
void premultiply_alpha();
@@ -348,7 +353,9 @@ public:
Image get_rect(const Rect2& p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *));
- Image(const uint8_t* p_mem_png);
+ static String get_format_name(Format p_format);
+
+ Image(const uint8_t* p_mem_png, int p_len=-1);
Image(const char **p_xpm);
~Image();
diff --git a/core/image_quantize.cpp b/core/image_quantize.cpp
index d728a32861..a14e0ab72e 100644
--- a/core/image_quantize.cpp
+++ b/core/image_quantize.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 9426b0568e..24151c59c9 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,7 +42,7 @@ void InputMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("action_add_event","action","event"),&InputMap::action_add_event);
ObjectTypeDB::bind_method(_MD("action_has_event","action","event"),&InputMap::action_has_event);
ObjectTypeDB::bind_method(_MD("action_erase_event","action","event"),&InputMap::action_erase_event);
- ObjectTypeDB::bind_method(_MD("get_action_list","action"),&InputMap::get_action_list);
+ ObjectTypeDB::bind_method(_MD("get_action_list","action"),&InputMap::_get_action_list);
ObjectTypeDB::bind_method(_MD("event_is_action","event","action"),&InputMap::event_is_action);
ObjectTypeDB::bind_method(_MD("load_from_globals"),&InputMap::load_from_globals);
@@ -162,6 +162,22 @@ void InputMap::action_erase_event(const StringName& p_action,const InputEvent& p
}
+
+Array InputMap::_get_action_list(const StringName& p_action) {
+
+ Array ret;
+ const List<InputEvent> *al = get_action_list(p_action);
+ if (al) {
+ for(const List<InputEvent>::Element *E=al->front();E;E=E->next()) {
+
+ ret.push_back(E->get());;
+ }
+ }
+
+ return ret;
+
+}
+
const List<InputEvent> *InputMap::get_action_list(const StringName& p_action) {
const Map<StringName, Action>::Element *E=input_map.find(p_action);
@@ -176,7 +192,7 @@ bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_ac
Map<StringName,Action >::Element *E=input_map.find(p_action);
if(!E) {
- ERR_EXPLAIN("Request for unexisting InputMap action: "+String(p_action));
+ ERR_EXPLAIN("Request for nonexistent InputMap action: "+String(p_action));
ERR_FAIL_COND_V(!E,false);
}
diff --git a/core/input_map.h b/core/input_map.h
index bf20645b15..c5b21b1457 100644
--- a/core/input_map.h
+++ b/core/input_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,6 +46,8 @@ class InputMap : public Object {
List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const;
+ Array _get_action_list(const StringName& p_action);
+
protected:
static void _bind_methods();
diff --git a/core/int_types.h b/core/int_types.h
index 15ef68e915..231196b808 100644
--- a/core/int_types.h
+++ b/core/int_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -48,7 +48,7 @@ typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef long long int64_t;
-typedef unsigned long long int64_t;
+typedef unsigned long long uint64_t;
#else
#include <stdint.h>
#endif
diff --git a/core/io/SCsub b/core/io/SCsub
index 5aecb4b915..3ff9b355a4 100644
--- a/core/io/SCsub
+++ b/core/io/SCsub
@@ -5,5 +5,3 @@ env.add_source_files(env.core_sources,"*.c")
#env.core_sources.append("io/fastlz.c")
Export('env')
-
-
diff --git a/core/io/aes256.cpp b/core/io/aes256.cpp
index 69a5091f1d..e7f465dcc6 100644
--- a/core/io/aes256.cpp
+++ b/core/io/aes256.cpp
@@ -1,359 +1,359 @@
-/*
-* Byte-oriented AES-256 implementation.
-* All lookup tables replaced with 'on the fly' calculations.
-*
-* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
-* Other contributors: Hal Finney
-*
-* Permission to use, copy, modify, and distribute this software for any
-* purpose with or without fee is hereby granted, provided that the above
-* copyright notice and this permission notice appear in all copies.
-*
-* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-#include "aes256.h"
-
-#define F(x) (((x)<<1) ^ ((((x)>>7) & 1) * 0x1b))
-#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))
-
-// #define BACK_TO_TABLES
-#ifdef BACK_TO_TABLES
-
-const uint8_t sbox[256] = {
- 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
- 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
- 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
- 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
- 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
- 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
- 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
- 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
- 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
- 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
- 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
- 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
- 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
- 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
- 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
- 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
- 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
- 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
- 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
- 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
- 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
- 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
- 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
- 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
- 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
- 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
- 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
- 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
- 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
- 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
- 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
-};
-const uint8_t sboxinv[256] = {
- 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
- 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
- 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
- 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
- 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
- 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
- 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
- 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
- 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
- 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
- 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
- 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
- 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
- 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
- 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
- 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
- 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
- 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
- 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
- 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
- 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
- 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
- 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
- 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
- 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
- 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
- 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
- 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
- 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
- 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
- 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
-};
-
-#define rj_sbox(x) sbox[(x)]
-#define rj_sbox_inv(x) sboxinv[(x)]
-
-#else /* tableless subroutines */
-
-/* -------------------------------------------------------------------------- */
-uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3
-{
- uint8_t atb = 1, z;
-
- while (x--) {z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;}
-
- return atb;
-} /* gf_alog */
-
-/* -------------------------------------------------------------------------- */
-uint8_t gf_log(uint8_t x) // calculate logarithm gen 3
-{
- uint8_t atb = 1, i = 0, z;
-
- do {
- if (atb == x) break;
- z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;
- } while (++i > 0);
-
- return i;
-} /* gf_log */
-
-
-/* -------------------------------------------------------------------------- */
-uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse
-{
- return (x) ? gf_alog(255 - gf_log(x)) : 0;
-} /* gf_mulinv */
-
-/* -------------------------------------------------------------------------- */
-uint8_t rj_sbox(uint8_t x)
-{
- uint8_t y, sb;
-
- sb = y = gf_mulinv(x);
- y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;
- y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;
-
- return (sb ^ 0x63);
-} /* rj_sbox */
-
-/* -------------------------------------------------------------------------- */
-uint8_t rj_sbox_inv(uint8_t x)
-{
- uint8_t y, sb;
-
- y = x ^ 0x63;
- sb = y = (y<<1)|(y>>7);
- y = (y<<2)|(y>>6); sb ^= y; y = (y<<3)|(y>>5); sb ^= y;
-
- return gf_mulinv(sb);
-} /* rj_sbox_inv */
-
-#endif
-
-/* -------------------------------------------------------------------------- */
-uint8_t rj_xtime(uint8_t x)
-{
- return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1);
-} /* rj_xtime */
-
-/* -------------------------------------------------------------------------- */
-void aes_subBytes(uint8_t *buf)
-{
- register uint8_t i = 16;
-
- while (i--) buf[i] = rj_sbox(buf[i]);
-} /* aes_subBytes */
-
-/* -------------------------------------------------------------------------- */
-void aes_subBytes_inv(uint8_t *buf)
-{
- register uint8_t i = 16;
-
- while (i--) buf[i] = rj_sbox_inv(buf[i]);
-} /* aes_subBytes_inv */
-
-/* -------------------------------------------------------------------------- */
-void aes_addRoundKey(uint8_t *buf, uint8_t *key)
-{
- register uint8_t i = 16;
-
- while (i--) buf[i] ^= key[i];
-} /* aes_addRoundKey */
-
-/* -------------------------------------------------------------------------- */
-void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk)
-{
- register uint8_t i = 16;
-
- while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16+i] = key[16 + i];
-} /* aes_addRoundKey_cpy */
-
-
-/* -------------------------------------------------------------------------- */
-void aes_shiftRows(uint8_t *buf)
-{
- register uint8_t i, j; /* to make it potentially parallelable :) */
-
- i = buf[1]; buf[1] = buf[5]; buf[5] = buf[9]; buf[9] = buf[13]; buf[13] = i;
- i = buf[10]; buf[10] = buf[2]; buf[2] = i;
- j = buf[3]; buf[3] = buf[15]; buf[15] = buf[11]; buf[11] = buf[7]; buf[7] = j;
- j = buf[14]; buf[14] = buf[6]; buf[6] = j;
-
-} /* aes_shiftRows */
-
-/* -------------------------------------------------------------------------- */
-void aes_shiftRows_inv(uint8_t *buf)
-{
- register uint8_t i, j; /* same as above :) */
-
- i = buf[1]; buf[1] = buf[13]; buf[13] = buf[9]; buf[9] = buf[5]; buf[5] = i;
- i = buf[2]; buf[2] = buf[10]; buf[10] = i;
- j = buf[3]; buf[3] = buf[7]; buf[7] = buf[11]; buf[11] = buf[15]; buf[15] = j;
- j = buf[6]; buf[6] = buf[14]; buf[14] = j;
-
-} /* aes_shiftRows_inv */
-
-/* -------------------------------------------------------------------------- */
-void aes_mixColumns(uint8_t *buf)
-{
- register uint8_t i, a, b, c, d, e;
-
- for (i = 0; i < 16; i += 4)
- {
- a = buf[i]; b = buf[i + 1]; c = buf[i + 2]; d = buf[i + 3];
- e = a ^ b ^ c ^ d;
- buf[i] ^= e ^ rj_xtime(a^b); buf[i+1] ^= e ^ rj_xtime(b^c);
- buf[i+2] ^= e ^ rj_xtime(c^d); buf[i+3] ^= e ^ rj_xtime(d^a);
- }
-} /* aes_mixColumns */
-
-/* -------------------------------------------------------------------------- */
-void aes_mixColumns_inv(uint8_t *buf)
-{
- register uint8_t i, a, b, c, d, e, x, y, z;
-
- for (i = 0; i < 16; i += 4)
- {
- a = buf[i]; b = buf[i + 1]; c = buf[i + 2]; d = buf[i + 3];
- e = a ^ b ^ c ^ d;
- z = rj_xtime(e);
- x = e ^ rj_xtime(rj_xtime(z^a^c)); y = e ^ rj_xtime(rj_xtime(z^b^d));
- buf[i] ^= x ^ rj_xtime(a^b); buf[i+1] ^= y ^ rj_xtime(b^c);
- buf[i+2] ^= x ^ rj_xtime(c^d); buf[i+3] ^= y ^ rj_xtime(d^a);
- }
-} /* aes_mixColumns_inv */
-
-/* -------------------------------------------------------------------------- */
-void aes_expandEncKey(uint8_t *k, uint8_t *rc)
-{
- register uint8_t i;
-
- k[0] ^= rj_sbox(k[29]) ^ (*rc);
- k[1] ^= rj_sbox(k[30]);
- k[2] ^= rj_sbox(k[31]);
- k[3] ^= rj_sbox(k[28]);
- *rc = F( *rc);
-
- for(i = 4; i < 16; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
- k[16] ^= rj_sbox(k[12]);
- k[17] ^= rj_sbox(k[13]);
- k[18] ^= rj_sbox(k[14]);
- k[19] ^= rj_sbox(k[15]);
-
- for(i = 20; i < 32; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
-
-} /* aes_expandEncKey */
-
-/* -------------------------------------------------------------------------- */
-void aes_expandDecKey(uint8_t *k, uint8_t *rc)
-{
- uint8_t i;
-
- for(i = 28; i > 16; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
-
- k[16] ^= rj_sbox(k[12]);
- k[17] ^= rj_sbox(k[13]);
- k[18] ^= rj_sbox(k[14]);
- k[19] ^= rj_sbox(k[15]);
-
- for(i = 12; i > 0; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],
- k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
-
- *rc = FD(*rc);
- k[0] ^= rj_sbox(k[29]) ^ (*rc);
- k[1] ^= rj_sbox(k[30]);
- k[2] ^= rj_sbox(k[31]);
- k[3] ^= rj_sbox(k[28]);
-} /* aes_expandDecKey */
-
-
-/* -------------------------------------------------------------------------- */
-void aes256_init(aes256_context *ctx, uint8_t *k)
-{
- uint8_t rcon = 1;
- register uint8_t i;
-
- for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];
- for (i = 8;--i;) aes_expandEncKey(ctx->deckey, &rcon);
-} /* aes256_init */
-
-/* -------------------------------------------------------------------------- */
-void aes256_done(aes256_context *ctx)
-{
- register uint8_t i;
-
- for (i = 0; i < sizeof(ctx->key); i++)
- ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;
-} /* aes256_done */
-
-/* -------------------------------------------------------------------------- */
-void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
-{
- uint8_t i, rcon;
-
- aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);
- for(i = 1, rcon = 1; i < 14; ++i)
- {
- aes_subBytes(buf);
- aes_shiftRows(buf);
- aes_mixColumns(buf);
- if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);
- else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key);
- }
- aes_subBytes(buf);
- aes_shiftRows(buf);
- aes_expandEncKey(ctx->key, &rcon);
- aes_addRoundKey(buf, ctx->key);
-} /* aes256_encrypt */
-
-/* -------------------------------------------------------------------------- */
-void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf)
-{
- uint8_t i, rcon;
-
- aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key);
- aes_shiftRows_inv(buf);
- aes_subBytes_inv(buf);
-
- for (i = 14, rcon = 0x80; --i;)
- {
- if( ( i & 1 ) )
- {
- aes_expandDecKey(ctx->key, &rcon);
- aes_addRoundKey(buf, &ctx->key[16]);
- }
- else aes_addRoundKey(buf, ctx->key);
- aes_mixColumns_inv(buf);
- aes_shiftRows_inv(buf);
- aes_subBytes_inv(buf);
- }
- aes_addRoundKey( buf, ctx->key);
-} /* aes256_decrypt */
+/*
+* Byte-oriented AES-256 implementation.
+* All lookup tables replaced with 'on the fly' calculations.
+*
+* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
+* Other contributors: Hal Finney
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+#include "aes256.h"
+
+#define F(x) (((x)<<1) ^ ((((x)>>7) & 1) * 0x1b))
+#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))
+
+// #define BACK_TO_TABLES
+#ifdef BACK_TO_TABLES
+
+const uint8_t sbox[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+const uint8_t sboxinv[256] = {
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
+ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+#define rj_sbox(x) sbox[(x)]
+#define rj_sbox_inv(x) sboxinv[(x)]
+
+#else /* tableless subroutines */
+
+/* -------------------------------------------------------------------------- */
+uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3
+{
+ uint8_t atb = 1, z;
+
+ while (x--) {z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;}
+
+ return atb;
+} /* gf_alog */
+
+/* -------------------------------------------------------------------------- */
+uint8_t gf_log(uint8_t x) // calculate logarithm gen 3
+{
+ uint8_t atb = 1, i = 0, z;
+
+ do {
+ if (atb == x) break;
+ z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;
+ } while (++i > 0);
+
+ return i;
+} /* gf_log */
+
+
+/* -------------------------------------------------------------------------- */
+uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse
+{
+ return (x) ? gf_alog(255 - gf_log(x)) : 0;
+} /* gf_mulinv */
+
+/* -------------------------------------------------------------------------- */
+uint8_t rj_sbox(uint8_t x)
+{
+ uint8_t y, sb;
+
+ sb = y = gf_mulinv(x);
+ y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;
+ y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;
+
+ return (sb ^ 0x63);
+} /* rj_sbox */
+
+/* -------------------------------------------------------------------------- */
+uint8_t rj_sbox_inv(uint8_t x)
+{
+ uint8_t y, sb;
+
+ y = x ^ 0x63;
+ sb = y = (y<<1)|(y>>7);
+ y = (y<<2)|(y>>6); sb ^= y; y = (y<<3)|(y>>5); sb ^= y;
+
+ return gf_mulinv(sb);
+} /* rj_sbox_inv */
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+uint8_t rj_xtime(uint8_t x)
+{
+ return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1);
+} /* rj_xtime */
+
+/* -------------------------------------------------------------------------- */
+void aes_subBytes(uint8_t *buf)
+{
+ register uint8_t i = 16;
+
+ while (i--) buf[i] = rj_sbox(buf[i]);
+} /* aes_subBytes */
+
+/* -------------------------------------------------------------------------- */
+void aes_subBytes_inv(uint8_t *buf)
+{
+ register uint8_t i = 16;
+
+ while (i--) buf[i] = rj_sbox_inv(buf[i]);
+} /* aes_subBytes_inv */
+
+/* -------------------------------------------------------------------------- */
+void aes_addRoundKey(uint8_t *buf, uint8_t *key)
+{
+ register uint8_t i = 16;
+
+ while (i--) buf[i] ^= key[i];
+} /* aes_addRoundKey */
+
+/* -------------------------------------------------------------------------- */
+void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk)
+{
+ register uint8_t i = 16;
+
+ while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16+i] = key[16 + i];
+} /* aes_addRoundKey_cpy */
+
+
+/* -------------------------------------------------------------------------- */
+void aes_shiftRows(uint8_t *buf)
+{
+ register uint8_t i, j; /* to make it potentially parallelable :) */
+
+ i = buf[1]; buf[1] = buf[5]; buf[5] = buf[9]; buf[9] = buf[13]; buf[13] = i;
+ i = buf[10]; buf[10] = buf[2]; buf[2] = i;
+ j = buf[3]; buf[3] = buf[15]; buf[15] = buf[11]; buf[11] = buf[7]; buf[7] = j;
+ j = buf[14]; buf[14] = buf[6]; buf[6] = j;
+
+} /* aes_shiftRows */
+
+/* -------------------------------------------------------------------------- */
+void aes_shiftRows_inv(uint8_t *buf)
+{
+ register uint8_t i, j; /* same as above :) */
+
+ i = buf[1]; buf[1] = buf[13]; buf[13] = buf[9]; buf[9] = buf[5]; buf[5] = i;
+ i = buf[2]; buf[2] = buf[10]; buf[10] = i;
+ j = buf[3]; buf[3] = buf[7]; buf[7] = buf[11]; buf[11] = buf[15]; buf[15] = j;
+ j = buf[6]; buf[6] = buf[14]; buf[14] = j;
+
+} /* aes_shiftRows_inv */
+
+/* -------------------------------------------------------------------------- */
+void aes_mixColumns(uint8_t *buf)
+{
+ register uint8_t i, a, b, c, d, e;
+
+ for (i = 0; i < 16; i += 4)
+ {
+ a = buf[i]; b = buf[i + 1]; c = buf[i + 2]; d = buf[i + 3];
+ e = a ^ b ^ c ^ d;
+ buf[i] ^= e ^ rj_xtime(a^b); buf[i+1] ^= e ^ rj_xtime(b^c);
+ buf[i+2] ^= e ^ rj_xtime(c^d); buf[i+3] ^= e ^ rj_xtime(d^a);
+ }
+} /* aes_mixColumns */
+
+/* -------------------------------------------------------------------------- */
+void aes_mixColumns_inv(uint8_t *buf)
+{
+ register uint8_t i, a, b, c, d, e, x, y, z;
+
+ for (i = 0; i < 16; i += 4)
+ {
+ a = buf[i]; b = buf[i + 1]; c = buf[i + 2]; d = buf[i + 3];
+ e = a ^ b ^ c ^ d;
+ z = rj_xtime(e);
+ x = e ^ rj_xtime(rj_xtime(z^a^c)); y = e ^ rj_xtime(rj_xtime(z^b^d));
+ buf[i] ^= x ^ rj_xtime(a^b); buf[i+1] ^= y ^ rj_xtime(b^c);
+ buf[i+2] ^= x ^ rj_xtime(c^d); buf[i+3] ^= y ^ rj_xtime(d^a);
+ }
+} /* aes_mixColumns_inv */
+
+/* -------------------------------------------------------------------------- */
+void aes_expandEncKey(uint8_t *k, uint8_t *rc)
+{
+ register uint8_t i;
+
+ k[0] ^= rj_sbox(k[29]) ^ (*rc);
+ k[1] ^= rj_sbox(k[30]);
+ k[2] ^= rj_sbox(k[31]);
+ k[3] ^= rj_sbox(k[28]);
+ *rc = F( *rc);
+
+ for(i = 4; i < 16; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],
+ k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+ k[16] ^= rj_sbox(k[12]);
+ k[17] ^= rj_sbox(k[13]);
+ k[18] ^= rj_sbox(k[14]);
+ k[19] ^= rj_sbox(k[15]);
+
+ for(i = 20; i < 32; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],
+ k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+
+} /* aes_expandEncKey */
+
+/* -------------------------------------------------------------------------- */
+void aes_expandDecKey(uint8_t *k, uint8_t *rc)
+{
+ uint8_t i;
+
+ for(i = 28; i > 16; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],
+ k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+
+ k[16] ^= rj_sbox(k[12]);
+ k[17] ^= rj_sbox(k[13]);
+ k[18] ^= rj_sbox(k[14]);
+ k[19] ^= rj_sbox(k[15]);
+
+ for(i = 12; i > 0; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],
+ k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];
+
+ *rc = FD(*rc);
+ k[0] ^= rj_sbox(k[29]) ^ (*rc);
+ k[1] ^= rj_sbox(k[30]);
+ k[2] ^= rj_sbox(k[31]);
+ k[3] ^= rj_sbox(k[28]);
+} /* aes_expandDecKey */
+
+
+/* -------------------------------------------------------------------------- */
+void aes256_init(aes256_context *ctx, uint8_t *k)
+{
+ uint8_t rcon = 1;
+ register uint8_t i;
+
+ for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];
+ for (i = 8;--i;) aes_expandEncKey(ctx->deckey, &rcon);
+} /* aes256_init */
+
+/* -------------------------------------------------------------------------- */
+void aes256_done(aes256_context *ctx)
+{
+ register uint8_t i;
+
+ for (i = 0; i < sizeof(ctx->key); i++)
+ ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;
+} /* aes256_done */
+
+/* -------------------------------------------------------------------------- */
+void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
+{
+ uint8_t i, rcon;
+
+ aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);
+ for(i = 1, rcon = 1; i < 14; ++i)
+ {
+ aes_subBytes(buf);
+ aes_shiftRows(buf);
+ aes_mixColumns(buf);
+ if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);
+ else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key);
+ }
+ aes_subBytes(buf);
+ aes_shiftRows(buf);
+ aes_expandEncKey(ctx->key, &rcon);
+ aes_addRoundKey(buf, ctx->key);
+} /* aes256_encrypt */
+
+/* -------------------------------------------------------------------------- */
+void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf)
+{
+ uint8_t i, rcon;
+
+ aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key);
+ aes_shiftRows_inv(buf);
+ aes_subBytes_inv(buf);
+
+ for (i = 14, rcon = 0x80; --i;)
+ {
+ if( ( i & 1 ) )
+ {
+ aes_expandDecKey(ctx->key, &rcon);
+ aes_addRoundKey(buf, &ctx->key[16]);
+ }
+ else aes_addRoundKey(buf, ctx->key);
+ aes_mixColumns_inv(buf);
+ aes_shiftRows_inv(buf);
+ aes_subBytes_inv(buf);
+ }
+ aes_addRoundKey( buf, ctx->key);
+} /* aes256_decrypt */
diff --git a/core/io/aes256.h b/core/io/aes256.h
index 180352e970..fabbcf1968 100644
--- a/core/io/aes256.h
+++ b/core/io/aes256.h
@@ -1,46 +1,46 @@
-/*
-* Byte-oriented AES-256 implementation.
-* All lookup tables replaced with 'on the fly' calculations.
-*
-* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
-* Other contributors: Hal Finney
-*
-* Permission to use, copy, modify, and distribute this software for any
-* purpose with or without fee is hereby granted, provided that the above
-* copyright notice and this permission notice appear in all copies.
-*
-* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef AES_256_H
-#define AES_256_H
-
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- typedef struct {
- uint8_t key[32];
- uint8_t enckey[32];
- uint8_t deckey[32];
- } aes256_context;
-
-
- void aes256_init(aes256_context *, uint8_t * /* key */);
- void aes256_done(aes256_context *);
- void aes256_encrypt_ecb(aes256_context *, uint8_t * /* plaintext */);
- void aes256_decrypt_ecb(aes256_context *, uint8_t * /* cipertext */);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*
+* Byte-oriented AES-256 implementation.
+* All lookup tables replaced with 'on the fly' calculations.
+*
+* Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com
+* Other contributors: Hal Finney
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef AES_256_H
+#define AES_256_H
+
+#include "typedefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct {
+ uint8_t key[32];
+ uint8_t enckey[32];
+ uint8_t deckey[32];
+ } aes256_context;
+
+
+ void aes256_init(aes256_context *, uint8_t * /* key */);
+ void aes256_done(aes256_context *);
+ void aes256_encrypt_ecb(aes256_context *, uint8_t * /* plaintext */);
+ void aes256_decrypt_ecb(aes256_context *, uint8_t * /* cipertext */);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index ea2f5d2d9c..729b7bec52 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/compression.h b/core/io/compression.h
index 70742d42d6..106a3f0201 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,28 +26,28 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COMPRESSION_H
-#define COMPRESSION_H
-
-#include "typedefs.h"
-
-class Compression
-{
-public:
-
- enum Mode {
- MODE_FASTLZ,
- MODE_DEFLATE
- };
-
-
- static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
- static int get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ);
- static void decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
-
- Compression();
-};
-
-
-
-#endif // COMPRESSION_H
+#ifndef COMPRESSION_H
+#define COMPRESSION_H
+
+#include "typedefs.h"
+
+class Compression
+{
+public:
+
+ enum Mode {
+ MODE_FASTLZ,
+ MODE_DEFLATE
+ };
+
+
+ static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
+ static int get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ);
+ static void decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
+
+ Compression();
+};
+
+
+
+#endif // COMPRESSION_H
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 17ee72f2eb..75388f514a 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -357,6 +357,7 @@ if (res!=-1 && res < min_pos) {\
} break;
case MIN_OPEN: {
int level=1;
+ end++;
while(end<close_pos) {
if (str[end]=='[')
@@ -373,6 +374,7 @@ if (res!=-1 && res < min_pos) {\
} break;
case MIN_CURLY_OPEN: {
int level=1;
+ end++;
while(end<close_pos) {
if (str[end]=='{')
diff --git a/core/io/config_file.h b/core/io/config_file.h
index e132e46fea..608f143fb1 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
index 6927b3772f..ab17cb8118 100644
--- a/core/io/file_access_buffered.cpp
+++ b/core/io/file_access_buffered.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h
index 533cc6c7dd..e6de203cda 100644
--- a/core/io/file_access_buffered.h
+++ b/core/io/file_access_buffered.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index 5de2f66ace..d36c4843e4 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index b90a41df54..1d06dc8c4b 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 3039b5c8be..69a03fa14f 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,76 +26,76 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef FILE_ACCESS_COMPRESSED_H
-#define FILE_ACCESS_COMPRESSED_H
-
-#include "io/compression.h"
-#include "os/file_access.h"
-
-class FileAccessCompressed : public FileAccess {
-
- Compression::Mode cmode;
- bool writing;
- int write_pos;
- uint8_t*write_ptr;
- int write_buffer_size;
- int write_max;
- int block_size;
- mutable bool read_eof;
- mutable bool at_end;
-
- struct ReadBlock {
- int csize;
- int offset;
- };
-
- mutable Vector<uint8_t> comp_buffer;
- uint8_t *read_ptr;
- mutable int read_block;
- int read_block_count;
- mutable int read_block_size;
- mutable int read_pos;
- Vector<ReadBlock> read_blocks;
- int read_total;
-
-
-
-
- String magic;
- mutable Vector<uint8_t> buffer;
- FileAccess *f;
-public:
-
- void configure(const String& p_magic, Compression::Mode p_mode=Compression::MODE_FASTLZ, int p_block_size=4096);
-
- Error open_after_magic(FileAccess *p_base);
-
- 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
-
- virtual void seek(size_t p_position); ///< seek to a given position
- virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
-
- virtual bool eof_reached() const; ///< reading passed EOF
-
- virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
-
- virtual Error get_error() const; ///< get last error
-
- virtual void store_8(uint8_t p_dest); ///< store a byte
-
- virtual bool file_exists(const String& p_name); ///< return true if a file exists
-
- virtual uint64_t _get_modified_time(const String& p_file);
-
-
- FileAccessCompressed();
- virtual ~FileAccessCompressed();
-
-};
-
-#endif // FILE_ACCESS_COMPRESSED_H
+#ifndef FILE_ACCESS_COMPRESSED_H
+#define FILE_ACCESS_COMPRESSED_H
+
+#include "io/compression.h"
+#include "os/file_access.h"
+
+class FileAccessCompressed : public FileAccess {
+
+ Compression::Mode cmode;
+ bool writing;
+ int write_pos;
+ uint8_t*write_ptr;
+ int write_buffer_size;
+ int write_max;
+ int block_size;
+ mutable bool read_eof;
+ mutable bool at_end;
+
+ struct ReadBlock {
+ int csize;
+ int offset;
+ };
+
+ mutable Vector<uint8_t> comp_buffer;
+ uint8_t *read_ptr;
+ mutable int read_block;
+ int read_block_count;
+ mutable int read_block_size;
+ mutable int read_pos;
+ Vector<ReadBlock> read_blocks;
+ int read_total;
+
+
+
+
+ String magic;
+ mutable Vector<uint8_t> buffer;
+ FileAccess *f;
+public:
+
+ void configure(const String& p_magic, Compression::Mode p_mode=Compression::MODE_FASTLZ, int p_block_size=4096);
+
+ Error open_after_magic(FileAccess *p_base);
+
+ 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
+
+ virtual void seek(size_t p_position); ///< seek to a given position
+ virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
+ virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_len() const; ///< get size of the file
+
+ virtual bool eof_reached() const; ///< reading passed EOF
+
+ virtual uint8_t get_8() const; ///< get a byte
+ virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+
+ virtual Error get_error() const; ///< get last error
+
+ virtual void store_8(uint8_t p_dest); ///< store a byte
+
+ virtual bool file_exists(const String& p_name); ///< return true if a file exists
+
+ virtual uint64_t _get_modified_time(const String& p_file);
+
+
+ FileAccessCompressed();
+ virtual ~FileAccessCompressed();
+
+};
+
+#endif // FILE_ACCESS_COMPRESSED_H
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 29f27dcbda..65b1ca5207 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -5,10 +5,12 @@
#include "print_string.h"
#define COMP_MAGIC 0x43454447
+#include "core/variant.h"
+#include <stdio.h>
Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_t>& p_key,Mode p_mode) {
- print_line("open and parse!");
+ //print_line("open and parse!");
ERR_FAIL_COND_V(file!=NULL,ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER);
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index a1dd2e48bb..83da55fc61 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,7 +39,7 @@ void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
if (!files) {
files = memnew((Map<String, Vector<uint8_t> >));
- };
+ }
String name;
if (Globals::get_singleton())
@@ -49,7 +49,7 @@ void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
name = DirAccess::normalize_path(name);
(*files)[name] = p_data;
-};
+}
void FileAccessMemory::cleanup() {
@@ -57,13 +57,13 @@ void FileAccessMemory::cleanup() {
return;
memdelete(files);
-};
+}
FileAccess* FileAccessMemory::create() {
return memnew(FileAccessMemory);
-};
+}
bool FileAccessMemory::file_exists(const String& p_name) {
@@ -71,8 +71,16 @@ bool FileAccessMemory::file_exists(const String& p_name) {
name = DirAccess::normalize_path(name);
return files && (files->find(name) != NULL);
-};
+}
+
+Error FileAccessMemory::open_custom(const uint8_t* p_data, int p_len) {
+
+ data=(uint8_t*)p_data;
+ length=p_len;
+ pos=0;
+ return OK;
+}
Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
@@ -89,57 +97,57 @@ Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
pos = 0;
return OK;
-};
+}
void FileAccessMemory::close() {
data = NULL;
-};
+}
bool FileAccessMemory::is_open() const {
return data != NULL;
-};
+}
void FileAccessMemory::seek(size_t p_position) {
ERR_FAIL_COND(!data);
pos = p_position;
-};
+}
void FileAccessMemory::seek_end(int64_t p_position) {
ERR_FAIL_COND(!data);
pos = length + p_position;
-};
+}
size_t FileAccessMemory::get_pos() const {
ERR_FAIL_COND_V(!data, 0);
return pos;
-};
+}
size_t FileAccessMemory::get_len() const {
ERR_FAIL_COND_V(!data, 0);
return length;
-};
+}
bool FileAccessMemory::eof_reached() const {
return pos >= length;
-};
+}
uint8_t FileAccessMemory::get_8() const {
- uint8_t ret;
+ uint8_t ret = 0;
if (pos < length) {
ret = data[pos];
- };
+ }
++pos;
return ret;
-};
+}
int FileAccessMemory::get_buffer(uint8_t *p_dst,int p_length) const {
@@ -156,19 +164,19 @@ int FileAccessMemory::get_buffer(uint8_t *p_dst,int p_length) const {
pos += p_length;
return read;
-};
+}
Error FileAccessMemory::get_error() const {
return pos >= length ? ERR_FILE_EOF : OK;
-};
+}
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_COND(!data);
ERR_FAIL_COND(pos >= length);
data[pos++] = p_byte;
-};
+}
void FileAccessMemory::store_buffer(const uint8_t *p_src,int p_length) {
@@ -176,11 +184,11 @@ void FileAccessMemory::store_buffer(const uint8_t *p_src,int p_length) {
int write = MIN(p_length, left);
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
- };
+ }
copymem(&data[pos], p_src, write);
pos += p_length;
-};
+}
FileAccessMemory::FileAccessMemory() {
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index a02a022a4f..8c58a8a8ce 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,6 +44,7 @@ public:
static void register_file(String p_name, Vector<uint8_t> p_data);
static void cleanup();
+ virtual Error open_custom(const uint8_t* p_data, int p_len); ///< 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
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 26194040b0..850e055129 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -254,6 +254,7 @@ FileAccessNetworkClient::~FileAccessNetworkClient() {
quit=true;
sem->post();
Thread::wait_to_finish(thread);
+ memdelete(thread);
}
memdelete(blockrequest_mutex);
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index f338bea43f..2190cdb0ea 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 6e03819aac..339a6d0528 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -92,7 +92,9 @@ void PackedData::add_path(const String& pkg_path, const String& path, uint64_t o
void PackedData::add_pack_source(PackSource *p_source) {
- sources.push_back(p_source);
+ if (p_source != NULL) {
+ sources.push_back(p_source);
+ }
};
PackedData *PackedData::singleton=NULL;
@@ -107,6 +109,21 @@ PackedData::PackedData() {
add_pack_source(memnew(PackedSourcePCK));
}
+void PackedData::_free_packed_dirs(PackedDir *p_dir) {
+
+ for (Map<String,PackedDir*>::Element *E=p_dir->subdirs.front();E;E=E->next())
+ _free_packed_dirs(E->get());
+ memdelete(p_dir);
+}
+
+PackedData::~PackedData() {
+
+ for(int i=0;i<sources.size();i++) {
+ memdelete(sources[i]);
+ }
+ _free_packed_dirs(root);
+}
+
//////////////////////////////////////////////////////////////////
@@ -362,6 +379,10 @@ bool DirAccessPack::current_is_dir() const{
return cdir;
}
+bool DirAccessPack::current_is_hidden() const{
+
+ return false;
+}
void DirAccessPack::list_dir_end() {
list_dirs.clear();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 5fcc79aaf4..5bf5ad012c 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -96,6 +96,8 @@ private:
static PackedData *singleton;
bool disabled;
+ void _free_packed_dirs(PackedDir *p_dir);
+
public:
void add_pack_source(PackSource* p_source);
@@ -111,6 +113,7 @@ public:
_FORCE_INLINE_ bool has_path(const String& p_path);
PackedData();
+ ~PackedData();
};
class PackSource {
@@ -119,6 +122,7 @@ public:
virtual bool try_open_pack(const String& p_path)=0;
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file)=0;
+ virtual ~PackSource() {}
};
class PackedSourcePCK : public PackSource {
@@ -208,6 +212,7 @@ public:
virtual bool list_dir_begin();
virtual String get_next();
virtual bool current_is_dir() const;
+ virtual bool current_is_hidden() const;
virtual void list_dir_end();
virtual int get_drive_count();
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 55c0dedad9..ab2eb3b3f2 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -31,6 +31,7 @@
#include "file_access_zip.h"
#include "core/os/file_access.h"
+#include "core/os/copymem.h"
ZipArchive* ZipArchive::instance = NULL;
@@ -103,9 +104,17 @@ static int godot_testerror(voidpf opaque, voidpf stream) {
return f->get_error()!=OK?1:0;
};
+static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
+ return memalloc(items * size);
};
+static void godot_free(voidpf opaque, voidpf address) {
+
+ memfree(address);
+};
+
+}; // extern "C"
void ZipArchive::close_handle(unzFile p_file) const {
@@ -125,6 +134,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
ERR_FAIL_COND_V(!f, NULL);
zlib_filefunc_def io;
+ zeromem(&io, sizeof(io));
io.opaque = f;
io.zopen_file = godot_open;
@@ -136,9 +146,13 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
io.zclose_file = godot_close;
io.zerror_file = godot_testerror;
+ io.alloc_mem = godot_alloc;
+ io.free_mem = godot_free;
+
unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
ERR_FAIL_COND_V(!pkg, NULL);
- unzGoToFilePos(pkg, &file.file_pos);
+ int unz_err = unzGoToFilePos(pkg, &file.file_pos);
+ ERR_FAIL_COND_V(unz_err != UNZ_OK, NULL);
if (unzOpenCurrentFile(pkg) != UNZ_OK) {
unzClose(pkg);
@@ -150,7 +164,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
bool ZipArchive::try_open_pack(const String& p_name) {
- printf("opening pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
+ //printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
if (p_name.extension().nocasecmp_to("zip") != 0 && p_name.extension().nocasecmp_to("pcz") != 0)
return false;
@@ -198,7 +212,8 @@ bool ZipArchive::try_open_pack(const String& p_name) {
files[fname] = f;
uint8_t md5[16]={0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0};
- PackedData::get_singleton()->add_path(p_name, fname, 0, 0, md5, this);
+ PackedData::get_singleton()->add_path(p_name, fname, 1, 0, md5, this);
+ //printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str());
if ((i+1)<gi.number_entry) {
unzGoToNextFile(zfile);
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index faead675d4..58092efd4b 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -273,7 +273,7 @@ Error HTTPClient::poll(){
while(true) {
uint8_t byte;
int rec=0;
- Error err = connection->get_partial_data(&byte,1,rec);
+ Error err = _get_http_data(&byte,1,rec);
if (err!=OK) {
close();
status=STATUS_CONNECTION_ERROR;
@@ -325,7 +325,7 @@ Error HTTPClient::poll(){
if (i==0 && responses[i].begins_with("HTTP")) {
- String num = responses[i].get_slice(" ",1);
+ String num = responses[i].get_slicec(' ',1);
response_num=num.to_int();
} else {
@@ -417,7 +417,7 @@ ByteArray HTTPClient::read_response_body_chunk() {
//reading len
uint8_t b;
int rec=0;
- err = connection->get_partial_data(&b,1,rec);
+ err = _get_http_data(&b,1,rec);
if (rec==0)
break;
@@ -471,7 +471,7 @@ ByteArray HTTPClient::read_response_body_chunk() {
} else {
int rec=0;
- err = connection->get_partial_data(&chunk[chunk.size()-chunk_left],chunk_left,rec);
+ err = _get_http_data(&chunk[chunk.size()-chunk_left],chunk_left,rec);
if (rec==0) {
break;
}
@@ -502,18 +502,23 @@ ByteArray HTTPClient::read_response_body_chunk() {
}
} else {
+
+ int to_read = MIN(body_left,read_chunk_size);
ByteArray ret;
- ret.resize(MAX(body_left,tmp_read.size()));
+ ret.resize(to_read);
ByteArray::Write w = ret.write();
int _offset = 0;
- while (body_left > 0) {
- ByteArray::Write r = tmp_read.write();
+ while (to_read > 0) {
int rec=0;
- err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
+ err = _get_http_data(w.ptr()+_offset,to_read,rec);
if (rec>0) {
- copymem(w.ptr()+_offset,r.ptr(),rec);
body_left-=rec;
+ to_read-=rec;
_offset += rec;
+ } else {
+ if (to_read>0) //ended up reading less
+ ret.resize(_offset);
+ break;
}
}
if (body_left==0) {
@@ -557,10 +562,24 @@ bool HTTPClient::is_blocking_mode_enabled() const{
return blocking;
}
+Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) {
+
+ if (blocking) {
+
+ Error err = connection->get_data(p_buffer,p_bytes);
+ if (err==OK)
+ r_received=p_bytes;
+ else
+ r_received=0;
+ return err;
+ } else {
+ return connection->get_partial_data(p_buffer,p_bytes,r_received);
+ }
+}
void HTTPClient::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true));
+ ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true));
ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String()));
ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text);
@@ -574,6 +593,7 @@ void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary);
ObjectTypeDB::bind_method(_MD("get_response_body_length"),&HTTPClient::get_response_body_length);
ObjectTypeDB::bind_method(_MD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk);
+ ObjectTypeDB::bind_method(_MD("set_read_chunk_size","bytes"),&HTTPClient::set_read_chunk_size);
ObjectTypeDB::bind_method(_MD("set_blocking_mode","enabled"),&HTTPClient::set_blocking_mode);
ObjectTypeDB::bind_method(_MD("is_blocking_mode_enabled"),&HTTPClient::is_blocking_mode_enabled);
@@ -581,6 +601,8 @@ void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status);
ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll);
+ ObjectTypeDB::bind_method(_MD("query_string_from_dict:String","fields"),&HTTPClient::query_string_from_dict);
+
BIND_CONSTANT( METHOD_GET );
BIND_CONSTANT( METHOD_HEAD );
@@ -664,6 +686,21 @@ void HTTPClient::_bind_methods() {
}
+void HTTPClient::set_read_chunk_size(int p_size) {
+ ERR_FAIL_COND(p_size<256 || p_size>(1<<24));
+ read_chunk_size=p_size;
+}
+
+String HTTPClient::query_string_from_dict(const Dictionary& p_dict) {
+ String query = "";
+ Array keys = p_dict.keys();
+ for (int i = 0; i < keys.size(); ++i) {
+ query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape();
+ }
+ query.erase(0, 1);
+ return query;
+}
+
HTTPClient::HTTPClient(){
tcp_connection = StreamPeerTCP::create_ref();
@@ -677,7 +714,7 @@ HTTPClient::HTTPClient(){
response_num=0;
ssl=false;
blocking=false;
- tmp_read.resize(4096);
+ read_chunk_size=4096;
}
HTTPClient::~HTTPClient(){
@@ -685,4 +722,3 @@ HTTPClient::~HTTPClient(){
}
-
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 09ad64f48a..b103dc43fc 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -157,7 +157,10 @@ private:
static void _bind_methods();
StringArray _get_response_headers();
Dictionary _get_response_headers_as_dictionary();
- ByteArray tmp_read;
+ int read_chunk_size;
+
+ Error _get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received);
+
public:
@@ -185,9 +188,12 @@ public:
void set_blocking_mode(bool p_enable); //useful mostly if running in a thread
bool is_blocking_mode_enabled() const;
+ void set_read_chunk_size(int p_size);
Error poll();
+ String query_string_from_dict(const Dictionary& p_dict);
+
HTTPClient();
~HTTPClient();
};
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 180df8964b..2db6e00f0a 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/image_loader.h b/core/io/image_loader.h
index 665cc0b460..ff972696ea 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
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/ip.cpp b/core/io/ip.cpp
index 6ef6b31188..523f9f472b 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -183,7 +183,7 @@ void IP::erase_resolve_item(ResolverID p_id) {
GLOBAL_LOCK_FUNCTION;
- resolver->queue[p_id].status=IP::RESOLVER_STATUS_DONE;
+ resolver->queue[p_id].status=IP::RESOLVER_STATUS_NONE;
}
diff --git a/core/io/ip.h b/core/io/ip.h
index 0181dc7d12..6f50a190e6 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index a1400adbb6..ed5a45c9ef 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,7 +47,7 @@ IP_Address::IP_Address(const String& p_string) {
}
for(int i=0;i<4;i++) {
- field[i]=p_string.get_slice(".",i).to_int();
+ field[i]=p_string.get_slicec('.',i).to_int();
}
}
diff --git a/core/io/ip_address.h b/core/io/ip_address.h
index 3cd8bb7733..e55f45a2d7 100644
--- a/core/io/ip_address.h
+++ b/core/io/ip_address.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/json.cpp b/core/io/json.cpp
index a83d7e4d6e..22c99d0465 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -177,9 +177,6 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
case 'n': res=10; break;
case 'f': res=12; break;
case 'r': res=13; break;
- case '\"': res='\"'; break;
- case '\\': res='\\'; break;
- case '/': res='/'; break; //wtf
case 'u': {
//hexnumbarh - oct is deprecated
@@ -218,10 +215,13 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
} break;
+ //case '\"': res='\"'; break;
+ //case '\\': res='\\'; break;
+ //case '/': res='/'; break;
default: {
-
- r_err_str="Invalid escape sequence";
- return ERR_PARSE_ERROR;
+ res = next;
+ //r_err_str="Invalid escape sequence";
+ //return ERR_PARSE_ERROR;
} break;
}
@@ -250,7 +250,7 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) {
//a number
const CharType *rptr;
- double number = String::to_double(&p_str[idx],-1,&rptr);
+ double number = String::to_double(&p_str[idx],&rptr);
idx+=(rptr - &p_str[idx]);
r_token.type=TK_NUMBER;
r_token.value=number;
diff --git a/core/io/json.h b/core/io/json.h
index d113d0e4ef..78b6303451 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index c6c15af5e0..62ccd81489 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,10 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
const uint8_t * buf=p_buffer;
int len=p_len;
- ERR_FAIL_COND_V(len<4,ERR_INVALID_DATA);
+ if (len<4) {
+
+ ERR_FAIL_COND_V(len<4,ERR_INVALID_DATA);
+ }
uint32_t type=decode_uint32(buf);
@@ -299,10 +302,8 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
ERR_FAIL_COND_V(len<12,ERR_INVALID_DATA);
Vector<StringName> names;
Vector<StringName> subnames;
- bool absolute;
StringName prop;
- int i=0;
uint32_t namecount=strlen&=0x7FFFFFFF;
uint32_t subnamecount = decode_uint32(buf+4);
uint32_t flags = decode_uint32(buf+8);
@@ -391,7 +392,6 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
ie.type=decode_uint32(&buf[0]);
ie.device=decode_uint32(&buf[4]);
- uint32_t len = decode_uint32(&buf[8])-12;
if (r_len)
(*r_len)+=12;
diff --git a/core/io/marshalls.h b/core/io/marshalls.h
index bb8d3b336a..df673debf5 100644
--- a/core/io/marshalls.h
+++ b/core/io/marshalls.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index b566ce4b7b..f6d526b512 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@
PacketPeer::PacketPeer() {
-
+ last_get_error=OK;
}
Error PacketPeer::get_packet_buffer(DVector<uint8_t> &r_buffer) const {
@@ -108,10 +108,29 @@ Variant PacketPeer::_bnd_get_var() const {
return var;
};
+Error PacketPeer::_put_packet(const DVector<uint8_t> &p_buffer) {
+ return put_packet_buffer(p_buffer);
+}
+DVector<uint8_t> PacketPeer::_get_packet() const {
+
+ DVector<uint8_t> raw;
+ last_get_error=get_packet_buffer(raw);
+ return raw;
+}
+
+Error PacketPeer::_get_packet_error() const {
+
+ return last_get_error;
+}
+
+
void PacketPeer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var);
ObjectTypeDB::bind_method(_MD("put_var", "var:var"),&PacketPeer::put_var);
+ ObjectTypeDB::bind_method(_MD("get_packet"),&PacketPeer::_get_packet);
+ ObjectTypeDB::bind_method(_MD("put_packet:Error", "buffer"),&PacketPeer::_put_packet);
+ ObjectTypeDB::bind_method(_MD("get_packet_error:Error"),&PacketPeer::_get_packet_error);
ObjectTypeDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count);
};
@@ -137,7 +156,6 @@ Error PacketPeerStream::_poll_buffer() const {
Error err = peer->get_partial_data(&temp_buffer[0], ring_buffer.space_left(), read);
if (err)
return err;
-
if (read==0)
return OK;
@@ -183,7 +201,7 @@ Error PacketPeerStream::get_packet(const uint8_t **r_buffer,int &r_buffer_size)
uint8_t lbuf[4];
ring_buffer.copy(lbuf,0,4);
remaining-=4;
- uint32_t len = decode_uint32(lbuf);
+ uint32_t len = decode_uint32(lbuf);
ERR_FAIL_COND_V(remaining<(int)len,ERR_UNAVAILABLE);
ring_buffer.read(lbuf,4); //get rid of first 4 bytes
diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h
index e9d6be4fb9..76d1eb22b5 100644
--- a/core/io/packet_peer.h
+++ b/core/io/packet_peer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,6 +41,14 @@ class PacketPeer : public Reference {
static void _bind_methods();
+
+ Error _put_packet(const DVector<uint8_t> &p_buffer);
+ DVector<uint8_t> _get_packet() const;
+ Error _get_packet_error() const;
+
+
+ mutable Error last_get_error;
+
public:
virtual int get_available_packet_count() const=0;
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index e2371fe24f..1a0552e8d1 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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,16 +387,21 @@ 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();
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()+"/"+path);
+ path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path));
}
+ 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);
}
@@ -663,14 +702,18 @@ Error ResourceInteractiveLoaderBinary::poll(){
//maybe it is loaded already
String path;
+ int subindex=0;
if (!main) {
path=internal_resources[s].path;
- if (path.begins_with("local://"))
- path=path.replace("local://",res_path+"::");
+ if (path.begins_with("local://")) {
+ path=path.replace_first("local://","");
+ subindex = path.to_int();
+ path=res_path+"::"+path;
+ }
@@ -709,6 +752,7 @@ Error ResourceInteractiveLoaderBinary::poll(){
RES res = RES( r );
r->set_path(path);
+ r->set_subindex(subindex);
int pc = f->get_32();
@@ -782,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();
@@ -796,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)
@@ -809,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);
}
@@ -861,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 || (ver_major==VERSION_MAJOR && ver_minor>VERSION_MINOR)) {
+ 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);
@@ -898,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();
@@ -908,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();
@@ -968,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 || (ver_major==VERSION_MAJOR && ver_minor>VERSION_MINOR)) {
+ if (ver_format>FORMAT_VERSION || ver_major>VERSION_MAJOR) {
f->close();
return "";
@@ -995,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);
@@ -1109,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);
@@ -1118,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;
}
@@ -1428,20 +1710,18 @@ 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_map.has(res)) {
+ if (!resource_set.has(res)) {
f->store_32(OBJECT_EMPTY);
ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
ERR_FAIL();
}
f->store_32(OBJECT_INTERNAL_RESOURCE);
- f->store_32(resource_map[res]);
+ f->store_32(res->get_subindex());
//internal resource
}
@@ -1589,16 +1869,17 @@ 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;
}
- if (resource_map.has(res))
+ if (resource_set.has(res))
return;
List<PropertyInfo> property_list;
@@ -1613,7 +1894,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant& p_variant
}
}
- resource_map[ res ] = saved_resources.size();
+ resource_set.insert(res);
saved_resources.push_back(res);
} break;
@@ -1778,6 +2059,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
f->store_32(VERSION_MINOR);
f->store_32(FORMAT_VERSION);
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
save_unicode_string(p_resource->get_type());
uint64_t md_at = f->get_pos();
@@ -1809,7 +2095,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
Property p;
p.name_idx=get_string_index(F->get().name);
p.value=E->get()->get(F->get().name);
- if (F->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero())
+ if ((F->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero())||(F->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && p.value.is_one()) )
continue;
p.pi=F->get();
@@ -1832,25 +2118,65 @@ 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();
+ }
+
+ for(int i=0;i<save_order.size();i++) {
- save_unicode_string(E->get()->get_save_type());
- String path = E->get()->get_path();
+ 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
f->store_32(saved_resources.size()); //amount of internal resources
Vector<uint64_t> ofs_pos;
+ Set<int> used_indices;
+
for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
RES r = E->get();
if (r->get_path()=="" || r->get_path().find("::")!=-1) {
- save_unicode_string("local://"+itos(ofs_pos.size()));
+
+ if (r->get_subindex()!=0) {
+ if (used_indices.has(r->get_subindex())) {
+ r->set_subindex(0); //repeated
+ } else {
+ used_indices.insert(r->get_subindex());
+ }
+ }
+ }
+
+ }
+
+
+ for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
+
+
+ RES r = E->get();
+ if (r->get_path()=="" || r->get_path().find("::")!=-1) {
+ if (r->get_subindex()==0) {
+ int new_subindex=1;
+ if (used_indices.size()) {
+ new_subindex=used_indices.back()->get()+1;
+ }
+
+ r->set_subindex(new_subindex);
+ used_indices.insert(new_subindex);
+
+ }
+
+ save_unicode_string("local://"+itos(r->get_subindex()));
if (takeover_paths) {
- r->set_path(p_path+"::"+itos(ofs_pos.size()),true);
+ r->set_path(p_path+"::"+itos(r->get_subindex()),true);
}
- } else
+ } else {
save_unicode_string(r->get_path()); //actual external
+ }
ofs_pos.push_back(f->get_pos());
f->store_64(0); //offset in 64 bits
}
@@ -1910,6 +2236,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
f->store_buffer((const uint8_t*)"RSRC",4); //magic at end
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
f->close();
@@ -1949,3 +2280,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 cc26357bfb..8bf20bc574 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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);
@@ -129,12 +132,12 @@ class ResourceFormatSaverBinaryInstance {
int bin_meta_idx;
FileAccess *f;
String magic;
- Map<RES,int> resource_map;
+ Set<RES> resource_set;
Map<StringName,int> string_map;
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 75384d4ab6..48917a19ea 100644
--- a/core/io/resource_format_xml.cpp
+++ b/core/io/resource_format_xml.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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;
@@ -309,6 +317,7 @@ Error ResourceInteractiveLoaderXML::_parse_array_element(Vector<char> &buff,bool
buff_max++;
buff.resize(buff_max);
+ buffptr=buff.ptr();
}
@@ -458,10 +467,14 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
path=path.replace("local://",local_path+"::");
else 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(local_path.get_base_dir()+"/"+path);
+ path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
}
+ 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);
@@ -472,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.");
@@ -1206,47 +1240,47 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
r_v=Vector3(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double(),
+ data.get_slicec(',',2).to_double()
);
} else if (type=="vector2") {
r_v=Vector2(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double()
);
} else if (type=="plane") {
r_v=Plane(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double(),
+ data.get_slicec(',',2).to_double(),
+ data.get_slicec(',',3).to_double()
);
} else if (type=="quaternion") {
r_v=Quat(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double(),
+ data.get_slicec(',',2).to_double(),
+ data.get_slicec(',',3).to_double()
);
} else if (type=="rect2") {
r_v=Rect2(
Vector2(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double()
),
Vector2(
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
+ data.get_slicec(',',2).to_double(),
+ data.get_slicec(',',3).to_double()
)
);
@@ -1255,14 +1289,14 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
r_v=AABB(
Vector3(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double(),
+ data.get_slicec(',',2).to_double()
),
Vector3(
- data.get_slice(",",3).to_double(),
- data.get_slice(",",4).to_double(),
- data.get_slice(",",5).to_double()
+ data.get_slicec(',',3).to_double(),
+ data.get_slicec(',',4).to_double(),
+ data.get_slicec(',',5).to_double()
)
);
@@ -1271,7 +1305,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
Matrix32 m3;
for (int i=0;i<3;i++) {
for (int j=0;j<2;j++) {
- m3.elements[i][j]=data.get_slice(",",i*2+j).to_double();
+ m3.elements[i][j]=data.get_slicec(',',i*2+j).to_double();
}
}
r_v=m3;
@@ -1281,7 +1315,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
Matrix3 m3;
for (int i=0;i<3;i++) {
for (int j=0;j<3;j++) {
- m3.elements[i][j]=data.get_slice(",",i*3+j).to_double();
+ m3.elements[i][j]=data.get_slicec(',',i*3+j).to_double();
}
}
r_v=m3;
@@ -1291,24 +1325,24 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
Transform tr;
for (int i=0;i<3;i++) {
for (int j=0;j<3;j++) {
- tr.basis.elements[i][j]=data.get_slice(",",i*3+j).to_double();
+ tr.basis.elements[i][j]=data.get_slicec(',',i*3+j).to_double();
}
}
tr.origin=Vector3(
- data.get_slice(",",9).to_double(),
- data.get_slice(",",10).to_double(),
- data.get_slice(",",11).to_double()
+ data.get_slicec(',',9).to_double(),
+ data.get_slicec(',',10).to_double(),
+ data.get_slicec(',',11).to_double()
);
r_v=tr;
} else if (type=="color") {
r_v=Color(
- data.get_slice(",",0).to_double(),
- data.get_slice(",",1).to_double(),
- data.get_slice(",",2).to_double(),
- data.get_slice(",",3).to_double()
+ data.get_slicec(',',0).to_double(),
+ data.get_slicec(',',1).to_double(),
+ data.get_slicec(',',2).to_double(),
+ data.get_slicec(',',3).to_double()
);
} else if (type=="node_path") {
@@ -1363,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 unexisting 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);
@@ -1412,36 +1420,48 @@ 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);
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(local_path.get_base_dir()+"/"+path);
+ 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);
if (res.is_null()) {
if (ResourceLoader::get_abort_on_missing_resources()) {
- ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> referenced unexisting resource at: "+path);
+ 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;
@@ -1465,6 +1485,7 @@ Error ResourceInteractiveLoaderXML::poll() {
String type;
String path;
+ int subres=0;
if (!main) {
//loading resource
@@ -1475,11 +1496,15 @@ Error ResourceInteractiveLoaderXML::poll() {
ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <resource> missing 'type' field.");
ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT);
path=tag->args["path"];
+
error=OK;
if (path.begins_with("local://")) {
//built-in resource (but really external)
- path=path.replace("local://",local_path+"::");
+
+ path=path.replace("local://","");
+ subres=path.to_int();
+ path=local_path+"::"+path;
}
@@ -1518,6 +1543,7 @@ Error ResourceInteractiveLoaderXML::poll() {
res = RES( r );
if (path!="")
r->set_path(path);
+ r->set_subindex(subres);
//load properties
@@ -1559,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() {
@@ -1567,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);
@@ -1601,7 +1627,7 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *
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(local_path.get_base_dir()+"/"+path);
+ path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
}
if (path.ends_with("*")) {
@@ -1610,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");
@@ -1621,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) {
@@ -1667,10 +1858,10 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
ERR_FAIL();
}
- int major = version.get_slice(".",0).to_int();
- int minor = version.get_slice(".",1).to_int();
+ int major = version.get_slicec('.',0).to_int();
+ int minor = version.get_slicec('.',1).to_int();
- if (major>VERSION_MAJOR || (major==VERSION_MAJOR && minor>VERSION_MINOR)) {
+ if (major>VERSION_MAJOR) {
error=ERR_FILE_UNRECOGNIZED;
ResourceLoader::notify_load_error(local_path+": File Format '"+version+"' is too new. Please upgrade to a newer engine version.");
@@ -1679,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();
@@ -1690,7 +1882,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
}
print_line(local_path+" - EXTERNAL RESOURCES: "+itos(ext_resources.size()));
}
-
+*/
}
@@ -1723,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);
@@ -1760,7 +1955,6 @@ void ResourceFormatLoaderXML::get_recognized_extensions_for_type(const String& p
if (ext=="res")
continue;
p_extensions->push_back("x"+ext);
- p_extensions->push_back(ext);
}
p_extensions->push_back("xml");
@@ -1809,7 +2003,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) {
@@ -1821,11 +2015,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);
+}
+
+
/****************************************************************************************/
/****************************************************************************************/
/****************************************************************************************/
@@ -1845,11 +2055,11 @@ void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String>
void ResourceFormatSaverXMLInstance::escape(String& p_str) {
p_str=p_str.replace("&","&amp;");
- p_str=p_str.replace("<","&gt;");
- p_str=p_str.replace(">","&lt;");
+ p_str=p_str.replace("<","&lt;");
+ p_str=p_str.replace(">","&gt;");
p_str=p_str.replace("'","&apos;");
p_str=p_str.replace("\"","&quot;");
- for (int i=1;i<32;i++) {
+ for (char i=1;i<32;i++) {
char chr[2]={i,0};
const char hexn[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
@@ -2017,20 +2227,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()+"\"";
+
+
+ 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_map.has(res));
+ //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(resource_map[res])+"\"";
+ params+=" path=\"local://"+itos(res->get_subindex())+"\"";
+ }
}
} break;
@@ -2243,12 +2459,12 @@ void ResourceFormatSaverXMLInstance::write_property(const String& p_name,const V
List<Variant> keys;
dict.get_key_list(&keys);
+ keys.sort();
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
//if (!_check_type(dict[E->get()]))
// continue;
-
bool ok;
write_property("",E->get(),&ok);
ERR_CONTINUE(!ok);
@@ -2434,20 +2650,22 @@ 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.insert(res);
+ int index = external_resources.size();
+ external_resources[res]=index;
return;
}
- if (resource_map.has(res))
+ if (resource_set.has(res))
return;
List<PropertyInfo> property_list;
res->get_property_list( &property_list );
+ property_list.sort();
List<PropertyInfo>::Element *I=property_list.front();
@@ -2464,7 +2682,7 @@ void ResourceFormatSaverXMLInstance::_find_resources(const Variant& p_variant,bo
I=I->next();
}
- resource_map[ res ] = resource_map.size(); //saved after, so the childs it needs are available when loaded
+ resource_set.insert( res ); //saved after, so the childs it needs are available when loaded
saved_resources.push_back(res);
} break;
@@ -2525,22 +2743,37 @@ 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(Set<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);
}
+ Set<int> used_indices;
+ for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
+
+ RES res = E->get();
+ if (E->next() && (res->get_path()=="" || res->get_path().find("::") != -1 )) {
+
+ if (res->get_subindex()!=0) {
+ if (used_indices.has(res->get_subindex())) {
+ res->set_subindex(0); //repeated
+ } else {
+ used_indices.insert(res->get_subindex());
+ }
+ }
+ }
+ }
for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
RES res = E->get();
- ERR_CONTINUE(!resource_map.has(res));
+ ERR_CONTINUE(!resource_set.has(res));
bool main = (E->next()==NULL);
write_tabs();
@@ -2550,7 +2783,18 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
else if (res->get_path().length() && res->get_path().find("::") == -1 )
enter_tag("resource","type=\""+res->get_type()+"\" path=\""+res->get_path()+"\""); //bundled
else {
- int idx = resource_map[res];
+
+ if (res->get_subindex()==0) {
+ int new_subindex=1;
+ if (used_indices.size()) {
+ new_subindex=used_indices.back()->get()+1;
+ }
+
+ res->set_subindex(new_subindex);
+ used_indices.insert(new_subindex);
+ }
+
+ int idx = res->get_subindex();
enter_tag("resource","type=\""+res->get_type()+"\" path=\"local://"+itos(idx)+"\"");
if (takeover_paths) {
res->set_path(p_path+"::"+itos(idx),true);
@@ -2562,6 +2806,7 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
List<PropertyInfo> property_list;
res->get_property_list(&property_list);
+// property_list.sort();
for(List<PropertyInfo>::Element *PE = property_list.front();PE;PE=PE->next()) {
@@ -2572,9 +2817,12 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
String name = PE->get().name;
Variant value = res->get(name);
- if (PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())
+
+
+ if ((PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())||(PE->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()) )
continue;
+
write_property(name,value);
}
@@ -2592,6 +2840,11 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
}
exit_tag("resource_file");
+ if (f->get_error()!=OK && f->get_error()!=ERR_FILE_EOF) {
+ f->close();
+ return ERR_CANT_CREATE;
+ }
+
f->close();
//memdelete(f);
@@ -2624,3 +2877,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 40aaa01451..77987c6a5b 100644
--- a/core/io/resource_format_xml.h
+++ b/core/io/resource_format_xml.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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);
};
@@ -123,9 +133,9 @@ class ResourceFormatSaverXMLInstance {
bool skip_editor;
FileAccess *f;
int depth;
- Map<RES,int> resource_map;
+ Set<RES> resource_set;
List<RES> saved_resources;
- Set<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 d2610d5d4f..3862790b02 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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,11 +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);
@@ -129,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());
}
@@ -139,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
}
@@ -148,11 +155,18 @@ 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) {
- String local_path = Globals::get_singleton()->localize_path(p_path);
+ if (r_error)
+ *r_error=ERR_CANT_OPEN;
- local_path=find_complete_path(p_path,p_type_hint);
+ String local_path;
+ if (p_path.is_rel_path())
+ local_path="res://"+p_path;
+ else
+ local_path = Globals::get_singleton()->localize_path(p_path);
+
+ local_path=find_complete_path(local_path,p_type_hint);
ERR_FAIL_COND_V(local_path=="",RES());
if (!p_no_cache && ResourceCache::has(local_path)) {
@@ -178,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)
@@ -209,17 +223,20 @@ RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_n
Ref<ResourceImportMetadata> ResourceLoader::load_import_metadata(const String &p_path) {
- String local_path = Globals::get_singleton()->localize_path(p_path);
+
+ 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 extension=p_path.extension();
- bool found=false;
Ref<ResourceImportMetadata> ret;
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
- found=true;
Error err = loader[i]->load_import_metadata(local_path,ret);
if (err==OK)
@@ -279,13 +296,19 @@ 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 = Globals::get_singleton()->localize_path(p_path);
+ String local_path;
+ if (p_path.is_rel_path())
+ local_path="res://"+p_path;
+ else
+ local_path = Globals::get_singleton()->localize_path(p_path);
- local_path=find_complete_path(p_path,p_type_hint);
+ local_path=find_complete_path(local_path,p_type_hint);
ERR_FAIL_COND_V(local_path=="",Ref<ResourceInteractiveLoader>());
@@ -313,7 +336,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)
@@ -338,9 +361,15 @@ 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 local_path = Globals::get_singleton()->localize_path(p_path);
String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
String extension=remapped_path.extension();
@@ -352,14 +381,47 @@ 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);
+ 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;
+ 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;
+
+ 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 = Globals::get_singleton()->localize_path(p_path);
+ String local_path;
+ if (p_path.is_rel_path())
+ local_path="res://"+p_path;
+ else
+ local_path = Globals::get_singleton()->localize_path(p_path);
return find_complete_path(local_path,p_type);
@@ -367,7 +429,12 @@ String ResourceLoader::guess_full_filename(const String &p_path,const String& p_
String ResourceLoader::get_resource_type(const String &p_path) {
- String local_path = Globals::get_singleton()->localize_path(p_path);
+ 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();
@@ -385,6 +452,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 ab23158785..00a05dcb43 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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.cpp b/core/io/resource_saver.cpp
index 598f517d76..fdb9a53f0d 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index e307668721..8382b65290 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/stream_peer.cpp b/core/io/stream_peer.cpp
index 0eae660373..b00b462eb6 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index 84552cfd3e..e83fc71b93 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 0e75e22767..c2343790ea 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,7 +32,7 @@ StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL;
void StreamPeerTCP::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("connect","host","ip"),&StreamPeerTCP::connect);
+ ObjectTypeDB::bind_method(_MD("connect","host","port"),&StreamPeerTCP::connect);
ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected);
ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status);
ObjectTypeDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host);
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index d447ded78b..0e37303516 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index bce9e19ae3..803df87086 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h
index fff00e5ce0..b59f3293d7 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 0d42cebb41..020d168208 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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 7a0c4e10dc..e07ae15e28 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/unzip.c b/core/io/unzip.c
index 0cd975211e..b438021ad7 100644
--- a/core/io/unzip.c
+++ b/core/io/unzip.c
@@ -1788,7 +1788,7 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
return UNZ_PARAMERROR;
- if ((pfile_in_zip_read_info->read_buffer == NULL))
+ if (pfile_in_zip_read_info->read_buffer==NULL)
return UNZ_END_OF_LIST_OF_FILE;
if (len==0)
return 0;
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 1d69f8e5e7..1ff458f325 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 9debbf9e2f..418a8efa70 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/io/zip.c b/core/io/zip.c
index 8f6aeb922f..c4ab93ab81 100644
--- a/core/io/zip.c
+++ b/core/io/zip.c
@@ -1114,9 +1114,9 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
zi->ci.flag = flagBase;
if ((level==8) || (level==9))
zi->ci.flag |= 2;
- if ((level==2))
+ if (level==2)
zi->ci.flag |= 4;
- if ((level==1))
+ if (level==1)
zi->ci.flag |= 6;
if (password != NULL)
zi->ci.flag |= 1;
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 798265cc48..dd3c371a4a 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/list.h b/core/list.h
index f581feb735..018abca940 100644
--- a/core/list.h
+++ b/core/list.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#define GLOBALS_LIST_H
#include "os/memory.h"
-
+#include "sort.h"
/**
* Generic Templatized Linked List Implementation.
@@ -518,10 +518,16 @@ public:
if (value->prev_ptr) {
value->prev_ptr->next_ptr = value->next_ptr;
- };
+ }
+ else {
+ _data->first = value->next_ptr;
+ }
if (value->next_ptr) {
value->next_ptr->prev_ptr = value->prev_ptr;
- };
+ }
+ else {
+ _data->last = value->prev_ptr;
+ }
value->next_ptr = where;
if (!where) {
@@ -551,7 +557,7 @@ public:
}
template<class C>
- void sort_custom() {
+ void sort_custom_inplace() {
if(size()<2)
return;
@@ -603,6 +609,58 @@ public:
_data->last=to;
}
+ template<class C>
+ struct AuxiliaryComparator {
+
+ C compare;
+ _FORCE_INLINE_ bool operator()(const Element *a,const Element* b) const {
+
+ return compare(a->value,b->value);
+ }
+ };
+
+ template<class C>
+ void sort_custom() {
+
+ //this version uses auxiliary memory for speed.
+ //if you don't want to use auxiliary memory, use the in_place version
+
+ int s = size();
+ if(s<2)
+ return;
+
+
+ Element **aux_buffer = memnew_arr(Element*,s);
+
+ int idx=0;
+ for(Element *E=front();E;E=E->next_ptr) {
+
+ aux_buffer[idx]=E;
+ idx++;
+ }
+
+ SortArray<Element*,AuxiliaryComparator<C> > sort;
+ sort.sort(aux_buffer,s);
+
+ _data->first=aux_buffer[0];
+ aux_buffer[0]->prev_ptr=NULL;
+ aux_buffer[0]->next_ptr=aux_buffer[1];
+
+ _data->last=aux_buffer[s-1];
+ aux_buffer[s-1]->prev_ptr=aux_buffer[s-2];
+ aux_buffer[s-1]->next_ptr=NULL;
+
+ for(int i=1;i<s-1;i++) {
+
+ aux_buffer[i]->prev_ptr=aux_buffer[i-1];
+ aux_buffer[i]->next_ptr=aux_buffer[i+1];
+
+ }
+
+ memdelete_arr(aux_buffer);
+ }
+
+
/**
* copy constructor for the list
*/
diff --git a/core/map.h b/core/map.h
index 05abdc510e..e45c833bcb 100644
--- a/core/map.h
+++ b/core/map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/SCsub b/core/math/SCsub
index c6ba1fa537..7b4a6acbc0 100644
--- a/core/math/SCsub
+++ b/core/math/SCsub
@@ -3,5 +3,3 @@ Import('env')
env.add_source_files(env.core_sources,"*.cpp")
Export('env')
-
-
diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp
index 576e4fa928..435df66aab 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 089d5d15f7..4781e5c263 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -110,17 +110,17 @@ public:
inline bool AABB::intersects(const AABB& p_aabb) const {
- if ( pos.x > (p_aabb.pos.x + p_aabb.size.x) )
+ if ( pos.x >= (p_aabb.pos.x + p_aabb.size.x) )
return false;
- if ( (pos.x+size.x) < p_aabb.pos.x )
+ if ( (pos.x+size.x) <= p_aabb.pos.x )
return false;
- if ( pos.y > (p_aabb.pos.y + p_aabb.size.y) )
+ if ( pos.y >= (p_aabb.pos.y + p_aabb.size.y) )
return false;
- if ( (pos.y+size.y) < p_aabb.pos.y )
+ if ( (pos.y+size.y) <= p_aabb.pos.y )
return false;
- if ( pos.z > (p_aabb.pos.z + p_aabb.size.z) )
+ if ( pos.z >= (p_aabb.pos.z + p_aabb.size.z) )
return false;
- if ( (pos.z+size.z) < p_aabb.pos.z )
+ if ( (pos.z+size.z) <= p_aabb.pos.z )
return false;
return true;
diff --git a/core/math/bezier_curve.cpp b/core/math/bezier_curve.cpp
index 2676804945..c9467a77e4 100644
--- a/core/math/bezier_curve.cpp
+++ b/core/math/bezier_curve.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bezier_curve.h b/core/math/bezier_curve.h
index 6cc4c730db..de14d68987 100644
--- a/core/math/bezier_curve.h
+++ b/core/math/bezier_curve.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp
index 7f838b1215..d71b7551d9 100644
--- a/core/math/bsp_tree.cpp
+++ b/core/math/bsp_tree.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h
index 03bfd947cb..b980d9590b 100644
--- a/core/math/bsp_tree.h
+++ b/core/math/bsp_tree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index a60dea7379..f1afa33a4b 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -121,7 +121,7 @@ void CameraMatrix::set_orthogonal(float p_size, float p_aspect, float p_znear, f
void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, float p_top, float p_near, float p_far) {
-
+#if 0
///@TODO, give a check to this. I'm not sure if it's working.
set_identity();
@@ -133,10 +133,27 @@ void CameraMatrix::set_frustum(float p_left, float p_right, float p_bottom, floa
matrix[2][3]=-(2*p_far*p_near) / (p_far-p_near);
matrix[3][2]=-1;
matrix[3][3]=0;
+#else
+ float *te = &matrix[0][0];
+ float x = 2 * p_near / ( p_right - p_left );
+ float y = 2 * p_near / ( p_top - p_bottom );
+
+ float a = ( p_right + p_left ) / ( p_right - p_left );
+ float b = ( p_top + p_bottom ) / ( p_top - p_bottom );
+ float c = - ( p_far + p_near ) / ( p_far - p_near );
+ float d = - 2 * p_far * p_near / ( p_far - p_near );
+
+ te[0] = x; te[4] = 0; te[8] = a; te[12] = 0;
+ te[1] = 0; te[5] = y; te[9] = b; te[13] = 0;
+ te[2] = 0; te[6] = 0; te[10] = c; te[14] = d;
+ te[3] = 0; te[7] = 0; te[11] = - 1; te[15] = 0;
+
+#endif
}
+
float CameraMatrix::get_z_far() const {
const float * matrix = (const float*)this->matrix;
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 767236ea04..52b84f4870 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 1adc95e4e9..354372df74 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/face3.h b/core/math/face3.h
index 5a509299a2..eccbc78122 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index 2d525dd1ce..14adde74e7 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/geometry.h b/core/math/geometry.h
index 81530e30c0..b438b41d61 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -511,6 +511,20 @@ public:
else
return p_segment[0]+n*d; // inside
}
+
+ static bool is_point_in_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c)
+ {
+ int as_x = s.x-a.x;
+ int as_y = s.y-a.y;
+
+ bool s_ab = (b.x-a.x)*as_y-(b.y-a.y)*as_x > 0;
+
+ if(((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0) == s_ab) return false;
+
+ if(((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0) != s_ab) return false;
+
+ return true;
+ }
static Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2& p_point, const Vector2 *p_segment) {
Vector2 p=p_point-p_segment[0];
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index 3aaa539fbb..ce03f089e5 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,7 +29,7 @@
#include "math_2d.h"
-real_t Vector2::atan2() const {
+real_t Vector2::angle() const {
return Math::atan2(x,y);
}
@@ -165,7 +165,7 @@ Vector2 Vector2::floor() const {
Vector2 Vector2::rotated(float p_by) const {
Vector2 v;
- v.set_rotation(atan2()+p_by);
+ v.set_rotation(angle()+p_by);
v*=length();
return v;
}
@@ -230,6 +230,23 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co
+ Vector2 p0=p_pre_a;
+ Vector2 p1=*this;
+ Vector2 p2=p_b;
+ Vector2 p3=p_post_b;
+
+ float t = p_t;
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ Vector2 out;
+ out = 0.5f * ( ( p1 * 2.0f) +
+ ( -p0 + p2 ) * t +
+ ( 2.0f * p0 - 5.0f * p1 + 4 * p2 - p3 ) * t2 +
+ ( -p0 + 3.0f * p1 - 3.0f * p2 + p3 ) * t3 );
+ return out;
+
+/*
float mu = p_t;
float mu2 = mu*mu;
@@ -239,7 +256,7 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co
Vector2 a3 = *this;
return ( a0*mu*mu2 + a1*mu2 + a2*mu + a3 );
-
+*/
/*
float t = p_t;
real_t t2 = t*t;
@@ -605,9 +622,39 @@ float Matrix32::basis_determinant() const {
}
Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) const {
+
+ //extract parameters
+ Vector2 p1 = get_origin();
+ Vector2 p2 = p_transform.get_origin();
+
+ real_t r1 = get_rotation();
+ real_t r2 = p_transform.get_rotation();
+
+ Vector2 s1 = get_scale();
+ Vector2 s2 = p_transform.get_scale();
+
+ //slerp rotation
+ Vector2 v1(Math::cos(r1), Math::sin(r1));
+ Vector2 v2(Math::cos(r2), Math::sin(r2));
+
+ real_t dot = v1.dot(v2);
+
+ dot = (dot < -1.0) ? -1.0 : ((dot > 1.0) ? 1.0 : dot); //clamp dot to [-1,1]
+
+ Vector2 v;
-
- return Matrix32();
+ if (dot > 0.9995) {
+ v = Vector2::linear_interpolate(v1, v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
+ } else {
+ real_t angle = p_c*Math::acos(dot);
+ Vector2 v3 = (v2 - v1*dot).normalized();
+ v = v1*Math::cos(angle) + v3*Math::sin(angle);
+ }
+
+ //construct matrix
+ Matrix32 res(Math::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c));
+ res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c));
+ return res;
}
Matrix32::operator String() const {
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index fa40d305f5..3d40e24091 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -133,7 +133,7 @@ struct Vector2 {
bool operator<(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y<p_vec2.y):(x<p_vec2.x); }
bool operator<=(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y<=p_vec2.y):(x<=p_vec2.x); }
- real_t atan2() const;
+ real_t angle() const;
void set_rotation(float p_radians) {
@@ -159,8 +159,8 @@ struct Vector2 {
operator String() const { return String::num(x)+","+String::num(y); }
- inline Vector2(float p_x,float p_y) { x=p_x; y=p_y; }
- inline Vector2() { x=0; y=0; }
+ _FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; }
+ _FORCE_INLINE_ Vector2() { x=0; y=0; }
};
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2& p_vec) const {
@@ -198,6 +198,8 @@ Vector2 Vector2::linear_interpolate(const Vector2& p_a, const Vector2& p_b,float
typedef Vector2 Size2;
typedef Vector2 Point2;
+struct Matrix32;
+
struct Rect2 {
@@ -212,18 +214,43 @@ struct Rect2 {
float get_area() const { return size.width*size.height; }
inline bool intersects(const Rect2& p_rect) const {
- if ( pos.x > (p_rect.pos.x + p_rect.size.width) )
+ if ( pos.x >= (p_rect.pos.x + p_rect.size.width) )
return false;
- if ( (pos.x+size.width) < p_rect.pos.x )
+ if ( (pos.x+size.width) <= p_rect.pos.x )
return false;
- if ( pos.y > (p_rect.pos.y + p_rect.size.height) )
+ if ( pos.y >= (p_rect.pos.y + p_rect.size.height) )
return false;
- if ( (pos.y+size.height) < p_rect.pos.y )
+ if ( (pos.y+size.height) <= p_rect.pos.y )
return false;
return true;
}
+ inline float distance_to(const Vector2& p_point) const {
+
+ float dist = 1e20;
+
+ if (p_point.x < pos.x) {
+ dist=MIN(dist,pos.x-p_point.x);
+ }
+ if (p_point.y < pos.y) {
+ dist=MIN(dist,pos.y-p_point.y);
+ }
+ if (p_point.x >= (pos.x+size.x) ) {
+ dist=MIN(p_point.x-(pos.x+size.x),dist);
+ }
+ if (p_point.y >= (pos.y+size.y) ) {
+ dist=MIN(p_point.y-(pos.y+size.y),dist);
+ }
+
+ if (dist==1e20)
+ return 0;
+ else
+ return dist;
+ }
+
+ _FORCE_INLINE_ bool intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const;
+
bool intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos=NULL, Point2* r_normal=NULL) const;
inline bool encloses(const Rect2& p_rect) const {
@@ -597,6 +624,160 @@ struct Matrix32 {
};
+bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const {
+
+ //SAT intersection between local and transformed rect2
+
+ Vector2 xf_points[4]={
+ p_xform.xform(p_rect.pos),
+ p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y)),
+ p_xform.xform(Vector2(p_rect.pos.x,p_rect.pos.y+p_rect.size.y)),
+ p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y+p_rect.size.y)),
+ };
+
+ real_t low_limit;
+
+ //base rect2 first (faster)
+
+ if (xf_points[0].y>pos.y)
+ goto next1;
+ if (xf_points[1].y>pos.y)
+ goto next1;
+ if (xf_points[2].y>pos.y)
+ goto next1;
+ if (xf_points[3].y>pos.y)
+ goto next1;
+
+ return false;
+
+ next1:
+
+ low_limit=pos.y+size.y;
+
+ if (xf_points[0].y<low_limit)
+ goto next2;
+ if (xf_points[1].y<low_limit)
+ goto next2;
+ if (xf_points[2].y<low_limit)
+ goto next2;
+ if (xf_points[3].y<low_limit)
+ goto next2;
+
+ return false;
+
+ next2:
+
+ if (xf_points[0].x>pos.x)
+ goto next3;
+ if (xf_points[1].x>pos.x)
+ goto next3;
+ if (xf_points[2].x>pos.x)
+ goto next3;
+ if (xf_points[3].x>pos.x)
+ goto next3;
+
+ return false;
+
+ next3:
+
+ low_limit=pos.x+size.x;
+
+ if (xf_points[0].x<low_limit)
+ goto next4;
+ if (xf_points[1].x<low_limit)
+ goto next4;
+ if (xf_points[2].x<low_limit)
+ goto next4;
+ if (xf_points[3].x<low_limit)
+ goto next4;
+
+ return false;
+
+ next4:
+
+ Vector2 xf_points2[4]={
+ pos,
+ Vector2(pos.x+size.x,pos.y),
+ Vector2(pos.x,pos.y+size.y),
+ Vector2(pos.x+size.x,pos.y+size.y),
+ };
+
+ real_t maxa=p_xform.elements[0].dot(xf_points2[0]);
+ real_t mina=maxa;
+
+ real_t dp = p_xform.elements[0].dot(xf_points2[1]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[0].dot(xf_points2[2]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[0].dot(xf_points2[3]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ real_t maxb=p_xform.elements[0].dot(xf_points[0]);
+ real_t minb=maxb;
+
+ dp = p_xform.elements[0].dot(xf_points[1]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[0].dot(xf_points[2]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[0].dot(xf_points[3]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+
+ if ( mina > maxb )
+ return false;
+ if ( minb > maxa )
+ return false;
+
+ maxa=p_xform.elements[1].dot(xf_points2[0]);
+ mina=maxa;
+
+ dp = p_xform.elements[1].dot(xf_points2[1]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[1].dot(xf_points2[2]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[1].dot(xf_points2[3]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ maxb=p_xform.elements[1].dot(xf_points[0]);
+ minb=maxb;
+
+ dp = p_xform.elements[1].dot(xf_points[1]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[1].dot(xf_points[2]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[1].dot(xf_points[3]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+
+ if ( mina > maxb )
+ return false;
+ if ( minb > maxa )
+ return false;
+
+
+ return true;
+
+}
Vector2 Matrix32::basis_xform(const Vector2& v) const {
diff --git a/core/math/math_defs.cpp b/core/math/math_defs.cpp
index ca43bc7ae3..51aaa6800e 100644
--- a/core/math/math_defs.cpp
+++ b/core/math/math_defs.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,5 +26,5 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "math_defs.h"
-
+#include "math_defs.h"
+
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index dd0390240a..7cb6c7f499 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,35 +26,35 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef MATH_DEFS_H
-#define MATH_DEFS_H
-
-#define CMP_EPSILON 0.00001
-#define CMP_EPSILON2 (CMP_EPSILON*CMP_EPSILON)
-#define CMP_NORMALIZE_TOLERANCE 0.000001
-#define CMP_POINT_IN_PLANE_EPSILON 0.00001
-
-/**
- * "Real" is a type that will be translated to either floats or fixed depending
- * on the compilation setting
- */
-
-enum ClockDirection {
-
- CLOCKWISE,
- COUNTERCLOCKWISE
-};
-
-
-#ifdef REAL_T_IS_DOUBLE
-
-typedef double real_t;
-
-#else
-
-typedef float real_t;
-
-#endif
-
-
-#endif // MATH_DEFS_H
+#ifndef MATH_DEFS_H
+#define MATH_DEFS_H
+
+#define CMP_EPSILON 0.00001
+#define CMP_EPSILON2 (CMP_EPSILON*CMP_EPSILON)
+#define CMP_NORMALIZE_TOLERANCE 0.000001
+#define CMP_POINT_IN_PLANE_EPSILON 0.00001
+
+/**
+ * "Real" is a type that will be translated to either floats or fixed depending
+ * on the compilation setting
+ */
+
+enum ClockDirection {
+
+ CLOCKWISE,
+ COUNTERCLOCKWISE
+};
+
+
+#ifdef REAL_T_IS_DOUBLE
+
+typedef double real_t;
+
+#else
+
+typedef float real_t;
+
+#endif
+
+
+#endif // MATH_DEFS_H
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index ad48ceaac0..3c94ac5bc7 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,8 +36,9 @@ uint32_t Math::default_seed=1;
#define PHI 0x9e3779b9
-static uint32_t Q[4096], c = 362436;
-
+#if 0
+static uint32_t Q[4096];
+#endif
uint32_t Math::rand_from_seed(uint32_t *seed) {
@@ -48,8 +49,8 @@ uint32_t Math::rand_from_seed(uint32_t *seed) {
s = 0x12345987;
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
- if (s < 0)
- s += 2147483647;
+// if (s < 0)
+// s += 2147483647;
(*seed) = s;
return (s & Math::RANDOM_MAX);
#else
@@ -269,7 +270,7 @@ bool Math::is_inf(double p_val) {
uint32_t Math::larger_prime(uint32_t p_val) {
- static const int primes[] = {
+ static const uint32_t primes[] = {
5,
13,
23,
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 28a8413325..ec089ebc8b 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,9 +79,9 @@ public:
return Math::log( p_linear ) * 8.6858896380650365530225783783321;
}
- static inline double db2linear(double p_linear) {
+ static inline double db2linear(double p_db) {
- return Math::exp( p_linear * 0.11512925464970228420089957273422 );
+ return Math::exp( p_db * 0.11512925464970228420089957273422 );
}
static bool is_nan(double p_val);
@@ -136,7 +136,7 @@ public:
static int b;
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603 // windows 8?
+#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone?
b = (int)((a>0.0f) ? (a + 0.5f):(a -0.5f));
#elif defined(_MSC_VER) && _MSC_VER < 1800
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index ff62e7786b..10f1461fdc 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/matrix3.h b/core/math/matrix3.h
index f68703ca23..98feb2dbbd 100644
--- a/core/math/matrix3.h
+++ b/core/math/matrix3.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/octree.h b/core/math/octree.h
index b64ba381c0..84de388178 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/plane.cpp b/core/math/plane.cpp
index 88c7be5f63..f9395a002a 100644
--- a/core/math/plane.cpp
+++ b/core/math/plane.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/plane.h b/core/math/plane.h
index 608ec26926..604b880266 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
index 950a4756ad..e0c4b0793c 100644
--- a/core/math/quat.cpp
+++ b/core/math/quat.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quat.h b/core/math/quat.h
index 04901116b8..f161e35074 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -73,7 +73,7 @@ public:
-x * v.x - y * v.y - z * v.z);
}
- _FORCE_INLINE_ Vector3 xform(const Vector3& v) {
+ _FORCE_INLINE_ Vector3 xform(const Vector3& v) const {
Quat q = *this * v;
q *= this->inverse();
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index a417cdaddf..80ae0f04e1 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h
index d7f056d366..cb486a0b6f 100644
--- a/core/math/quick_hull.h
+++ b/core/math/quick_hull.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/transform.cpp b/core/math/transform.cpp
index bb874facbd..a6f4f626cc 100644
--- a/core/math/transform.cpp
+++ b/core/math/transform.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/transform.h b/core/math/transform.h
index b1a0ea1ab8..a992843d70 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 111ceca185..70cb639fc2 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,543 +26,543 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "triangle_mesh.h"
-#include "sort.h"
-
-
-
-int TriangleMesh::_create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_depth,int&max_depth,int&max_alloc) {
-
-
- if (p_depth>max_depth) {
- max_depth=p_depth;
- }
-
- if (p_size==1) {
-
-
- return p_bb[p_from]-p_bvh;
- } else if (p_size==0) {
-
- return -1;
- }
-
-
- AABB aabb;
- aabb=p_bb[p_from]->aabb;
- for(int i=1;i<p_size;i++) {
-
- aabb.merge_with(p_bb[p_from+i]->aabb);
- }
-
- int li=aabb.get_longest_axis_index();
-
- switch(li) {
-
- case Vector3::AXIS_X: {
- SortArray<BVH*,BVHCmpX> sort_x;
- sort_x.nth_element(0,p_size,p_size/2,&p_bb[p_from]);
- //sort_x.sort(&p_bb[p_from],p_size);
- } break;
- case Vector3::AXIS_Y: {
- SortArray<BVH*,BVHCmpY> sort_y;
- sort_y.nth_element(0,p_size,p_size/2,&p_bb[p_from]);
- //sort_y.sort(&p_bb[p_from],p_size);
- } break;
- case Vector3::AXIS_Z: {
- SortArray<BVH*,BVHCmpZ> sort_z;
- sort_z.nth_element(0,p_size,p_size/2,&p_bb[p_from]);
- //sort_z.sort(&p_bb[p_from],p_size);
-
- } break;
- }
-
-
- int left = _create_bvh(p_bvh,p_bb,p_from,p_size/2,p_depth+1,max_depth,max_alloc);
- int right = _create_bvh(p_bvh,p_bb,p_from+p_size/2,p_size-p_size/2,p_depth+1,max_depth,max_alloc);
-
- int index=max_alloc++;
- BVH *_new = &p_bvh[index];
- _new->aabb=aabb;
- _new->center=aabb.pos+aabb.size*0.5;
- _new->face_index=-1;
- _new->left=left;
- _new->right=right;
-
- return index;
-
-}
-
-
-void TriangleMesh::create(const DVector<Vector3>& p_faces) {
-
- valid=false;
-
- int fc=p_faces.size();
- ERR_FAIL_COND(!fc || ((fc%3) != 0));
- fc/=3;
- triangles.resize(fc);
-
- bvh.resize(fc*3); //will never be larger than this (todo make better)
- DVector<BVH>::Write bw = bvh.write();
-
- {
-
- //create faces and indices and base bvh
- //except for the Set for repeated triangles, everything
- //goes in-place.
-
- DVector<Vector3>::Read r = p_faces.read();
- DVector<Triangle>::Write w = triangles.write();
- Map<Vector3,int> db;
-
- for(int i=0;i<fc;i++) {
-
- Triangle&f=w[i];
- const Vector3 *v=&r[i*3];
-
- for(int j=0;j<3;j++) {
-
- int vidx=-1;
- Vector3 vs=v[j].snapped(0.0001);
- Map<Vector3,int>::Element *E=db.find(vs);
- if (E) {
- vidx=E->get();
- } else {
- vidx=db.size();
- db[vs]=vidx;
- }
-
- f.indices[j]=vidx;
- if (j==0)
- bw[i].aabb.pos=vs;
- else
- bw[i].aabb.expand_to(vs);
- }
-
- f.normal=Face3(r[i*3+0],r[i*3+1],r[i*3+2]).get_plane().get_normal();
-
- bw[i].left=-1;
- bw[i].right=-1;
- bw[i].face_index=i;
- bw[i].center=bw[i].aabb.pos+bw[i].aabb.size*0.5;
- }
-
- vertices.resize(db.size());
- DVector<Vector3>::Write vw = vertices.write();
- for (Map<Vector3,int>::Element *E=db.front();E;E=E->next()) {
- vw[E->get()]=E->key();
- }
-
- }
-
- DVector<BVH*> bwptrs;
- bwptrs.resize(fc);
- DVector<BVH*>::Write bwp = bwptrs.write();
- for(int i=0;i<fc;i++) {
-
- bwp[i]=&bw[i];
- }
-
- max_depth=0;
- int max_alloc=fc;
- int max=_create_bvh(bw.ptr(),bwp.ptr(),0,fc,1,max_depth,max_alloc);
-
- bw=DVector<BVH>::Write(); //clearup
- bvh.resize(max_alloc); //resize back
-
- valid=true;
-
-}
-
-
-Vector3 TriangleMesh::get_area_normal(const AABB& p_aabb) const {
-
- uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth);
-
- enum {
- TEST_AABB_BIT=0,
- VISIT_LEFT_BIT=1,
- VISIT_RIGHT_BIT=2,
- VISIT_DONE_BIT=3,
- VISITED_BIT_SHIFT=29,
- NODE_IDX_MASK=(1<<VISITED_BIT_SHIFT)-1,
- VISITED_BIT_MASK=~NODE_IDX_MASK,
-
-
- };
-
- int n_count=0;
- Vector3 n;
-
- //for(int i=0;i<max_depth;i++)
- // stack[i]=0;
-
- int level=0;
-
- DVector<Triangle>::Read trianglesr = triangles.read();
- DVector<Vector3>::Read verticesr=vertices.read();
- DVector<BVH>::Read bvhr=bvh.read();
-
- const Triangle *triangleptr=trianglesr.ptr();
- const Vector3 *vertexptr=verticesr.ptr();
- int pos=bvh.size()-1;
- const BVH *bvhptr = bvhr.ptr();
-
- stack[0]=pos;
- while(true) {
-
- uint32_t node = stack[level]&NODE_IDX_MASK;
- const BVH &b = bvhptr[ node ];
- bool done=false;
-
- switch(stack[level]>>VISITED_BIT_SHIFT) {
- case TEST_AABB_BIT: {
-
-
- bool valid = b.aabb.intersects(p_aabb);
- if (!valid) {
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
-
- } else {
-
- if (b.face_index>=0) {
-
- const Triangle &s=triangleptr[ b.face_index ];
- n+=s.normal;
- n_count++;
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
-
- } else {
-
- stack[level]=(VISIT_LEFT_BIT<<VISITED_BIT_SHIFT)|node;
- }
- }
-
- } continue;
- case VISIT_LEFT_BIT: {
-
- stack[level]=(VISIT_RIGHT_BIT<<VISITED_BIT_SHIFT)|node;
- stack[level+1]=b.left|TEST_AABB_BIT;
- level++;
-
- } continue;
- case VISIT_RIGHT_BIT: {
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
- stack[level+1]=b.right|TEST_AABB_BIT;
- level++;
- } continue;
- case VISIT_DONE_BIT: {
-
- if (level==0) {
- done=true;
- break;
- } else
- level--;
-
- } continue;
- }
-
-
- if (done)
- break;
- }
-
-
- if (n_count>0)
- n/=n_count;
-
- return n;
-
-}
-
-
-bool TriangleMesh::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const {
-
-
- uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth);
-
- enum {
- TEST_AABB_BIT=0,
- VISIT_LEFT_BIT=1,
- VISIT_RIGHT_BIT=2,
- VISIT_DONE_BIT=3,
- VISITED_BIT_SHIFT=29,
- NODE_IDX_MASK=(1<<VISITED_BIT_SHIFT)-1,
- VISITED_BIT_MASK=~NODE_IDX_MASK,
-
-
- };
-
- Vector3 n = (p_end-p_begin).normalized();
- real_t d=1e10;
- bool inters=false;
-
- //for(int i=0;i<max_depth;i++)
- // stack[i]=0;
-
- int level=0;
- //AABB ray_aabb;
- //ray_aabb.pos=p_begin;
- //ray_aabb.expand_to(p_end);
-
-
- DVector<Triangle>::Read trianglesr = triangles.read();
- DVector<Vector3>::Read verticesr=vertices.read();
- DVector<BVH>::Read bvhr=bvh.read();
-
- const Triangle *triangleptr=trianglesr.ptr();
- const Vector3 *vertexptr=verticesr.ptr();
- int pos=bvh.size()-1;
- const BVH *bvhptr = bvhr.ptr();
-
- stack[0]=pos;
- while(true) {
-
- uint32_t node = stack[level]&NODE_IDX_MASK;
- const BVH &b = bvhptr[ node ];
- bool done=false;
-
- switch(stack[level]>>VISITED_BIT_SHIFT) {
- case TEST_AABB_BIT: {
-
-
- bool valid = b.aabb.intersects_segment(p_begin,p_end);
-// bool valid = b.aabb.intersects(ray_aabb);
-
- if (!valid) {
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
-
- } else {
-
- if (b.face_index>=0) {
-
- const Triangle &s=triangleptr[ b.face_index ];
- Face3 f3(vertexptr[ s.indices[0] ],vertexptr[ s.indices[1] ],vertexptr[ s.indices[2] ]);
-
-
- Vector3 res;
-
- if (f3.intersects_segment(p_begin,p_end,&res)) {
-
-
- float nd = n.dot(res);
- if (nd<d) {
-
- d=nd;
- r_point=res;
- r_normal=f3.get_plane().get_normal();
- inters=true;
- }
-
- }
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
-
- } else {
-
- stack[level]=(VISIT_LEFT_BIT<<VISITED_BIT_SHIFT)|node;
- }
- }
-
- } continue;
- case VISIT_LEFT_BIT: {
-
- stack[level]=(VISIT_RIGHT_BIT<<VISITED_BIT_SHIFT)|node;
- stack[level+1]=b.left|TEST_AABB_BIT;
- level++;
-
- } continue;
- case VISIT_RIGHT_BIT: {
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
- stack[level+1]=b.right|TEST_AABB_BIT;
- level++;
- } continue;
- case VISIT_DONE_BIT: {
-
- if (level==0) {
- done=true;
- break;
- } else
- level--;
-
- } continue;
- }
-
-
- if (done)
- break;
- }
-
-
- if (inters) {
-
- if (n.dot(r_normal)>0)
- r_normal=-r_normal;
- }
-
- return inters;
-}
-
-
-bool TriangleMesh::intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vector3 &r_point, Vector3 &r_normal) const {
-
-
- uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth);
-
- enum {
- TEST_AABB_BIT=0,
- VISIT_LEFT_BIT=1,
- VISIT_RIGHT_BIT=2,
- VISIT_DONE_BIT=3,
- VISITED_BIT_SHIFT=29,
- NODE_IDX_MASK=(1<<VISITED_BIT_SHIFT)-1,
- VISITED_BIT_MASK=~NODE_IDX_MASK,
-
-
- };
-
- Vector3 n = p_dir;
- real_t d=1e20;
- bool inters=false;
-
- //for(int i=0;i<max_depth;i++)
- // stack[i]=0;
-
- int level=0;
-
- DVector<Triangle>::Read trianglesr = triangles.read();
- DVector<Vector3>::Read verticesr=vertices.read();
- DVector<BVH>::Read bvhr=bvh.read();
-
- const Triangle *triangleptr=trianglesr.ptr();
- const Vector3 *vertexptr=verticesr.ptr();
- int pos=bvh.size()-1;
- const BVH *bvhptr = bvhr.ptr();
-
- stack[0]=pos;
- while(true) {
-
- uint32_t node = stack[level]&NODE_IDX_MASK;
- const BVH &b = bvhptr[ node ];
- bool done=false;
-
- switch(stack[level]>>VISITED_BIT_SHIFT) {
- case TEST_AABB_BIT: {
-
-
- bool valid = b.aabb.intersects_ray(p_begin,p_dir);
- if (!valid) {
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
-
- } else {
-
- if (b.face_index>=0) {
-
- const Triangle &s=triangleptr[ b.face_index ];
- Face3 f3(vertexptr[ s.indices[0] ],vertexptr[ s.indices[1] ],vertexptr[ s.indices[2] ]);
-
-
- Vector3 res;
-
- if (f3.intersects_ray(p_begin,p_dir,&res)) {
-
-
- float nd = n.dot(res);
- if (nd<d) {
-
- d=nd;
- r_point=res;
- r_normal=f3.get_plane().get_normal();
- inters=true;
- }
-
- }
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
-
- } else {
-
- stack[level]=(VISIT_LEFT_BIT<<VISITED_BIT_SHIFT)|node;
- }
- }
-
- } continue;
- case VISIT_LEFT_BIT: {
-
- stack[level]=(VISIT_RIGHT_BIT<<VISITED_BIT_SHIFT)|node;
- stack[level+1]=b.left|TEST_AABB_BIT;
- level++;
-
- } continue;
- case VISIT_RIGHT_BIT: {
-
- stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
- stack[level+1]=b.right|TEST_AABB_BIT;
- level++;
- } continue;
- case VISIT_DONE_BIT: {
-
- if (level==0) {
- done=true;
- break;
- } else
- level--;
-
- } continue;
- }
-
-
- if (done)
- break;
- }
-
-
- if (inters) {
-
- if (n.dot(r_normal)>0)
- r_normal=-r_normal;
- }
-
- return inters;
-}
-
-bool TriangleMesh::is_valid() const {
-
- return valid;
-}
-
-DVector<Face3> TriangleMesh::get_faces() const {
-
- if (!valid)
- return DVector<Face3>();
-
- DVector<Face3> faces;
- int ts = triangles.size();
- faces.resize(triangles.size());
-
- DVector<Face3>::Write w=faces.write();
- DVector<Triangle>::Read r = triangles.read();
- DVector<Vector3>::Read rv = vertices.read();
-
- for(int i=0;i<ts;i++) {
- for(int j=0;j<3;j++) {
- w[i].vertex[j]=rv[r[i].indices[j]];
- }
- }
-
- w = DVector<Face3>::Write();
- return faces;
-}
-
-TriangleMesh::TriangleMesh() {
-
- valid=false;
- max_depth=0;
-}
+#include "triangle_mesh.h"
+#include "sort.h"
+
+
+
+int TriangleMesh::_create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_depth,int&max_depth,int&max_alloc) {
+
+
+ if (p_depth>max_depth) {
+ max_depth=p_depth;
+ }
+
+ if (p_size==1) {
+
+
+ return p_bb[p_from]-p_bvh;
+ } else if (p_size==0) {
+
+ return -1;
+ }
+
+
+ AABB aabb;
+ aabb=p_bb[p_from]->aabb;
+ for(int i=1;i<p_size;i++) {
+
+ aabb.merge_with(p_bb[p_from+i]->aabb);
+ }
+
+ int li=aabb.get_longest_axis_index();
+
+ switch(li) {
+
+ case Vector3::AXIS_X: {
+ SortArray<BVH*,BVHCmpX> sort_x;
+ sort_x.nth_element(0,p_size,p_size/2,&p_bb[p_from]);
+ //sort_x.sort(&p_bb[p_from],p_size);
+ } break;
+ case Vector3::AXIS_Y: {
+ SortArray<BVH*,BVHCmpY> sort_y;
+ sort_y.nth_element(0,p_size,p_size/2,&p_bb[p_from]);
+ //sort_y.sort(&p_bb[p_from],p_size);
+ } break;
+ case Vector3::AXIS_Z: {
+ SortArray<BVH*,BVHCmpZ> sort_z;
+ sort_z.nth_element(0,p_size,p_size/2,&p_bb[p_from]);
+ //sort_z.sort(&p_bb[p_from],p_size);
+
+ } break;
+ }
+
+
+ int left = _create_bvh(p_bvh,p_bb,p_from,p_size/2,p_depth+1,max_depth,max_alloc);
+ int right = _create_bvh(p_bvh,p_bb,p_from+p_size/2,p_size-p_size/2,p_depth+1,max_depth,max_alloc);
+
+ int index=max_alloc++;
+ BVH *_new = &p_bvh[index];
+ _new->aabb=aabb;
+ _new->center=aabb.pos+aabb.size*0.5;
+ _new->face_index=-1;
+ _new->left=left;
+ _new->right=right;
+
+ return index;
+
+}
+
+
+void TriangleMesh::create(const DVector<Vector3>& p_faces) {
+
+ valid=false;
+
+ int fc=p_faces.size();
+ ERR_FAIL_COND(!fc || ((fc%3) != 0));
+ fc/=3;
+ triangles.resize(fc);
+
+ bvh.resize(fc*3); //will never be larger than this (todo make better)
+ DVector<BVH>::Write bw = bvh.write();
+
+ {
+
+ //create faces and indices and base bvh
+ //except for the Set for repeated triangles, everything
+ //goes in-place.
+
+ DVector<Vector3>::Read r = p_faces.read();
+ DVector<Triangle>::Write w = triangles.write();
+ Map<Vector3,int> db;
+
+ for(int i=0;i<fc;i++) {
+
+ Triangle&f=w[i];
+ const Vector3 *v=&r[i*3];
+
+ for(int j=0;j<3;j++) {
+
+ int vidx=-1;
+ Vector3 vs=v[j].snapped(0.0001);
+ Map<Vector3,int>::Element *E=db.find(vs);
+ if (E) {
+ vidx=E->get();
+ } else {
+ vidx=db.size();
+ db[vs]=vidx;
+ }
+
+ f.indices[j]=vidx;
+ if (j==0)
+ bw[i].aabb.pos=vs;
+ else
+ bw[i].aabb.expand_to(vs);
+ }
+
+ f.normal=Face3(r[i*3+0],r[i*3+1],r[i*3+2]).get_plane().get_normal();
+
+ bw[i].left=-1;
+ bw[i].right=-1;
+ bw[i].face_index=i;
+ bw[i].center=bw[i].aabb.pos+bw[i].aabb.size*0.5;
+ }
+
+ vertices.resize(db.size());
+ DVector<Vector3>::Write vw = vertices.write();
+ for (Map<Vector3,int>::Element *E=db.front();E;E=E->next()) {
+ vw[E->get()]=E->key();
+ }
+
+ }
+
+ DVector<BVH*> bwptrs;
+ bwptrs.resize(fc);
+ DVector<BVH*>::Write bwp = bwptrs.write();
+ for(int i=0;i<fc;i++) {
+
+ bwp[i]=&bw[i];
+ }
+
+ max_depth=0;
+ int max_alloc=fc;
+ int max=_create_bvh(bw.ptr(),bwp.ptr(),0,fc,1,max_depth,max_alloc);
+
+ bw=DVector<BVH>::Write(); //clearup
+ bvh.resize(max_alloc); //resize back
+
+ valid=true;
+
+}
+
+
+Vector3 TriangleMesh::get_area_normal(const AABB& p_aabb) const {
+
+ uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth);
+
+ enum {
+ TEST_AABB_BIT=0,
+ VISIT_LEFT_BIT=1,
+ VISIT_RIGHT_BIT=2,
+ VISIT_DONE_BIT=3,
+ VISITED_BIT_SHIFT=29,
+ NODE_IDX_MASK=(1<<VISITED_BIT_SHIFT)-1,
+ VISITED_BIT_MASK=~NODE_IDX_MASK,
+
+
+ };
+
+ int n_count=0;
+ Vector3 n;
+
+ //for(int i=0;i<max_depth;i++)
+ // stack[i]=0;
+
+ int level=0;
+
+ DVector<Triangle>::Read trianglesr = triangles.read();
+ DVector<Vector3>::Read verticesr=vertices.read();
+ DVector<BVH>::Read bvhr=bvh.read();
+
+ const Triangle *triangleptr=trianglesr.ptr();
+ const Vector3 *vertexptr=verticesr.ptr();
+ int pos=bvh.size()-1;
+ const BVH *bvhptr = bvhr.ptr();
+
+ stack[0]=pos;
+ while(true) {
+
+ uint32_t node = stack[level]&NODE_IDX_MASK;
+ const BVH &b = bvhptr[ node ];
+ bool done=false;
+
+ switch(stack[level]>>VISITED_BIT_SHIFT) {
+ case TEST_AABB_BIT: {
+
+
+ bool valid = b.aabb.intersects(p_aabb);
+ if (!valid) {
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+
+ } else {
+
+ if (b.face_index>=0) {
+
+ const Triangle &s=triangleptr[ b.face_index ];
+ n+=s.normal;
+ n_count++;
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+
+ } else {
+
+ stack[level]=(VISIT_LEFT_BIT<<VISITED_BIT_SHIFT)|node;
+ }
+ }
+
+ } continue;
+ case VISIT_LEFT_BIT: {
+
+ stack[level]=(VISIT_RIGHT_BIT<<VISITED_BIT_SHIFT)|node;
+ stack[level+1]=b.left|TEST_AABB_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+ stack[level+1]=b.right|TEST_AABB_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+ if (n_count>0)
+ n/=n_count;
+
+ return n;
+
+}
+
+
+bool TriangleMesh::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const {
+
+
+ uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth);
+
+ enum {
+ TEST_AABB_BIT=0,
+ VISIT_LEFT_BIT=1,
+ VISIT_RIGHT_BIT=2,
+ VISIT_DONE_BIT=3,
+ VISITED_BIT_SHIFT=29,
+ NODE_IDX_MASK=(1<<VISITED_BIT_SHIFT)-1,
+ VISITED_BIT_MASK=~NODE_IDX_MASK,
+
+
+ };
+
+ Vector3 n = (p_end-p_begin).normalized();
+ real_t d=1e10;
+ bool inters=false;
+
+ //for(int i=0;i<max_depth;i++)
+ // stack[i]=0;
+
+ int level=0;
+ //AABB ray_aabb;
+ //ray_aabb.pos=p_begin;
+ //ray_aabb.expand_to(p_end);
+
+
+ DVector<Triangle>::Read trianglesr = triangles.read();
+ DVector<Vector3>::Read verticesr=vertices.read();
+ DVector<BVH>::Read bvhr=bvh.read();
+
+ const Triangle *triangleptr=trianglesr.ptr();
+ const Vector3 *vertexptr=verticesr.ptr();
+ int pos=bvh.size()-1;
+ const BVH *bvhptr = bvhr.ptr();
+
+ stack[0]=pos;
+ while(true) {
+
+ uint32_t node = stack[level]&NODE_IDX_MASK;
+ const BVH &b = bvhptr[ node ];
+ bool done=false;
+
+ switch(stack[level]>>VISITED_BIT_SHIFT) {
+ case TEST_AABB_BIT: {
+
+
+ bool valid = b.aabb.intersects_segment(p_begin,p_end);
+// bool valid = b.aabb.intersects(ray_aabb);
+
+ if (!valid) {
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+
+ } else {
+
+ if (b.face_index>=0) {
+
+ const Triangle &s=triangleptr[ b.face_index ];
+ Face3 f3(vertexptr[ s.indices[0] ],vertexptr[ s.indices[1] ],vertexptr[ s.indices[2] ]);
+
+
+ Vector3 res;
+
+ if (f3.intersects_segment(p_begin,p_end,&res)) {
+
+
+ float nd = n.dot(res);
+ if (nd<d) {
+
+ d=nd;
+ r_point=res;
+ r_normal=f3.get_plane().get_normal();
+ inters=true;
+ }
+
+ }
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+
+ } else {
+
+ stack[level]=(VISIT_LEFT_BIT<<VISITED_BIT_SHIFT)|node;
+ }
+ }
+
+ } continue;
+ case VISIT_LEFT_BIT: {
+
+ stack[level]=(VISIT_RIGHT_BIT<<VISITED_BIT_SHIFT)|node;
+ stack[level+1]=b.left|TEST_AABB_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+ stack[level+1]=b.right|TEST_AABB_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+ if (inters) {
+
+ if (n.dot(r_normal)>0)
+ r_normal=-r_normal;
+ }
+
+ return inters;
+}
+
+
+bool TriangleMesh::intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vector3 &r_point, Vector3 &r_normal) const {
+
+
+ uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth);
+
+ enum {
+ TEST_AABB_BIT=0,
+ VISIT_LEFT_BIT=1,
+ VISIT_RIGHT_BIT=2,
+ VISIT_DONE_BIT=3,
+ VISITED_BIT_SHIFT=29,
+ NODE_IDX_MASK=(1<<VISITED_BIT_SHIFT)-1,
+ VISITED_BIT_MASK=~NODE_IDX_MASK,
+
+
+ };
+
+ Vector3 n = p_dir;
+ real_t d=1e20;
+ bool inters=false;
+
+ //for(int i=0;i<max_depth;i++)
+ // stack[i]=0;
+
+ int level=0;
+
+ DVector<Triangle>::Read trianglesr = triangles.read();
+ DVector<Vector3>::Read verticesr=vertices.read();
+ DVector<BVH>::Read bvhr=bvh.read();
+
+ const Triangle *triangleptr=trianglesr.ptr();
+ const Vector3 *vertexptr=verticesr.ptr();
+ int pos=bvh.size()-1;
+ const BVH *bvhptr = bvhr.ptr();
+
+ stack[0]=pos;
+ while(true) {
+
+ uint32_t node = stack[level]&NODE_IDX_MASK;
+ const BVH &b = bvhptr[ node ];
+ bool done=false;
+
+ switch(stack[level]>>VISITED_BIT_SHIFT) {
+ case TEST_AABB_BIT: {
+
+
+ bool valid = b.aabb.intersects_ray(p_begin,p_dir);
+ if (!valid) {
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+
+ } else {
+
+ if (b.face_index>=0) {
+
+ const Triangle &s=triangleptr[ b.face_index ];
+ Face3 f3(vertexptr[ s.indices[0] ],vertexptr[ s.indices[1] ],vertexptr[ s.indices[2] ]);
+
+
+ Vector3 res;
+
+ if (f3.intersects_ray(p_begin,p_dir,&res)) {
+
+
+ float nd = n.dot(res);
+ if (nd<d) {
+
+ d=nd;
+ r_point=res;
+ r_normal=f3.get_plane().get_normal();
+ inters=true;
+ }
+
+ }
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+
+ } else {
+
+ stack[level]=(VISIT_LEFT_BIT<<VISITED_BIT_SHIFT)|node;
+ }
+ }
+
+ } continue;
+ case VISIT_LEFT_BIT: {
+
+ stack[level]=(VISIT_RIGHT_BIT<<VISITED_BIT_SHIFT)|node;
+ stack[level+1]=b.left|TEST_AABB_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=(VISIT_DONE_BIT<<VISITED_BIT_SHIFT)|node;
+ stack[level+1]=b.right|TEST_AABB_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+ if (inters) {
+
+ if (n.dot(r_normal)>0)
+ r_normal=-r_normal;
+ }
+
+ return inters;
+}
+
+bool TriangleMesh::is_valid() const {
+
+ return valid;
+}
+
+DVector<Face3> TriangleMesh::get_faces() const {
+
+ if (!valid)
+ return DVector<Face3>();
+
+ DVector<Face3> faces;
+ int ts = triangles.size();
+ faces.resize(triangles.size());
+
+ DVector<Face3>::Write w=faces.write();
+ DVector<Triangle>::Read r = triangles.read();
+ DVector<Vector3>::Read rv = vertices.read();
+
+ for(int i=0;i<ts;i++) {
+ for(int j=0;j<3;j++) {
+ w[i].vertex[j]=rv[r[i].indices[j]];
+ }
+ }
+
+ w = DVector<Face3>::Write();
+ return faces;
+}
+
+TriangleMesh::TriangleMesh() {
+
+ valid=false;
+ max_depth=0;
+}
diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h
index ab0cb713b1..87d8ce8e6c 100644
--- a/core/math/triangle_mesh.h
+++ b/core/math/triangle_mesh.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,74 +26,74 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TRIANGLE_MESH_H
-#define TRIANGLE_MESH_H
-
-#include "reference.h"
-#include "face3.h"
-class TriangleMesh : public Reference {
-
- OBJ_TYPE( TriangleMesh, Reference);
-
- struct Triangle {
-
- Vector3 normal;
- int indices[3];
- };
-
- DVector<Triangle> triangles;
- DVector<Vector3> vertices;
-
- struct BVH {
-
- AABB aabb;
- Vector3 center; //used for sorting
- int left;
- int right;
-
- int face_index;
- };
-
- struct BVHCmpX {
-
- bool operator()(const BVH* p_left, const BVH* p_right) const {
-
- return p_left->center.x < p_right->center.x;
- }
- };
-
- struct BVHCmpY {
-
- bool operator()(const BVH* p_left, const BVH* p_right) const {
-
- return p_left->center.y < p_right->center.y;
- }
- };
- struct BVHCmpZ {
-
- bool operator()(const BVH* p_left, const BVH* p_right) const {
-
- return p_left->center.z < p_right->center.z;
- }
- };
-
- int _create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_depth,int&max_depth,int&max_alloc);
-
- DVector<BVH> bvh;
- int max_depth;
- bool valid;
-
-public:
-
- bool is_valid() const;
- bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const;
- bool intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vector3 &r_point, Vector3 &r_normal) const;
- Vector3 get_area_normal(const AABB& p_aabb) const;
- DVector<Face3> get_faces() const;
-
-
- void create(const DVector<Vector3>& p_faces);
- TriangleMesh();
-};
-
-#endif // TRIANGLE_MESH_H
+#ifndef TRIANGLE_MESH_H
+#define TRIANGLE_MESH_H
+
+#include "reference.h"
+#include "face3.h"
+class TriangleMesh : public Reference {
+
+ OBJ_TYPE( TriangleMesh, Reference);
+
+ struct Triangle {
+
+ Vector3 normal;
+ int indices[3];
+ };
+
+ DVector<Triangle> triangles;
+ DVector<Vector3> vertices;
+
+ struct BVH {
+
+ AABB aabb;
+ Vector3 center; //used for sorting
+ int left;
+ int right;
+
+ int face_index;
+ };
+
+ struct BVHCmpX {
+
+ bool operator()(const BVH* p_left, const BVH* p_right) const {
+
+ return p_left->center.x < p_right->center.x;
+ }
+ };
+
+ struct BVHCmpY {
+
+ bool operator()(const BVH* p_left, const BVH* p_right) const {
+
+ return p_left->center.y < p_right->center.y;
+ }
+ };
+ struct BVHCmpZ {
+
+ bool operator()(const BVH* p_left, const BVH* p_right) const {
+
+ return p_left->center.z < p_right->center.z;
+ }
+ };
+
+ int _create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_depth,int&max_depth,int&max_alloc);
+
+ DVector<BVH> bvh;
+ int max_depth;
+ bool valid;
+
+public:
+
+ bool is_valid() const;
+ bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const;
+ bool intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vector3 &r_point, Vector3 &r_normal) const;
+ Vector3 get_area_normal(const AABB& p_aabb) const;
+ DVector<Face3> get_faces() const;
+
+
+ void create(const DVector<Vector3>& p_faces);
+ TriangleMesh();
+};
+
+#endif // TRIANGLE_MESH_H
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 4a870def4b..b13e13c47d 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangulate.h b/core/math/triangulate.h
index b20b37bd44..927b7efb8d 100644
--- a/core/math/triangulate.h
+++ b/core/math/triangulate.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/math/triangulator.cpp b/core/math/triangulator.cpp
new file mode 100644
index 0000000000..8f82d76823
--- /dev/null
+++ b/core/math/triangulator.cpp
@@ -0,0 +1,1550 @@
+//Copyright (C) 2011 by Ivan Fratric
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+//of this software and associated documentation files (the "Software"), to deal
+//in the Software without restriction, including without limitation the rights
+//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//copies of the Software, and to permit persons to whom the Software is
+//furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included in
+//all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//THE SOFTWARE.
+
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "triangulator.h"
+
+
+#define TRIANGULATOR_VERTEXTYPE_REGULAR 0
+#define TRIANGULATOR_VERTEXTYPE_START 1
+#define TRIANGULATOR_VERTEXTYPE_END 2
+#define TRIANGULATOR_VERTEXTYPE_SPLIT 3
+#define TRIANGULATOR_VERTEXTYPE_MERGE 4
+
+TriangulatorPoly::TriangulatorPoly() {
+ hole = false;
+ numpoints = 0;
+ points = NULL;
+}
+
+TriangulatorPoly::~TriangulatorPoly() {
+ if(points) delete [] points;
+}
+
+void TriangulatorPoly::Clear() {
+ if(points) delete [] points;
+ hole = false;
+ numpoints = 0;
+ points = NULL;
+}
+
+void TriangulatorPoly::Init(long numpoints) {
+ Clear();
+ this->numpoints = numpoints;
+ points = new Vector2[numpoints];
+}
+
+void TriangulatorPoly::Triangle(Vector2 &p1, Vector2 &p2, Vector2 &p3) {
+ Init(3);
+ points[0] = p1;
+ points[1] = p2;
+ points[2] = p3;
+}
+
+TriangulatorPoly::TriangulatorPoly(const TriangulatorPoly &src) {
+ hole = src.hole;
+ numpoints = src.numpoints;
+ points = new Vector2[numpoints];
+ memcpy(points, src.points, numpoints*sizeof(Vector2));
+}
+
+TriangulatorPoly& TriangulatorPoly::operator=(const TriangulatorPoly &src) {
+ Clear();
+ hole = src.hole;
+ numpoints = src.numpoints;
+ points = new Vector2[numpoints];
+ memcpy(points, src.points, numpoints*sizeof(Vector2));
+ return *this;
+}
+
+int TriangulatorPoly::GetOrientation() {
+ long i1,i2;
+ real_t area = 0;
+ for(i1=0; i1<numpoints; i1++) {
+ i2 = i1+1;
+ if(i2 == numpoints) i2 = 0;
+ area += points[i1].x * points[i2].y - points[i1].y * points[i2].x;
+ }
+ if(area>0) return TRIANGULATOR_CCW;
+ if(area<0) return TRIANGULATOR_CW;
+ return 0;
+}
+
+void TriangulatorPoly::SetOrientation(int orientation) {
+ int polyorientation = GetOrientation();
+ if(polyorientation&&(polyorientation!=orientation)) {
+ Invert();
+ }
+}
+
+void TriangulatorPoly::Invert() {
+ long i;
+ Vector2 *invpoints;
+
+ invpoints = new Vector2[numpoints];
+ for(i=0;i<numpoints;i++) {
+ invpoints[i] = points[numpoints-i-1];
+ }
+
+ delete [] points;
+ points = invpoints;
+}
+
+Vector2 TriangulatorPartition::Normalize(const Vector2 &p) {
+ Vector2 r;
+ real_t n = sqrt(p.x*p.x + p.y*p.y);
+ if(n!=0) {
+ r = p/n;
+ } else {
+ r.x = 0;
+ r.y = 0;
+ }
+ return r;
+}
+
+real_t TriangulatorPartition::Distance(const Vector2 &p1, const Vector2 &p2) {
+ real_t dx,dy;
+ dx = p2.x - p1.x;
+ dy = p2.y - p1.y;
+ return(sqrt(dx*dx + dy*dy));
+}
+
+//checks if two lines intersect
+int TriangulatorPartition::Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21, Vector2 &p22) {
+ if((p11.x == p21.x)&&(p11.y == p21.y)) return 0;
+ if((p11.x == p22.x)&&(p11.y == p22.y)) return 0;
+ if((p12.x == p21.x)&&(p12.y == p21.y)) return 0;
+ if((p12.x == p22.x)&&(p12.y == p22.y)) return 0;
+
+ Vector2 v1ort,v2ort,v;
+ real_t dot11,dot12,dot21,dot22;
+
+ v1ort.x = p12.y-p11.y;
+ v1ort.y = p11.x-p12.x;
+
+ v2ort.x = p22.y-p21.y;
+ v2ort.y = p21.x-p22.x;
+
+ v = p21-p11;
+ dot21 = v.x*v1ort.x + v.y*v1ort.y;
+ v = p22-p11;
+ dot22 = v.x*v1ort.x + v.y*v1ort.y;
+
+ v = p11-p21;
+ dot11 = v.x*v2ort.x + v.y*v2ort.y;
+ v = p12-p21;
+ dot12 = v.x*v2ort.x + v.y*v2ort.y;
+
+ if(dot11*dot12>0) return 0;
+ if(dot21*dot22>0) return 0;
+
+ return 1;
+}
+
+//removes holes from inpolys by merging them with non-holes
+int TriangulatorPartition::RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys) {
+ List<TriangulatorPoly> polys;
+ List<TriangulatorPoly>::Element *holeiter,*polyiter,*iter,*iter2;
+ long i,i2,holepointindex,polypointindex;
+ Vector2 holepoint,polypoint,bestpolypoint;
+ Vector2 linep1,linep2;
+ Vector2 v1,v2;
+ TriangulatorPoly newpoly;
+ bool hasholes;
+ bool pointvisible;
+ bool pointfound;
+
+ //check for trivial case (no holes)
+ hasholes = false;
+ for(iter = inpolys->front(); iter; iter=iter->next()) {
+ if(iter->get().IsHole()) {
+ hasholes = true;
+ break;
+ }
+ }
+ if(!hasholes) {
+ for(iter = inpolys->front(); iter; iter=iter->next()) {
+ outpolys->push_back(iter->get());
+ }
+ return 1;
+ }
+
+ polys = *inpolys;
+
+ while(1) {
+ //find the hole point with the largest x
+ hasholes = false;
+ for(iter = polys.front(); iter; iter=iter->next()) {
+ if(!iter->get().IsHole()) continue;
+
+ if(!hasholes) {
+ hasholes = true;
+ holeiter = iter;
+ holepointindex = 0;
+ }
+
+ for(i=0; i < iter->get().GetNumPoints(); i++) {
+ if(iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) {
+ holeiter = iter;
+ holepointindex = i;
+ }
+ }
+ }
+ if(!hasholes) break;
+ holepoint = holeiter->get().GetPoint(holepointindex);
+
+ pointfound = false;
+ for(iter = polys.front(); iter; iter=iter->next()) {
+ if(iter->get().IsHole()) continue;
+ for(i=0; i < iter->get().GetNumPoints(); i++) {
+ if(iter->get().GetPoint(i).x <= holepoint.x) continue;
+ if(!InCone(iter->get().GetPoint((i+iter->get().GetNumPoints()-1)%(iter->get().GetNumPoints())),
+ iter->get().GetPoint(i),
+ iter->get().GetPoint((i+1)%(iter->get().GetNumPoints())),
+ holepoint))
+ continue;
+ polypoint = iter->get().GetPoint(i);
+ if(pointfound) {
+ v1 = Normalize(polypoint-holepoint);
+ v2 = Normalize(bestpolypoint-holepoint);
+ if(v2.x > v1.x) continue;
+ }
+ pointvisible = true;
+ for(iter2 = polys.front(); iter2; iter2=iter2->next()) {
+ if(iter2->get().IsHole()) continue;
+ for(i2=0; i2 < iter2->get().GetNumPoints(); i2++) {
+ linep1 = iter2->get().GetPoint(i2);
+ linep2 = iter2->get().GetPoint((i2+1)%(iter2->get().GetNumPoints()));
+ if(Intersects(holepoint,polypoint,linep1,linep2)) {
+ pointvisible = false;
+ break;
+ }
+ }
+ if(!pointvisible) break;
+ }
+ if(pointvisible) {
+ pointfound = true;
+ bestpolypoint = polypoint;
+ polyiter = iter;
+ polypointindex = i;
+ }
+ }
+ }
+
+ if(!pointfound) return 0;
+
+ newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2);
+ i2 = 0;
+ for(i=0;i<=polypointindex;i++) {
+ newpoly[i2] = polyiter->get().GetPoint(i);
+ i2++;
+ }
+ for(i=0;i<=holeiter->get().GetNumPoints();i++) {
+ newpoly[i2] = holeiter->get().GetPoint((i+holepointindex)%holeiter->get().GetNumPoints());
+ i2++;
+ }
+ for(i=polypointindex;i<polyiter->get().GetNumPoints();i++) {
+ newpoly[i2] = polyiter->get().GetPoint(i);
+ i2++;
+ }
+
+ polys.erase(holeiter);
+ polys.erase(polyiter);
+ polys.push_back(newpoly);
+ }
+
+ for(iter = polys.front(); iter; iter=iter->next()) {
+ outpolys->push_back(iter->get());
+ }
+
+ return 1;
+}
+
+bool TriangulatorPartition::IsConvex(Vector2& p1, Vector2& p2, Vector2& p3) {
+ real_t tmp;
+ tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
+ if(tmp>0) return 1;
+ else return 0;
+}
+
+bool TriangulatorPartition::IsReflex(Vector2& p1, Vector2& p2, Vector2& p3) {
+ real_t tmp;
+ tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
+ if(tmp<0) return 1;
+ else return 0;
+}
+
+bool TriangulatorPartition::IsInside(Vector2& p1, Vector2& p2, Vector2& p3, Vector2 &p) {
+ if(IsConvex(p1,p,p2)) return false;
+ if(IsConvex(p2,p,p3)) return false;
+ if(IsConvex(p3,p,p1)) return false;
+ return true;
+}
+
+bool TriangulatorPartition::InCone(Vector2 &p1, Vector2 &p2, Vector2 &p3, Vector2 &p) {
+ bool convex;
+
+ convex = IsConvex(p1,p2,p3);
+
+ if(convex) {
+ if(!IsConvex(p1,p2,p)) return false;
+ if(!IsConvex(p2,p3,p)) return false;
+ return true;
+ } else {
+ if(IsConvex(p1,p2,p)) return true;
+ if(IsConvex(p2,p3,p)) return true;
+ return false;
+ }
+}
+
+bool TriangulatorPartition::InCone(PartitionVertex *v, Vector2 &p) {
+ Vector2 p1,p2,p3;
+
+ p1 = v->previous->p;
+ p2 = v->p;
+ p3 = v->next->p;
+
+ return InCone(p1,p2,p3,p);
+}
+
+void TriangulatorPartition::UpdateVertexReflexity(PartitionVertex *v) {
+ PartitionVertex *v1,*v3;
+ v1 = v->previous;
+ v3 = v->next;
+ v->isConvex = !IsReflex(v1->p,v->p,v3->p);
+}
+
+void TriangulatorPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) {
+ long i;
+ PartitionVertex *v1,*v3;
+ Vector2 vec1,vec3;
+
+ v1 = v->previous;
+ v3 = v->next;
+
+ v->isConvex = IsConvex(v1->p,v->p,v3->p);
+
+ vec1 = Normalize(v1->p - v->p);
+ vec3 = Normalize(v3->p - v->p);
+ v->angle = vec1.x*vec3.x + vec1.y*vec3.y;
+
+ if(v->isConvex) {
+ v->isEar = true;
+ for(i=0;i<numvertices;i++) {
+ if((vertices[i].p.x==v->p.x)&&(vertices[i].p.y==v->p.y)) continue;
+ if((vertices[i].p.x==v1->p.x)&&(vertices[i].p.y==v1->p.y)) continue;
+ if((vertices[i].p.x==v3->p.x)&&(vertices[i].p.y==v3->p.y)) continue;
+ if(IsInside(v1->p,v->p,v3->p,vertices[i].p)) {
+ v->isEar = false;
+ break;
+ }
+ }
+ } else {
+ v->isEar = false;
+ }
+}
+
+//triangulation by ear removal
+int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
+ long numvertices;
+ PartitionVertex *vertices;
+ PartitionVertex *ear;
+ TriangulatorPoly triangle;
+ long i,j;
+ bool earfound;
+
+ if(poly->GetNumPoints() < 3) return 0;
+ if(poly->GetNumPoints() == 3) {
+ triangles->push_back(*poly);
+ return 1;
+ }
+
+ numvertices = poly->GetNumPoints();
+
+ vertices = new PartitionVertex[numvertices];
+ for(i=0;i<numvertices;i++) {
+ vertices[i].isActive = true;
+ vertices[i].p = poly->GetPoint(i);
+ if(i==(numvertices-1)) vertices[i].next=&(vertices[0]);
+ else vertices[i].next=&(vertices[i+1]);
+ if(i==0) vertices[i].previous = &(vertices[numvertices-1]);
+ else vertices[i].previous = &(vertices[i-1]);
+ }
+ for(i=0;i<numvertices;i++) {
+ UpdateVertex(&vertices[i],vertices,numvertices);
+ }
+
+ for(i=0;i<numvertices-3;i++) {
+ earfound = false;
+ //find the most extruded ear
+ for(j=0;j<numvertices;j++) {
+ if(!vertices[j].isActive) continue;
+ if(!vertices[j].isEar) continue;
+ if(!earfound) {
+ earfound = true;
+ ear = &(vertices[j]);
+ } else {
+ if(vertices[j].angle > ear->angle) {
+ ear = &(vertices[j]);
+ }
+ }
+ }
+ if(!earfound) {
+ delete [] vertices;
+ return 0;
+ }
+
+ triangle.Triangle(ear->previous->p,ear->p,ear->next->p);
+ triangles->push_back(triangle);
+
+ ear->isActive = false;
+ ear->previous->next = ear->next;
+ ear->next->previous = ear->previous;
+
+ if(i==numvertices-4) break;
+
+ UpdateVertex(ear->previous,vertices,numvertices);
+ UpdateVertex(ear->next,vertices,numvertices);
+ }
+ for(i=0;i<numvertices;i++) {
+ if(vertices[i].isActive) {
+ triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p);
+ triangles->push_back(triangle);
+ break;
+ }
+ }
+
+ delete [] vertices;
+
+ return 1;
+}
+
+int TriangulatorPartition::Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
+ List<TriangulatorPoly> outpolys;
+ List<TriangulatorPoly>::Element*iter;
+
+ if(!RemoveHoles(inpolys,&outpolys)) return 0;
+ for(iter=outpolys.front();iter;iter=iter->next()) {
+ if(!Triangulate_EC(&(iter->get()),triangles)) return 0;
+ }
+ return 1;
+}
+
+int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
+ List<TriangulatorPoly> triangles;
+ List<TriangulatorPoly>::Element *iter1,*iter2;
+ TriangulatorPoly *poly1,*poly2;
+ TriangulatorPoly newpoly;
+ Vector2 d1,d2,p1,p2,p3;
+ long i11,i12,i21,i22,i13,i23,j,k;
+ bool isdiagonal;
+ long numreflex;
+
+ //check if the poly is already convex
+ numreflex = 0;
+ for(i11=0;i11<poly->GetNumPoints();i11++) {
+ if(i11==0) i12 = poly->GetNumPoints()-1;
+ else i12=i11-1;
+ if(i11==(poly->GetNumPoints()-1)) i13=0;
+ else i13=i11+1;
+ if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) {
+ numreflex = 1;
+ break;
+ }
+ }
+ if(numreflex == 0) {
+ parts->push_back(*poly);
+ return 1;
+ }
+
+ if(!Triangulate_EC(poly,&triangles)) return 0;
+
+ for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
+ poly1 = &(iter1->get());
+ for(i11=0;i11<poly1->GetNumPoints();i11++) {
+ d1 = poly1->GetPoint(i11);
+ i12 = (i11+1)%(poly1->GetNumPoints());
+ d2 = poly1->GetPoint(i12);
+
+ isdiagonal = false;
+ for(iter2 = iter1; iter2 ; iter2=iter2->next()) {
+ if(iter1 == iter2) continue;
+ poly2 = &(iter2->get());
+
+ for(i21=0;i21<poly2->GetNumPoints();i21++) {
+ if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue;
+ i22 = (i21+1)%(poly2->GetNumPoints());
+ if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue;
+ isdiagonal = true;
+ break;
+ }
+ if(isdiagonal) break;
+ }
+
+ if(!isdiagonal) continue;
+
+ p2 = poly1->GetPoint(i11);
+ if(i11 == 0) i13 = poly1->GetNumPoints()-1;
+ else i13 = i11-1;
+ p1 = poly1->GetPoint(i13);
+ if(i22 == (poly2->GetNumPoints()-1)) i23 = 0;
+ else i23 = i22+1;
+ p3 = poly2->GetPoint(i23);
+
+ if(!IsConvex(p1,p2,p3)) continue;
+
+ p2 = poly1->GetPoint(i12);
+ if(i12 == (poly1->GetNumPoints()-1)) i13 = 0;
+ else i13 = i12+1;
+ p3 = poly1->GetPoint(i13);
+ if(i21 == 0) i23 = poly2->GetNumPoints()-1;
+ else i23 = i21-1;
+ p1 = poly2->GetPoint(i23);
+
+ if(!IsConvex(p1,p2,p3)) continue;
+
+ newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2);
+ k = 0;
+ for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) {
+ newpoly[k] = poly1->GetPoint(j);
+ k++;
+ }
+ for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) {
+ newpoly[k] = poly2->GetPoint(j);
+ k++;
+ }
+
+ triangles.erase(iter2);
+ iter1->get() = newpoly;
+ poly1 = &(iter1->get());
+ i11 = -1;
+
+ continue;
+ }
+ }
+
+ for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
+ parts->push_back(iter1->get());
+ }
+
+ return 1;
+}
+
+int TriangulatorPartition::ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts) {
+ List<TriangulatorPoly> outpolys;
+ List<TriangulatorPoly>::Element* iter;
+
+ if(!RemoveHoles(inpolys,&outpolys)) return 0;
+ for(iter=outpolys.front();iter;iter=iter->next()) {
+ if(!ConvexPartition_HM(&(iter->get()),parts)) return 0;
+ }
+ return 1;
+}
+
+//minimum-weight polygon triangulation by dynamic programming
+//O(n^3) time complexity
+//O(n^2) space complexity
+int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
+ long i,j,k,gap,n;
+ DPState **dpstates;
+ Vector2 p1,p2,p3,p4;
+ long bestvertex;
+ real_t weight,minweight,d1,d2;
+ Diagonal diagonal,newdiagonal;
+ List<Diagonal> diagonals;
+ TriangulatorPoly triangle;
+ int ret = 1;
+
+ n = poly->GetNumPoints();
+ dpstates = new DPState *[n];
+ for(i=1;i<n;i++) {
+ dpstates[i] = new DPState[i];
+ }
+
+ //init states and visibility
+ for(i=0;i<(n-1);i++) {
+ p1 = poly->GetPoint(i);
+ for(j=i+1;j<n;j++) {
+ dpstates[j][i].visible = true;
+ dpstates[j][i].weight = 0;
+ dpstates[j][i].bestvertex = -1;
+ if(j!=(i+1)) {
+ p2 = poly->GetPoint(j);
+
+ //visibility check
+ if(i==0) p3 = poly->GetPoint(n-1);
+ else p3 = poly->GetPoint(i-1);
+ if(i==(n-1)) p4 = poly->GetPoint(0);
+ else p4 = poly->GetPoint(i+1);
+ if(!InCone(p3,p1,p4,p2)) {
+ dpstates[j][i].visible = false;
+ continue;
+ }
+
+ if(j==0) p3 = poly->GetPoint(n-1);
+ else p3 = poly->GetPoint(j-1);
+ if(j==(n-1)) p4 = poly->GetPoint(0);
+ else p4 = poly->GetPoint(j+1);
+ if(!InCone(p3,p2,p4,p1)) {
+ dpstates[j][i].visible = false;
+ continue;
+ }
+
+ for(k=0;k<n;k++) {
+ p3 = poly->GetPoint(k);
+ if(k==(n-1)) p4 = poly->GetPoint(0);
+ else p4 = poly->GetPoint(k+1);
+ if(Intersects(p1,p2,p3,p4)) {
+ dpstates[j][i].visible = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ dpstates[n-1][0].visible = true;
+ dpstates[n-1][0].weight = 0;
+ dpstates[n-1][0].bestvertex = -1;
+
+ for(gap = 2; gap<n; gap++) {
+ for(i=0; i<(n-gap); i++) {
+ j = i+gap;
+ if(!dpstates[j][i].visible) continue;
+ bestvertex = -1;
+ for(k=(i+1);k<j;k++) {
+ if(!dpstates[k][i].visible) continue;
+ if(!dpstates[j][k].visible) continue;
+
+ if(k<=(i+1)) d1=0;
+ else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k));
+ if(j<=(k+1)) d2=0;
+ else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j));
+
+ weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2;
+
+ if((bestvertex == -1)||(weight<minweight)) {
+ bestvertex = k;
+ minweight = weight;
+ }
+ }
+ if(bestvertex == -1) {
+ for(i=1;i<n;i++) {
+ delete [] dpstates[i];
+ }
+ delete [] dpstates;
+
+ return 0;
+ }
+
+ dpstates[j][i].bestvertex = bestvertex;
+ dpstates[j][i].weight = minweight;
+ }
+ }
+
+ newdiagonal.index1 = 0;
+ newdiagonal.index2 = n-1;
+ diagonals.push_back(newdiagonal);
+ while(!diagonals.empty()) {
+ diagonal = (diagonals.front()->get());
+ diagonals.pop_front();
+ bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
+ if(bestvertex == -1) {
+ ret = 0;
+ break;
+ }
+ triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2));
+ triangles->push_back(triangle);
+ if(bestvertex > (diagonal.index1+1)) {
+ newdiagonal.index1 = diagonal.index1;
+ newdiagonal.index2 = bestvertex;
+ diagonals.push_back(newdiagonal);
+ }
+ if(diagonal.index2 > (bestvertex+1)) {
+ newdiagonal.index1 = bestvertex;
+ newdiagonal.index2 = diagonal.index2;
+ diagonals.push_back(newdiagonal);
+ }
+ }
+
+ for(i=1;i<n;i++) {
+ delete [] dpstates[i];
+ }
+ delete [] dpstates;
+
+ return ret;
+}
+
+void TriangulatorPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
+ Diagonal newdiagonal;
+ List<Diagonal> *pairs;
+ long w2;
+
+ w2 = dpstates[a][b].weight;
+ if(w>w2) return;
+
+ pairs = &(dpstates[a][b].pairs);
+ newdiagonal.index1 = i;
+ newdiagonal.index2 = j;
+
+ if(w<w2) {
+ pairs->clear();
+ pairs->push_front(newdiagonal);
+ dpstates[a][b].weight = w;
+ } else {
+ if((!pairs->empty())&&(i <= pairs->front()->get().index1)) return;
+ while((!pairs->empty())&&(pairs->front()->get().index2 >= j)) pairs->pop_front();
+ pairs->push_front(newdiagonal);
+ }
+}
+
+void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
+ List<Diagonal> *pairs;
+ List<Diagonal>::Element *iter,*lastiter;
+ long top;
+ long w;
+
+ if(!dpstates[i][j].visible) return;
+ top = j;
+ w = dpstates[i][j].weight;
+ if(k-j > 1) {
+ if (!dpstates[j][k].visible) return;
+ w += dpstates[j][k].weight + 1;
+ }
+ if(j-i > 1) {
+ pairs = &(dpstates[i][j].pairs);
+ iter = NULL;
+ lastiter = NULL;
+ while(iter!=pairs->front()) {
+ if (!iter)
+ iter=pairs->back();
+ else
+ iter=iter->prev();
+
+ if(!IsReflex(vertices[iter->get().index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
+ else break;
+ }
+ if(lastiter == NULL) w++;
+ else {
+ if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->get().index1].p)) w++;
+ else top = lastiter->get().index1;
+ }
+ }
+ UpdateState(i,k,w,top,j,dpstates);
+}
+
+void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
+ List<Diagonal> *pairs;
+ List<Diagonal>::Element* iter,*lastiter;
+ long top;
+ long w;
+
+ if(!dpstates[j][k].visible) return;
+ top = j;
+ w = dpstates[j][k].weight;
+
+ if (j-i > 1) {
+ if (!dpstates[i][j].visible) return;
+ w += dpstates[i][j].weight + 1;
+ }
+ if (k-j > 1) {
+ pairs = &(dpstates[j][k].pairs);
+
+ iter = pairs->front();
+ if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p))) {
+ lastiter = iter;
+ while(iter!=NULL) {
+ if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p)) {
+ lastiter = iter;
+ iter=iter->next();
+ }
+ else break;
+ }
+ if(IsReflex(vertices[lastiter->get().index2].p,vertices[k].p,vertices[i].p)) w++;
+ else top = lastiter->get().index2;
+ } else w++;
+ }
+ UpdateState(i,k,w,j,top,dpstates);
+}
+
+int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
+ Vector2 p1,p2,p3,p4;
+ PartitionVertex *vertices;
+ DPState2 **dpstates;
+ long i,j,k,n,gap;
+ List<Diagonal> diagonals,diagonals2;
+ Diagonal diagonal,newdiagonal;
+ List<Diagonal> *pairs,*pairs2;
+ List<Diagonal>::Element* iter,*iter2;
+ int ret;
+ TriangulatorPoly newpoly;
+ List<long> indices;
+ List<long>::Element* iiter;
+ bool ijreal,jkreal;
+
+ n = poly->GetNumPoints();
+ vertices = new PartitionVertex[n];
+
+ dpstates = new DPState2 *[n];
+ for(i=0;i<n;i++) {
+ dpstates[i] = new DPState2[n];
+ }
+
+ //init vertex information
+ for(i=0;i<n;i++) {
+ vertices[i].p = poly->GetPoint(i);
+ vertices[i].isActive = true;
+ if(i==0) vertices[i].previous = &(vertices[n-1]);
+ else vertices[i].previous = &(vertices[i-1]);
+ if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]);
+ else vertices[i].next = &(vertices[i+1]);
+ }
+ for(i=1;i<n;i++) {
+ UpdateVertexReflexity(&(vertices[i]));
+ }
+
+ //init states and visibility
+ for(i=0;i<(n-1);i++) {
+ p1 = poly->GetPoint(i);
+ for(j=i+1;j<n;j++) {
+ dpstates[i][j].visible = true;
+ if(j==i+1) {
+ dpstates[i][j].weight = 0;
+ } else {
+ dpstates[i][j].weight = 2147483647;
+ }
+ if(j!=(i+1)) {
+ p2 = poly->GetPoint(j);
+
+ //visibility check
+ if(!InCone(&vertices[i],p2)) {
+ dpstates[i][j].visible = false;
+ continue;
+ }
+ if(!InCone(&vertices[j],p1)) {
+ dpstates[i][j].visible = false;
+ continue;
+ }
+
+ for(k=0;k<n;k++) {
+ p3 = poly->GetPoint(k);
+ if(k==(n-1)) p4 = poly->GetPoint(0);
+ else p4 = poly->GetPoint(k+1);
+ if(Intersects(p1,p2,p3,p4)) {
+ dpstates[i][j].visible = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for(i=0;i<(n-2);i++) {
+ j = i+2;
+ if(dpstates[i][j].visible) {
+ dpstates[i][j].weight = 0;
+ newdiagonal.index1 = i+1;
+ newdiagonal.index2 = i+1;
+ dpstates[i][j].pairs.push_back(newdiagonal);
+ }
+ }
+
+ dpstates[0][n-1].visible = true;
+ vertices[0].isConvex = false; //by convention
+
+ for(gap=3; gap<n; gap++) {
+ for(i=0;i<n-gap;i++) {
+ if(vertices[i].isConvex) continue;
+ k = i+gap;
+ if(dpstates[i][k].visible) {
+ if(!vertices[k].isConvex) {
+ for(j=i+1;j<k;j++) TypeA(i,j,k,vertices,dpstates);
+ } else {
+ for(j=i+1;j<(k-1);j++) {
+ if(vertices[j].isConvex) continue;
+ TypeA(i,j,k,vertices,dpstates);
+ }
+ TypeA(i,k-1,k,vertices,dpstates);
+ }
+ }
+ }
+ for(k=gap;k<n;k++) {
+ if(vertices[k].isConvex) continue;
+ i = k-gap;
+ if((vertices[i].isConvex)&&(dpstates[i][k].visible)) {
+ TypeB(i,i+1,k,vertices,dpstates);
+ for(j=i+2;j<k;j++) {
+ if(vertices[j].isConvex) continue;
+ TypeB(i,j,k,vertices,dpstates);
+ }
+ }
+ }
+ }
+
+
+ //recover solution
+ ret = 1;
+ newdiagonal.index1 = 0;
+ newdiagonal.index2 = n-1;
+ diagonals.push_front(newdiagonal);
+ while(!diagonals.empty()) {
+ diagonal = (diagonals.front()->get());
+ diagonals.pop_front();
+ if((diagonal.index2 - diagonal.index1) <=1) continue;
+ pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
+ if(pairs->empty()) {
+ ret = 0;
+ break;
+ }
+ if(!vertices[diagonal.index1].isConvex) {
+ iter = pairs->back();
+
+ j = iter->get().index2;
+ newdiagonal.index1 = j;
+ newdiagonal.index2 = diagonal.index2;
+ diagonals.push_front(newdiagonal);
+ if((j - diagonal.index1)>1) {
+ if(iter->get().index1 != iter->get().index2) {
+ pairs2 = &(dpstates[diagonal.index1][j].pairs);
+ while(1) {
+ if(pairs2->empty()) {
+ ret = 0;
+ break;
+ }
+ iter2 = pairs2->back();
+
+ if(iter->get().index1 != iter2->get().index1) pairs2->pop_back();
+ else break;
+ }
+ if(ret == 0) break;
+ }
+ newdiagonal.index1 = diagonal.index1;
+ newdiagonal.index2 = j;
+ diagonals.push_front(newdiagonal);
+ }
+ } else {
+ iter = pairs->front();
+ j = iter->get().index1;
+ newdiagonal.index1 = diagonal.index1;
+ newdiagonal.index2 = j;
+ diagonals.push_front(newdiagonal);
+ if((diagonal.index2 - j) > 1) {
+ if(iter->get().index1 != iter->get().index2) {
+ pairs2 = &(dpstates[j][diagonal.index2].pairs);
+ while(1) {
+ if(pairs2->empty()) {
+ ret = 0;
+ break;
+ }
+ iter2 = pairs2->front();
+ if(iter->get().index2 != iter2->get().index2) pairs2->pop_front();
+ else break;
+ }
+ if(ret == 0) break;
+ }
+ newdiagonal.index1 = j;
+ newdiagonal.index2 = diagonal.index2;
+ diagonals.push_front(newdiagonal);
+ }
+ }
+ }
+
+ if(ret == 0) {
+ for(i=0;i<n;i++) {
+ delete [] dpstates[i];
+ }
+ delete [] dpstates;
+ delete [] vertices;
+
+ return ret;
+ }
+
+ newdiagonal.index1 = 0;
+ newdiagonal.index2 = n-1;
+ diagonals.push_front(newdiagonal);
+ while(!diagonals.empty()) {
+ diagonal = (diagonals.front())->get();
+ diagonals.pop_front();
+ if((diagonal.index2 - diagonal.index1) <= 1) continue;
+
+ indices.clear();
+ diagonals2.clear();
+ indices.push_back(diagonal.index1);
+ indices.push_back(diagonal.index2);
+ diagonals2.push_front(diagonal);
+
+ while(!diagonals2.empty()) {
+ diagonal = (diagonals2.front()->get());
+ diagonals2.pop_front();
+ if((diagonal.index2 - diagonal.index1) <= 1) continue;
+ ijreal = true;
+ jkreal = true;
+ pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
+ if(!vertices[diagonal.index1].isConvex) {
+ iter = pairs->back();
+ j = iter->get().index2;
+ if(iter->get().index1 != iter->get().index2) ijreal = false;
+ } else {
+ iter = pairs->front();
+ j = iter->get().index1;
+ if(iter->get().index1 != iter->get().index2) jkreal = false;
+ }
+
+ newdiagonal.index1 = diagonal.index1;
+ newdiagonal.index2 = j;
+ if(ijreal) {
+ diagonals.push_back(newdiagonal);
+ } else {
+ diagonals2.push_back(newdiagonal);
+ }
+
+ newdiagonal.index1 = j;
+ newdiagonal.index2 = diagonal.index2;
+ if(jkreal) {
+ diagonals.push_back(newdiagonal);
+ } else {
+ diagonals2.push_back(newdiagonal);
+ }
+
+ indices.push_back(j);
+ }
+
+ indices.sort();
+ newpoly.Init((long)indices.size());
+ k=0;
+ for(iiter = indices.front();iiter;iiter=iiter->next()) {
+ newpoly[k] = vertices[iiter->get()].p;
+ k++;
+ }
+ parts->push_back(newpoly);
+ }
+
+ for(i=0;i<n;i++) {
+ delete [] dpstates[i];
+ }
+ delete [] dpstates;
+ delete [] vertices;
+
+ return ret;
+}
+
+//triangulates a set of polygons by first partitioning them into monotone polygons
+//O(n*log(n)) time complexity, O(n) space complexity
+//the algorithm used here is outlined in the book
+//"Computational Geometry: Algorithms and Applications"
+//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
+int TriangulatorPartition::MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys) {
+ List<TriangulatorPoly>::Element *iter;
+ MonotoneVertex *vertices;
+ long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
+ long polystartindex, polyendindex;
+ TriangulatorPoly *poly;
+ MonotoneVertex *v,*v2,*vprev,*vnext;
+ ScanLineEdge newedge;
+ bool error = false;
+
+ numvertices = 0;
+ for(iter = inpolys->front(); iter ; iter=iter->next()) {
+ numvertices += iter->get().GetNumPoints();
+ }
+
+ maxnumvertices = numvertices*3;
+ vertices = new MonotoneVertex[maxnumvertices];
+ newnumvertices = numvertices;
+
+ polystartindex = 0;
+ for(iter = inpolys->front(); iter ; iter=iter->next()) {
+ poly = &(iter->get());
+ polyendindex = polystartindex + poly->GetNumPoints()-1;
+ for(i=0;i<poly->GetNumPoints();i++) {
+ vertices[i+polystartindex].p = poly->GetPoint(i);
+ if(i==0) vertices[i+polystartindex].previous = polyendindex;
+ else vertices[i+polystartindex].previous = i+polystartindex-1;
+ if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex;
+ else vertices[i+polystartindex].next = i+polystartindex+1;
+ }
+ polystartindex = polyendindex+1;
+ }
+
+ //construct the priority queue
+ long *priority = new long [numvertices];
+ for(i=0;i<numvertices;i++) priority[i] = i;
+ SortArray<long,VertexSorter> sorter;
+ sorter.compare.vertices=vertices;
+ sorter.sort(priority,numvertices);
+
+ //determine vertex types
+ char *vertextypes = new char[maxnumvertices];
+ for(i=0;i<numvertices;i++) {
+ v = &(vertices[i]);
+ vprev = &(vertices[v->previous]);
+ vnext = &(vertices[v->next]);
+
+ if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) {
+ if(IsConvex(vnext->p,vprev->p,v->p)) {
+ vertextypes[i] = TRIANGULATOR_VERTEXTYPE_START;
+ } else {
+ vertextypes[i] = TRIANGULATOR_VERTEXTYPE_SPLIT;
+ }
+ } else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) {
+ if(IsConvex(vnext->p,vprev->p,v->p))
+ {
+ vertextypes[i] = TRIANGULATOR_VERTEXTYPE_END;
+ } else {
+ vertextypes[i] = TRIANGULATOR_VERTEXTYPE_MERGE;
+ }
+ } else {
+ vertextypes[i] = TRIANGULATOR_VERTEXTYPE_REGULAR;
+ }
+ }
+
+ //helpers
+ long *helpers = new long[maxnumvertices];
+
+ //binary search tree that holds edges intersecting the scanline
+ //note that while set doesn't actually have to be implemented as a tree
+ //complexity requirements for operations are the same as for the balanced binary search tree
+ Set<ScanLineEdge> edgeTree;
+ //store iterators to the edge tree elements
+ //this makes deleting existing edges much faster
+ Set<ScanLineEdge>::Element **edgeTreeIterators,*edgeIter;
+ edgeTreeIterators = new Set<ScanLineEdge>::Element*[maxnumvertices];
+// Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet;
+ for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = NULL;
+
+ //for each vertex
+ for(i=0;i<numvertices;i++) {
+ vindex = priority[i];
+ v = &(vertices[vindex]);
+ vindex2 = vindex;
+ v2 = v;
+
+ //depending on the vertex type, do the appropriate action
+ //comments in the following sections are copied from "Computational Geometry: Algorithms and Applications"
+ switch(vertextypes[vindex]) {
+ case TRIANGULATOR_VERTEXTYPE_START:
+ //Insert ei in T and set helper(ei) to vi.
+ newedge.p1 = v->p;
+ newedge.p2 = vertices[v->next].p;
+ newedge.index = vindex;
+ edgeTreeIterators[vindex] = edgeTree.insert(newedge);
+ helpers[vindex] = vindex;
+ break;
+
+ case TRIANGULATOR_VERTEXTYPE_END:
+ //if helper(ei-1) is a merge vertex
+ if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+ //Insert the diagonal connecting vi to helper(ei-1) in D.
+ AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
+ vertextypes, edgeTreeIterators, &edgeTree, helpers);
+ }
+ //Delete ei-1 from T
+ edgeTree.erase(edgeTreeIterators[v->previous]);
+ break;
+
+ case TRIANGULATOR_VERTEXTYPE_SPLIT:
+ //Search in T to find the edge e j directly left of vi.
+ newedge.p1 = v->p;
+ newedge.p2 = v->p;
+ edgeIter = edgeTree.lower_bound(newedge);
+ if(edgeIter == edgeTree.front()) {
+ error = true;
+ break;
+ }
+ edgeIter=edgeIter->prev();
+ //Insert the diagonal connecting vi to helper(ej) in D.
+ AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index],
+ vertextypes, edgeTreeIterators, &edgeTree, helpers);
+ vindex2 = newnumvertices-2;
+ v2 = &(vertices[vindex2]);
+ //helper(e j)�vi
+ helpers[edgeIter->get().index] = vindex;
+ //Insert ei in T and set helper(ei) to vi.
+ newedge.p1 = v2->p;
+ newedge.p2 = vertices[v2->next].p;
+ newedge.index = vindex2;
+
+ edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
+ helpers[vindex2] = vindex2;
+ break;
+
+ case TRIANGULATOR_VERTEXTYPE_MERGE:
+ //if helper(ei-1) is a merge vertex
+ if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+ //Insert the diagonal connecting vi to helper(ei-1) in D.
+ AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
+ vertextypes, edgeTreeIterators, &edgeTree, helpers);
+ vindex2 = newnumvertices-2;
+ v2 = &(vertices[vindex2]);
+ }
+ //Delete ei-1 from T.
+ edgeTree.erase(edgeTreeIterators[v->previous]);
+ //Search in T to find the edge e j directly left of vi.
+ newedge.p1 = v->p;
+ newedge.p2 = v->p;
+ edgeIter = edgeTree.lower_bound(newedge);
+ if(edgeIter == edgeTree.front()) {
+ error = true;
+ break;
+ }
+ edgeIter=edgeIter->prev();
+ //if helper(ej) is a merge vertex
+ if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+ //Insert the diagonal connecting vi to helper(e j) in D.
+ AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->get().index],
+ vertextypes, edgeTreeIterators, &edgeTree, helpers);
+ }
+ //helper(e j)�vi
+ helpers[edgeIter->get().index] = vindex2;
+ break;
+
+ case TRIANGULATOR_VERTEXTYPE_REGULAR:
+ //if the interior of P lies to the right of vi
+ if(Below(v->p,vertices[v->previous].p)) {
+ //if helper(ei-1) is a merge vertex
+ if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+ //Insert the diagonal connecting vi to helper(ei-1) in D.
+ AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
+ vertextypes, edgeTreeIterators, &edgeTree, helpers);
+ vindex2 = newnumvertices-2;
+ v2 = &(vertices[vindex2]);
+ }
+ //Delete ei-1 from T.
+ edgeTree.erase(edgeTreeIterators[v->previous]);
+ //Insert ei in T and set helper(ei) to vi.
+ newedge.p1 = v2->p;
+ newedge.p2 = vertices[v2->next].p;
+ newedge.index = vindex2;
+ edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
+ helpers[vindex2] = vindex;
+ } else {
+ //Search in T to find the edge ej directly left of vi.
+ newedge.p1 = v->p;
+ newedge.p2 = v->p;
+ edgeIter = edgeTree.lower_bound(newedge);
+ if(edgeIter == edgeTree.front()) {
+ error = true;
+ break;
+ }
+ edgeIter=edgeIter->prev();
+ //if helper(ej) is a merge vertex
+ if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+ //Insert the diagonal connecting vi to helper(e j) in D.
+ AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index],
+ vertextypes, edgeTreeIterators, &edgeTree, helpers);
+ }
+ //helper(e j)�vi
+ helpers[edgeIter->get().index] = vindex;
+ }
+ break;
+ }
+
+ if(error) break;
+ }
+
+ char *used = new char[newnumvertices];
+ memset(used,0,newnumvertices*sizeof(char));
+
+ if(!error) {
+ //return result
+ long size;
+ TriangulatorPoly mpoly;
+ for(i=0;i<newnumvertices;i++) {
+ if(used[i]) continue;
+ v = &(vertices[i]);
+ vnext = &(vertices[v->next]);
+ size = 1;
+ while(vnext!=v) {
+ vnext = &(vertices[vnext->next]);
+ size++;
+ }
+ mpoly.Init(size);
+ v = &(vertices[i]);
+ mpoly[0] = v->p;
+ vnext = &(vertices[v->next]);
+ size = 1;
+ used[i] = 1;
+ used[v->next] = 1;
+ while(vnext!=v) {
+ mpoly[size] = vnext->p;
+ used[vnext->next] = 1;
+ vnext = &(vertices[vnext->next]);
+ size++;
+ }
+ monotonePolys->push_back(mpoly);
+ }
+ }
+
+ //cleanup
+ delete [] vertices;
+ delete [] priority;
+ delete [] vertextypes;
+ delete [] edgeTreeIterators;
+ delete [] helpers;
+ delete [] used;
+
+ if(error) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+//adds a diagonal to the doubly-connected list of vertices
+void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
+ char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
+ Set<ScanLineEdge> *edgeTree, long *helpers)
+{
+ long newindex1,newindex2;
+
+ newindex1 = *numvertices;
+ (*numvertices)++;
+ newindex2 = *numvertices;
+ (*numvertices)++;
+
+ vertices[newindex1].p = vertices[index1].p;
+ vertices[newindex2].p = vertices[index2].p;
+
+ vertices[newindex2].next = vertices[index2].next;
+ vertices[newindex1].next = vertices[index1].next;
+
+ vertices[vertices[index2].next].previous = newindex2;
+ vertices[vertices[index1].next].previous = newindex1;
+
+ vertices[index1].next = newindex2;
+ vertices[newindex2].previous = index1;
+
+ vertices[index2].next = newindex1;
+ vertices[newindex1].previous = index2;
+
+ //update all relevant structures
+ vertextypes[newindex1] = vertextypes[index1];
+ edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
+ helpers[newindex1] = helpers[index1];
+ if(edgeTreeIterators[newindex1] != NULL)
+ edgeTreeIterators[newindex1]->get().index = newindex1;
+ vertextypes[newindex2] = vertextypes[index2];
+ edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
+ helpers[newindex2] = helpers[index2];
+ if(edgeTreeIterators[newindex2] != NULL)
+ edgeTreeIterators[newindex2]->get().index = newindex2;
+}
+
+bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
+ if(p1.y < p2.y) return true;
+ else if(p1.y == p2.y) {
+ if(p1.x < p2.x) return true;
+ }
+ return false;
+}
+
+
+
+
+
+//sorts in the falling order of y values, if y is equal, x is used instead
+bool TriangulatorPartition::VertexSorter::operator() (long index1, long index2) const {
+ if(vertices[index1].p.y > vertices[index2].p.y) return true;
+ else if(vertices[index1].p.y == vertices[index2].p.y) {
+ if(vertices[index1].p.x > vertices[index2].p.x) return true;
+ }
+ return false;
+}
+
+bool TriangulatorPartition::ScanLineEdge::IsConvex(const Vector2& p1, const Vector2& p2, const Vector2& p3) const {
+ real_t tmp;
+ tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
+ if(tmp>0) return 1;
+ else return 0;
+}
+
+bool TriangulatorPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const {
+ if(other.p1.y == other.p2.y) {
+ if(p1.y == p2.y) {
+ if(p1.y < other.p1.y) return true;
+ else return false;
+ }
+ if(IsConvex(p1,p2,other.p1)) return true;
+ else return false;
+ } else if(p1.y == p2.y) {
+ if(IsConvex(other.p1,other.p2,p1)) return false;
+ else return true;
+ } else if(p1.y < other.p1.y) {
+ if(IsConvex(other.p1,other.p2,p1)) return false;
+ else return true;
+ } else {
+ if(IsConvex(p1,p2,other.p1)) return true;
+ else return false;
+ }
+}
+
+//triangulates monotone polygon
+//O(n) time, O(n) space complexity
+int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles) {
+ long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
+ Vector2 *points;
+ long numpoints;
+ TriangulatorPoly triangle;
+
+ numpoints = inPoly->GetNumPoints();
+ points = inPoly->GetPoints();
+
+ //trivial calses
+ if(numpoints < 3) return 0;
+ if(numpoints == 3) {
+ triangles->push_back(*inPoly);
+ }
+
+ topindex = 0; bottomindex=0;
+ for(i=1;i<numpoints;i++) {
+ if(Below(points[i],points[bottomindex])) bottomindex = i;
+ if(Below(points[topindex],points[i])) topindex = i;
+ }
+
+ //check if the poly is really monotone
+ i = topindex;
+ while(i!=bottomindex) {
+ i2 = i+1; if(i2>=numpoints) i2 = 0;
+ if(!Below(points[i2],points[i])) return 0;
+ i = i2;
+ }
+ i = bottomindex;
+ while(i!=topindex) {
+ i2 = i+1; if(i2>=numpoints) i2 = 0;
+ if(!Below(points[i],points[i2])) return 0;
+ i = i2;
+ }
+
+ char *vertextypes = new char[numpoints];
+ long *priority = new long[numpoints];
+
+ //merge left and right vertex chains
+ priority[0] = topindex;
+ vertextypes[topindex] = 0;
+ leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0;
+ rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1;
+ for(i=1;i<(numpoints-1);i++) {
+ if(leftindex==bottomindex) {
+ priority[i] = rightindex;
+ rightindex--; if(rightindex<0) rightindex = numpoints-1;
+ vertextypes[priority[i]] = -1;
+ } else if(rightindex==bottomindex) {
+ priority[i] = leftindex;
+ leftindex++; if(leftindex>=numpoints) leftindex = 0;
+ vertextypes[priority[i]] = 1;
+ } else {
+ if(Below(points[leftindex],points[rightindex])) {
+ priority[i] = rightindex;
+ rightindex--; if(rightindex<0) rightindex = numpoints-1;
+ vertextypes[priority[i]] = -1;
+ } else {
+ priority[i] = leftindex;
+ leftindex++; if(leftindex>=numpoints) leftindex = 0;
+ vertextypes[priority[i]] = 1;
+ }
+ }
+ }
+ priority[i] = bottomindex;
+ vertextypes[bottomindex] = 0;
+
+ long *stack = new long[numpoints];
+ long stackptr = 0;
+
+ stack[0] = priority[0];
+ stack[1] = priority[1];
+ stackptr = 2;
+
+ //for each vertex from top to bottom trim as many triangles as possible
+ for(i=2;i<(numpoints-1);i++) {
+ vindex = priority[i];
+ if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) {
+ for(j=0;j<(stackptr-1);j++) {
+ if(vertextypes[vindex]==1) {
+ triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
+ } else {
+ triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
+ }
+ triangles->push_back(triangle);
+ }
+ stack[0] = priority[i-1];
+ stack[1] = priority[i];
+ stackptr = 2;
+ } else {
+ stackptr--;
+ while(stackptr>0) {
+ if(vertextypes[vindex]==1) {
+ if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) {
+ triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]);
+ triangles->push_back(triangle);
+ stackptr--;
+ } else {
+ break;
+ }
+ } else {
+ if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) {
+ triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]);
+ triangles->push_back(triangle);
+ stackptr--;
+ } else {
+ break;
+ }
+ }
+ }
+ stackptr++;
+ stack[stackptr] = vindex;
+ stackptr++;
+ }
+ }
+ vindex = priority[i];
+ for(j=0;j<(stackptr-1);j++) {
+ if(vertextypes[stack[j+1]]==1) {
+ triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
+ } else {
+ triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
+ }
+ triangles->push_back(triangle);
+ }
+
+ delete [] priority;
+ delete [] vertextypes;
+ delete [] stack;
+
+ return 1;
+}
+
+int TriangulatorPartition::Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
+ List<TriangulatorPoly> monotone;
+ List<TriangulatorPoly>::Element* iter;
+
+ if(!MonotonePartition(inpolys,&monotone)) return 0;
+ for(iter = monotone.front(); iter;iter=iter->next()) {
+ if(!TriangulateMonotone(&(iter->get()),triangles)) return 0;
+ }
+ return 1;
+}
+
+int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
+ List<TriangulatorPoly> polys;
+ polys.push_back(*poly);
+
+ return Triangulate_MONO(&polys, triangles);
+}
diff --git a/core/math/triangulator.h b/core/math/triangulator.h
new file mode 100644
index 0000000000..b6dd7e8236
--- /dev/null
+++ b/core/math/triangulator.h
@@ -0,0 +1,306 @@
+//Copyright (C) 2011 by Ivan Fratric
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+//of this software and associated documentation files (the "Software"), to deal
+//in the Software without restriction, including without limitation the rights
+//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//copies of the Software, and to permit persons to whom the Software is
+//furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included in
+//all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//THE SOFTWARE.
+
+#ifndef TRIANGULATOR_H
+#define TRIANGULATOR_H
+
+#include "math_2d.h"
+#include "list.h"
+#include "set.h"
+//2D point structure
+
+
+#define TRIANGULATOR_CCW 1
+#define TRIANGULATOR_CW -1
+//Polygon implemented as an array of points with a 'hole' flag
+class TriangulatorPoly {
+protected:
+
+
+
+ Vector2 *points;
+ long numpoints;
+ bool hole;
+
+public:
+
+ //constructors/destructors
+ TriangulatorPoly();
+ ~TriangulatorPoly();
+
+ TriangulatorPoly(const TriangulatorPoly &src);
+ TriangulatorPoly& operator=(const TriangulatorPoly &src);
+
+ //getters and setters
+ long GetNumPoints() {
+ return numpoints;
+ }
+
+ bool IsHole() {
+ return hole;
+ }
+
+ void SetHole(bool hole) {
+ this->hole = hole;
+ }
+
+ Vector2 &GetPoint(long i) {
+ return points[i];
+ }
+
+ Vector2 *GetPoints() {
+ return points;
+ }
+
+ Vector2& operator[] (int i) {
+ return points[i];
+ }
+
+ //clears the polygon points
+ void Clear();
+
+ //inits the polygon with numpoints vertices
+ void Init(long numpoints);
+
+ //creates a triangle with points p1,p2,p3
+ void Triangle(Vector2 &p1, Vector2 &p2, Vector2 &p3);
+
+ //inverts the orfer of vertices
+ void Invert();
+
+ //returns the orientation of the polygon
+ //possible values:
+ // Triangulator_CCW : polygon vertices are in counter-clockwise order
+ // Triangulator_CW : polygon vertices are in clockwise order
+ // 0 : the polygon has no (measurable) area
+ int GetOrientation();
+
+ //sets the polygon orientation
+ //orientation can be
+ // Triangulator_CCW : sets vertices in counter-clockwise order
+ // Triangulator_CW : sets vertices in clockwise order
+ void SetOrientation(int orientation);
+};
+
+class TriangulatorPartition {
+protected:
+ struct PartitionVertex {
+ bool isActive;
+ bool isConvex;
+ bool isEar;
+
+ Vector2 p;
+ real_t angle;
+ PartitionVertex *previous;
+ PartitionVertex *next;
+ };
+
+ struct MonotoneVertex {
+ Vector2 p;
+ long previous;
+ long next;
+ };
+
+ struct VertexSorter{
+ mutable MonotoneVertex *vertices;
+ bool operator() (long index1, long index2) const;
+ };
+
+ struct Diagonal {
+ long index1;
+ long index2;
+ };
+
+ //dynamic programming state for minimum-weight triangulation
+ struct DPState {
+ bool visible;
+ real_t weight;
+ long bestvertex;
+ };
+
+ //dynamic programming state for convex partitioning
+ struct DPState2 {
+ bool visible;
+ long weight;
+ List<Diagonal> pairs;
+ };
+
+ //edge that intersects the scanline
+ struct ScanLineEdge {
+ mutable long index;
+ Vector2 p1;
+ Vector2 p2;
+
+ //determines if the edge is to the left of another edge
+ bool operator< (const ScanLineEdge & other) const;
+
+ bool IsConvex(const Vector2& p1, const Vector2& p2, const Vector2& p3) const;
+ };
+
+ //standard helper functions
+ bool IsConvex(Vector2& p1, Vector2& p2, Vector2& p3);
+ bool IsReflex(Vector2& p1, Vector2& p2, Vector2& p3);
+ bool IsInside(Vector2& p1, Vector2& p2, Vector2& p3, Vector2 &p);
+
+ bool InCone(Vector2 &p1, Vector2 &p2, Vector2 &p3, Vector2 &p);
+ bool InCone(PartitionVertex *v, Vector2 &p);
+
+ int Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21, Vector2 &p22);
+
+ Vector2 Normalize(const Vector2 &p);
+ real_t Distance(const Vector2 &p1, const Vector2 &p2);
+
+ //helper functions for Triangulate_EC
+ void UpdateVertexReflexity(PartitionVertex *v);
+ void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
+
+ //helper functions for ConvexPartition_OPT
+ void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
+ void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
+ void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
+
+ //helper functions for MonotonePartition
+ bool Below(Vector2 &p1, Vector2 &p2);
+ void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
+ char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
+ Set<ScanLineEdge> *edgeTree, long *helpers);
+
+ //triangulates a monotone polygon, used in Triangulate_MONO
+ int TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles);
+
+public:
+
+ //simple heuristic procedure for removing holes from a list of polygons
+ //works by creating a diagonal from the rightmost hole vertex to some visible vertex
+ //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // inpolys : a list of polygons that can contain holes
+ // vertices of all non-hole polys have to be in counter-clockwise order
+ // vertices of all hole polys have to be in clockwise order
+ // outpolys : a list of polygons without holes
+ //returns 1 on success, 0 on failure
+ int RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys);
+
+ //triangulates a polygon by ear clipping
+ //time complexity O(n^2), n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // poly : an input polygon to be triangulated
+ // vertices have to be in counter-clockwise order
+ // triangles : a list of triangles (result)
+ //returns 1 on success, 0 on failure
+ int Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
+
+ //triangulates a list of polygons that may contain holes by ear clipping algorithm
+ //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
+ //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // inpolys : a list of polygons to be triangulated (can contain holes)
+ // vertices of all non-hole polys have to be in counter-clockwise order
+ // vertices of all hole polys have to be in clockwise order
+ // triangles : a list of triangles (result)
+ //returns 1 on success, 0 on failure
+ int Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles);
+
+ //creates an optimal polygon triangulation in terms of minimal edge length
+ //time complexity: O(n^3), n is the number of vertices
+ //space complexity: O(n^2)
+ //params:
+ // poly : an input polygon to be triangulated
+ // vertices have to be in counter-clockwise order
+ // triangles : a list of triangles (result)
+ //returns 1 on success, 0 on failure
+ int Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
+
+ //triangulates a polygons by firstly partitioning it into monotone polygons
+ //time complexity: O(n*log(n)), n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // poly : an input polygon to be triangulated
+ // vertices have to be in counter-clockwise order
+ // triangles : a list of triangles (result)
+ //returns 1 on success, 0 on failure
+ int Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
+
+ //triangulates a list of polygons by firstly partitioning them into monotone polygons
+ //time complexity: O(n*log(n)), n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // inpolys : a list of polygons to be triangulated (can contain holes)
+ // vertices of all non-hole polys have to be in counter-clockwise order
+ // vertices of all hole polys have to be in clockwise order
+ // triangles : a list of triangles (result)
+ //returns 1 on success, 0 on failure
+ int Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles);
+
+ //creates a monotone partition of a list of polygons that can contain holes
+ //time complexity: O(n*log(n)), n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // inpolys : a list of polygons to be triangulated (can contain holes)
+ // vertices of all non-hole polys have to be in counter-clockwise order
+ // vertices of all hole polys have to be in clockwise order
+ // monotonePolys : a list of monotone polygons (result)
+ //returns 1 on success, 0 on failure
+ int MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys);
+
+ //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
+ //the algorithm gives at most four times the number of parts as the optimal algorithm
+ //however, in practice it works much better than that and often gives optimal partition
+ //uses triangulation obtained by ear clipping as intermediate result
+ //time complexity O(n^2), n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // poly : an input polygon to be partitioned
+ // vertices have to be in counter-clockwise order
+ // parts : resulting list of convex polygons
+ //returns 1 on success, 0 on failure
+ int ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts);
+
+ //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
+ //the algorithm gives at most four times the number of parts as the optimal algorithm
+ //however, in practice it works much better than that and often gives optimal partition
+ //uses triangulation obtained by ear clipping as intermediate result
+ //time complexity O(n^2), n is the number of vertices
+ //space complexity: O(n)
+ //params:
+ // inpolys : an input list of polygons to be partitioned
+ // vertices of all non-hole polys have to be in counter-clockwise order
+ // vertices of all hole polys have to be in clockwise order
+ // parts : resulting list of convex polygons
+ //returns 1 on success, 0 on failure
+ int ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts);
+
+ //optimal convex partitioning (in terms of number of resulting convex polygons)
+ //using the Keil-Snoeyink algorithm
+ //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998
+ //time complexity O(n^3), n is the number of vertices
+ //space complexity: O(n^3)
+ // poly : an input polygon to be partitioned
+ // vertices have to be in counter-clockwise order
+ // parts : resulting list of convex polygons
+ //returns 1 on success, 0 on failure
+ int ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts);
+};
+
+
+#endif
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index cf6fd9242e..a3877eb9ff 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,27 +27,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "vector3.h"
-
+#include "matrix3.h"
void Vector3::rotate(const Vector3& p_axis,float p_phi) {
- Vector3 axis1 = cross(p_axis);
- float l = axis1.length();
- if (l==0)
- return;
- axis1/=l;
- Vector3 axis2 = axis1.cross(p_axis).normalized();
-
- float _x = axis1.dot(*this);
- float _y = axis2.dot(*this);
-
- float ang = Math::atan2(_x,_y);
-
- ang+=p_phi;
-
- *this=((axis1 * Math::cos(ang)) + (axis2 * Math::sin(ang))) * length();
-
+ *this=Matrix3(p_axis,p_phi).xform(*this);
}
Vector3 Vector3::rotated(const Vector3& p_axis,float p_phi) const {
diff --git a/core/math/vector3.h b/core/math/vector3.h
index d2f2408829..8a3cca8f33 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,11 +40,11 @@ struct Vector3 {
enum Axis {
AXIS_X,
AXIS_Y,
- AXIS_Z,
+ AXIS_Z,
};
union {
-
+
#ifdef USE_QUAD_VECTORS
struct {
@@ -52,7 +52,7 @@ struct Vector3 {
real_t y;
real_t z;
real_t _unused;
- };
+ };
real_t coord[4];
#else
@@ -61,18 +61,18 @@ struct Vector3 {
real_t y;
real_t z;
};
-
+
real_t coord[3];
#endif
};
_FORCE_INLINE_ const real_t& operator[](int p_axis) const {
-
+
return coord[p_axis];
}
_FORCE_INLINE_ real_t& operator[](int p_axis) {
-
+
return coord[p_axis];
}
@@ -84,7 +84,7 @@ struct Vector3 {
_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;
-
+
_FORCE_INLINE_ void normalize();
_FORCE_INLINE_ Vector3 normalized() const;
_FORCE_INLINE_ Vector3 inverse() const;
@@ -107,6 +107,8 @@ struct Vector3 {
_FORCE_INLINE_ real_t dot(const Vector3& p_b) const;
_FORCE_INLINE_ Vector3 abs() const;
+ _FORCE_INLINE_ Vector3 floor() const;
+ _FORCE_INLINE_ Vector3 ceil() const;
_FORCE_INLINE_ real_t distance_to(const Vector3& p_b) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3& p_b) const;
@@ -172,7 +174,17 @@ real_t Vector3::dot(const Vector3& p_b) const {
Vector3 Vector3::abs() const {
return Vector3( Math::abs(x), Math::abs(y), Math::abs(z) );
-}
+}
+
+Vector3 Vector3::floor() const {
+
+ return Vector3( Math::floor(x), Math::floor(y), Math::floor(z) );
+}
+
+Vector3 Vector3::ceil() const {
+
+ return Vector3( Math::ceil(x), Math::ceil(y), Math::ceil(z) );
+}
Vector3 Vector3::linear_interpolate(const Vector3& p_b,float p_t) const {
@@ -301,7 +313,7 @@ bool Vector3::operator<(const Vector3& p_v) const {
return y<p_v.y;
} else
return x<p_v.x;
-
+
}
bool Vector3::operator<=(const Vector3& p_v) const {
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index dbf6217dc2..489939ee65 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -324,6 +324,7 @@ int MessageQueue::get_max_buffer_usage() const {
void MessageQueue::flush() {
+
if (buffer_max_used<buffer_end); {
buffer_max_used=buffer_end;
//statistics();
@@ -331,9 +332,14 @@ void MessageQueue::flush() {
uint32_t read_pos=0;
- while (read_pos < buffer_end ) {
+ //using reverse locking strategy
+ _THREAD_SAFE_LOCK_
+
+ while (read_pos<buffer_end) {
+
+ _THREAD_SAFE_UNLOCK_
+
//lock on each interation, so a call can re-add itself to the message queue
- _THREAD_SAFE_LOCK_
Message *message = (Message*)&buffer[ read_pos ];
@@ -379,16 +385,17 @@ void MessageQueue::flush() {
}
- read_pos+=sizeof(Message);
+ uint32_t advance = sizeof(Message);
if (message->type!=TYPE_NOTIFICATION)
- read_pos+=sizeof(Variant)*message->args;
+ advance+=sizeof(Variant)*message->args;
message->~Message();
- _THREAD_SAFE_UNLOCK_
+ _THREAD_SAFE_LOCK_
+ read_pos+=advance;
}
- _THREAD_SAFE_LOCK_
+
buffer_end=0; // reset buffer
_THREAD_SAFE_UNLOCK_
diff --git a/core/message_queue.h b/core/message_queue.h
index 691c289813..5cee21847b 100644
--- a/core/message_queue.h
+++ b/core/message_queue.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/method_bind.cpp b/core/method_bind.cpp
index 6ee4882571..ce57380434 100644
--- a/core/method_bind.cpp
+++ b/core/method_bind.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,8 +40,8 @@ PropertyInfo MethodBind::get_argument_info(int p_argument) const {
PropertyInfo pi( get_argument_type(p_argument), name );
if ((pi.type==Variant::OBJECT) && name.find(":")!=-1) {
pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string=name.get_slice(":",1);
- pi.name=name.get_slice(":",0);
+ pi.hint_string=name.get_slicec(':',1);
+ pi.name=name.get_slicec(':',0);
}
return pi;
diff --git a/core/method_bind.h b/core/method_bind.h
index 3f08c70af8..85c1084f80 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -98,7 +98,7 @@ struct VariantCaster<m_enum> {\
#define CHECK_ARG(m_arg)\
if ((m_arg-1)<p_arg_count) {\
Variant::Type argtype=get_argument_type(m_arg-1);\
- if (!Variant::can_convert(p_args[m_arg-1]->get_type(),argtype)) {\
+ if (!Variant::can_convert_strict(p_args[m_arg-1]->get_type(),argtype)) {\
r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\
r_error.argument=m_arg-1;\
r_error.expected=argtype;\
@@ -178,6 +178,7 @@ public:
#ifdef DEBUG_METHODS_ENABLED
_FORCE_INLINE_ void set_return_type(const StringName& p_type) { ret_type=p_type; }
+ _FORCE_INLINE_ StringName get_return_type() const { return ret_type; }
_FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const {
@@ -297,7 +298,7 @@ MethodBind* create_native_method_bind( Variant (T::*p_method)(const Variant**,in
// tale of an amazing hack.. //
-// if you declare an unexisting class..
+// if you declare an nonexistent class..
class __UnexistingClass;
diff --git a/core/multi_bucket_array.h b/core/multi_bucket_array.h
index a24af941f8..d85c9de583 100644
--- a/core/multi_bucket_array.h
+++ b/core/multi_bucket_array.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/object.cpp b/core/object.cpp
index 82144ab4be..07ac430d7a 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,6 +33,8 @@
#include "message_queue.h"
#include "core_string_names.h"
#include "translation.h"
+#include "os/os.h"
+#include "resource.h"
#ifdef DEBUG_ENABLED
@@ -256,12 +258,15 @@ bool Object::_predelete() {
_predelete_ok=1;
notification(NOTIFICATION_PREDELETE,true);
+ if (_predelete_ok) {
+ _type_ptr=NULL; //must restore so destructors can access type ptr correctly
+ }
return _predelete_ok;
}
void Object::_postinitialize() {
-
+ _type_ptr=_get_type_namev();
_initialize_typev();
notification(NOTIFICATION_POSTINITIALIZE);
@@ -994,12 +999,44 @@ Variant Object::get_meta(const String& p_name) const {
return metadata[p_name];
}
+
Array Object::_get_property_list_bind() const {
List<PropertyInfo> lpi;
get_property_list(&lpi);
return convert_property_list(&lpi);
}
+
+Array Object::_get_method_list_bind() const {
+
+ List<MethodInfo> ml;
+ get_method_list(&ml);
+ Array ret;
+
+ for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
+
+ Dictionary d;
+ d["name"]=E->get().name;
+ d["args"]=convert_property_list(&E->get().arguments);
+ Array da;
+ for(int i=0;i<E->get().default_arguments.size();i++)
+ da.push_back(E->get().default_arguments[i]);
+ d["default_args"]=da;
+ d["flags"]=E->get().flags;
+ d["id"]=E->get().id;
+ Dictionary r;
+ r["type"]=E->get().return_val.type;
+ r["hint"]=E->get().return_val.hint;
+ r["hint_string"]=E->get().return_val.hint_string;
+ d["return_type"]=r;
+ //va.push_back(d);
+ ret.push_back(d);
+ }
+
+ return ret;
+
+}
+
DVector<String> Object::_get_meta_list_bind() const {
DVector<String> _metaret;
@@ -1033,6 +1070,13 @@ void Object::add_user_signal(const MethodInfo& p_signal) {
signal_map[p_signal.name]=s;
}
+bool Object::_has_user_signal(const StringName& p_name) const {
+
+ if (!signal_map.has(p_name))
+ return false;
+ return signal_map[p_name].user.name.length()>0;
+}
+
struct _ObjectSignalDisconnectData {
StringName signal;
@@ -1261,6 +1305,10 @@ Array Object::_get_signal_connection_list(const String& p_signal) const{
void Object::get_signal_list(List<MethodInfo> *p_signals ) const {
+ if (!script.is_null()) {
+ Ref<Script>(script)->get_script_signal_list(p_signals);
+ }
+
ObjectTypeDB::get_signal_list(get_type_name(),p_signals);
//find maybe usersignals?
const StringName *S=NULL;
@@ -1272,6 +1320,24 @@ void Object::get_signal_list(List<MethodInfo> *p_signals ) const {
p_signals->push_back(signal_map[*S].user);
}
}
+
+}
+
+
+void Object::get_all_signal_connections(List<Connection> *p_connections) const {
+
+ const StringName *S=NULL;
+
+ while((S=signal_map.next(S))) {
+
+ const Signal *s=&signal_map[*S];
+
+ for(int i=0;i<s->slot_map.size();i++) {
+
+ p_connections->push_back(s->slot_map.getv(i).conn);
+ }
+ }
+
}
void Object::get_signal_connection_list(const StringName& p_signal,List<Connection> *p_connections) const {
@@ -1293,8 +1359,12 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str
Signal *s = signal_map.getptr(p_signal);
if (!s) {
bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
+ //check in script
+ if (!signal_is_valid && !script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
+ signal_is_valid=true;
+
if (!signal_is_valid) {
- ERR_EXPLAIN("Attempt to connect to unexisting signal: "+p_signal);
+ ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'");
ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER);
}
signal_map[p_signal]=Signal();
@@ -1331,7 +1401,7 @@ bool Object::is_connected(const StringName& p_signal, Object *p_to_object, const
bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
if (signal_is_valid)
return false;
- ERR_EXPLAIN("Unexisting signal: "+p_signal);
+ ERR_EXPLAIN("Nonexistent signal: "+p_signal);
ERR_FAIL_COND_V(!s,false);
}
@@ -1348,7 +1418,7 @@ void Object::disconnect(const StringName& p_signal, Object *p_to_object, const S
ERR_FAIL_NULL(p_to_object);
Signal *s = signal_map.getptr(p_signal);
if (!s) {
- ERR_EXPLAIN("Unexisting signal: "+p_signal);
+ ERR_EXPLAIN("Nonexistent signal: "+p_signal);
ERR_FAIL_COND(!s);
}
if (s->lock>0) {
@@ -1359,7 +1429,7 @@ void Object::disconnect(const StringName& p_signal, Object *p_to_object, const S
Signal::Target target(p_to_object->get_instance_ID(),p_to_method);
if (!s->slot_map.has(target)) {
- ERR_EXPLAIN("Disconnecting unexisting signal '"+p_signal+"', slot: "+itos(target._id)+":"+target.method);
+ ERR_EXPLAIN("Disconnecting nonexistent signal '"+p_signal+"', slot: "+itos(target._id)+":"+target.method);
ERR_FAIL();
}
int prev = p_to_object->connections.size();
@@ -1407,6 +1477,63 @@ StringName Object::tr(const StringName& p_message) const {
}
+
+void Object::_clear_internal_resource_paths(const Variant &p_var) {
+
+ switch(p_var.get_type()) {
+
+ case Variant::OBJECT: {
+
+ RES r = p_var;
+ if (!r.is_valid())
+ return;
+
+ if (!r->get_path().begins_with("res://") || r->get_path().find("::")==-1)
+ return; //not an internal resource
+
+ Object *object=p_var;
+ if (!object)
+ return;
+
+ r->set_path("");
+ r->clear_internal_resource_paths();
+ } break;
+ case Variant::ARRAY: {
+
+ Array a=p_var;
+ for(int i=0;i<a.size();i++) {
+ _clear_internal_resource_paths(a[i]);
+ }
+
+ } break;
+ case Variant::DICTIONARY: {
+
+ Dictionary d=p_var;
+ List<Variant> keys;
+ d.get_key_list(&keys);
+
+ for (List<Variant>::Element *E=keys.front();E;E=E->next()) {
+
+ _clear_internal_resource_paths(E->get());
+ _clear_internal_resource_paths(d[E->get()]);
+ }
+ } break;
+ }
+
+}
+
+void Object::clear_internal_resource_paths() {
+
+ List<PropertyInfo> pinfo;
+
+ get_property_list(&pinfo);
+
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ _clear_internal_resource_paths(get(E->get().name));
+ }
+}
+
void Object::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_type"),&Object::get_type);
@@ -1414,6 +1541,7 @@ void Object::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set","property","value"),&Object::_set_bind);
ObjectTypeDB::bind_method(_MD("get","property"),&Object::_get_bind);
ObjectTypeDB::bind_method(_MD("get_property_list"),&Object::_get_property_list_bind);
+ ObjectTypeDB::bind_method(_MD("get_method_list"),&Object::_get_method_list_bind);
ObjectTypeDB::bind_method(_MD("notification","what"),&Object::notification,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_instance_ID"),&Object::get_instance_ID);
@@ -1431,6 +1559,7 @@ void Object::_bind_methods() {
// ObjectTypeDB::bind_method(_MD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("add_user_signal","signal","arguments"),&Object::_add_user_signal,DEFVAL(Array()));
+ ObjectTypeDB::bind_method(_MD("has_user_signal","signal"),&Object::_has_user_signal);
// ObjectTypeDB::bind_method(_MD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array()));
@@ -1495,6 +1624,10 @@ void Object::_bind_methods() {
ObjectTypeDB::bind_method(_MD("XL_MESSAGE","message"),&Object::XL_MESSAGE);
ObjectTypeDB::bind_method(_MD("tr","message"),&Object::tr);
+ ObjectTypeDB::bind_method(_MD("is_queued_for_deletion"),&Object::is_queued_for_deletion);
+
+ ObjectTypeDB::add_virtual_method("Object",MethodInfo("free"),false);
+
ADD_SIGNAL( MethodInfo("script_changed"));
BIND_VMETHOD( MethodInfo("_notification",PropertyInfo(Variant::INT,"what")) );
@@ -1558,6 +1691,10 @@ void Object::get_translatable_strings(List<String> *p_strings) const {
}
+bool Object::is_queued_for_deletion() const {
+ return _is_queued_for_deletion;
+}
+
#ifdef TOOLS_ENABLED
void Object::set_edited(bool p_edited) {
@@ -1573,12 +1710,13 @@ bool Object::is_edited() const {
Object::Object() {
-
+ _type_ptr=NULL;
_block_signals=false;
_predelete_ok=0;
_instance_ID=0;
_instance_ID = ObjectDB::add_instance(this);
_can_translate=true;
+ _is_queued_for_deletion=false;
script_instance=NULL;
#ifdef TOOLS_ENABLED
@@ -1711,8 +1849,20 @@ void ObjectDB::cleanup() {
GLOBAL_LOCK_FUNCTION;
if (instances.size()) {
-
+
WARN_PRINT("ObjectDB Instances still exist!");
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ const uint32_t *K=NULL;
+ while((K=instances.next(K))) {
+
+ String node_name;
+ if (instances[*K]->is_type("Node"))
+ node_name=" - Node Name: "+String(instances[*K]->call("get_name"));
+ if (instances[*K]->is_type("Resoucre"))
+ node_name=" - Resource Name: "+String(instances[*K]->call("get_name"))+" Path: "+String(instances[*K]->call("get_path"));
+ print_line("Leaked Instance: "+String(instances[*K]->get_type())+":"+itos(*K)+node_name);
+ }
+ }
}
instances.clear();
instance_checks.clear();
diff --git a/core/object.h b/core/object.h
index 97ca50cb1a..981a83958c 100644
--- a/core/object.h
+++ b/core/object.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -49,20 +49,21 @@
enum PropertyHint {
PROPERTY_HINT_NONE, ///< no hint provided.
- PROPERTY_HINT_RANGE, ///< hint_text = "min,max,step"
+ PROPERTY_HINT_RANGE, ///< hint_text = "min,max,step,slider; //slider is optional"
PROPERTY_HINT_EXP_RANGE, ///< hint_text = "min,max,step", exponential edit
PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
PROPERTY_HINT_EXP_EASING, /// exponential easing funciton (Math::ease)
PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
+ PROPERTY_HINT_SPRITE_FRAME,
PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
PROPERTY_HINT_ALL_FLAGS,
- PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
+ PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_DIR, ///< a directort path must be passed
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed
PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
- PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
+ PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS,
@@ -70,7 +71,7 @@ enum PropertyHint {
};
enum PropertyUsageFlags {
-
+
PROPERTY_USAGE_STORAGE=1,
PROPERTY_USAGE_EDITOR=2,
PROPERTY_USAGE_NETWORK=4,
@@ -81,7 +82,8 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_BUNDLE=128, //used for optimized bundles
PROPERTY_USAGE_CATEGORY=256,
PROPERTY_USAGE_STORE_IF_NONZERO=512, //only store if nonzero
- PROPERTY_USAGE_NO_INSTANCE_STATE=1024,
+ PROPERTY_USAGE_STORE_IF_NONONE=1024, //only store if false
+ PROPERTY_USAGE_NO_INSTANCE_STATE=2048,
PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED,
@@ -96,21 +98,26 @@ enum PropertyUsageFlags {
#define ADD_PROPERTYI( m_property, m_setter, m_getter, m_index ) ObjectTypeDB::add_property( get_type_static(), m_property, m_setter, m_getter, m_index )
#define ADD_PROPERTYNZ( m_property, m_setter, m_getter ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter )
#define ADD_PROPERTYINZ( m_property, m_setter, m_getter, m_index ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter, m_index )
+#define ADD_PROPERTYNO( m_property, m_setter, m_getter ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter )
+#define ADD_PROPERTYINO( m_property, m_setter, m_getter, m_index ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter, m_index )
struct PropertyInfo {
-
- Variant::Type type;
+
+ Variant::Type type;
String name;
PropertyHint hint;
- String hint_string;
+ String hint_string;
uint32_t usage;
_FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const { PropertyInfo pi=*this; pi.usage|=p_fl; return pi; }
-
+
PropertyInfo() { type=Variant::NIL; hint=PROPERTY_HINT_NONE; usage = PROPERTY_USAGE_DEFAULT; }
PropertyInfo( Variant::Type p_type, const String p_name, PropertyHint p_hint=PROPERTY_HINT_NONE, const String& p_hint_string="",uint32_t p_usage=PROPERTY_USAGE_DEFAULT) {
type=p_type; name=p_name; hint=p_hint; hint_string=p_hint_string; usage=p_usage;
}
+ bool operator<(const PropertyInfo& p_info) const {
+ return name<p_info.name;
+ }
};
@@ -118,23 +125,23 @@ struct PropertyInfo {
Array convert_property_list(const List<PropertyInfo> * p_list);
struct MethodInfo {
-
+
String name;
List<PropertyInfo> arguments;
Vector<Variant> default_arguments;
PropertyInfo return_val;
uint32_t flags;
int id;
-
+
inline bool operator<(const MethodInfo& p_method) const { return id==p_method.id?(name < p_method.name):(id<p_method.id); }
-
+
MethodInfo();
MethodInfo(const String& p_name);
MethodInfo(const String& p_name, const PropertyInfo& p_param1);
MethodInfo(const String& p_name, const PropertyInfo& p_param1,const PropertyInfo& p_param2);
MethodInfo(const String& p_name, const PropertyInfo& p_param1,const PropertyInfo& p_param2,const PropertyInfo& p_param3);
MethodInfo(const String& p_name, const PropertyInfo& p_param1,const PropertyInfo& p_param2,const PropertyInfo& p_param3,const PropertyInfo& p_param4);
- MethodInfo(const String& p_name, const PropertyInfo& p_param1,const PropertyInfo& p_param2,const PropertyInfo& p_param3,const PropertyInfo& p_param4,const PropertyInfo& p_param5);
+ MethodInfo(const String& p_name, const PropertyInfo& p_param1,const PropertyInfo& p_param2,const PropertyInfo& p_param3,const PropertyInfo& p_param4,const PropertyInfo& p_param5);
MethodInfo(Variant::Type ret);
MethodInfo(Variant::Type ret,const String& p_name);
MethodInfo(Variant::Type ret,const String& p_name, const PropertyInfo& p_param1);
@@ -151,7 +158,7 @@ struct MethodInfo {
//return NULL;
/*
- the following is an uncomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
+ the following is an uncomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
*/
#define REVERSE_GET_PROPERTY_LIST \
@@ -175,10 +182,10 @@ public:\
virtual String get_type() const { \
return String(#m_type);\
}\
-virtual StringName get_type_name() const { \
+virtual const StringName* _get_type_namev() const { \
if (!_type_name)\
_type_name=get_type_static();\
- return _type_name;\
+ return &_type_name;\
}\
static _FORCE_INLINE_ void* get_type_ptr_static() { \
static int ptr;\
@@ -307,7 +314,7 @@ private:
class ScriptInstance;
typedef uint32_t ObjectID;
-class Object {
+class Object {
public:
enum ConnectFlags {
@@ -384,8 +391,11 @@ friend void postinitialize_handler(Object*);
ScriptInstance *script_instance;
RefPtr script;
Dictionary metadata;
+ mutable StringName _type_name;
+ mutable const StringName* _type_ptr;
void _add_user_signal(const String& p_name, const Array& p_pargs=Array());
+ bool _has_user_signal(const StringName& p_name) const;
Variant _emit_signal(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
Array _get_signal_list() const;
Array _get_signal_connection_list(const String& p_signal) const;
@@ -394,8 +404,7 @@ friend void postinitialize_handler(Object*);
void property_list_changed_notify();
-protected:
-
+protected:
virtual bool _use_builtin_script() const { return false; }
virtual void _initialize_typev() { initialize_type(); }
@@ -403,14 +412,14 @@ protected:
virtual bool _getv(const StringName& p_name,Variant &r_property) const { return false; };
virtual void _get_property_listv(List<PropertyInfo> *p_list,bool p_reversed) const {};
virtual void _notificationv(int p_notification,bool p_reversed) {};
-
+
static String _get_category() { return ""; }
static void _bind_methods();
bool _set(const StringName& p_name,const Variant &p_property) { return false; };
bool _get(const StringName& p_name,Variant &r_property) const { return false; };
void _get_property_list(List<PropertyInfo> *p_list) const {};
void _notification(int p_notification) {};
-
+
_FORCE_INLINE_ static void (*_get_bind_methods())() {
return &Object::_bind_methods;
}
@@ -422,13 +431,13 @@ protected:
}
_FORCE_INLINE_ void (Object::* (_get_get_property_list() const))(List<PropertyInfo> *p_list) const{
return &Object::_get_property_list;
- }
+ }
_FORCE_INLINE_ void (Object::* (_get_notification() const))(int){
return &Object::_notification;
- }
+ }
static void get_valid_parents_static(List<String> *p_parents);
static void _get_valid_parents_static(List<String> *p_parents);
-
+
void cancel_delete();
@@ -441,10 +450,17 @@ protected:
Variant _call_deferred_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
-
+ virtual const StringName* _get_type_namev() const {
+ if (!_type_name)
+ _type_name=get_type_static();
+ return &_type_name;
+ }
DVector<String> _get_meta_list_bind() const;
Array _get_property_list_bind() const;
+ Array _get_method_list_bind() const;
+
+ void _clear_internal_resource_paths(const Variant &p_var);
public: //should be protected, but bug in clang++
static void initialize_type();
@@ -469,7 +485,7 @@ public:
void add_change_receptor( Object *p_receptor );
void remove_change_receptor( Object *p_receptor );
-
+
template<class T>
T *cast_to() {
@@ -484,7 +500,7 @@ public:
return NULL;
#endif
}
-
+
template<class T>
const T *cast_to() const {
@@ -501,11 +517,11 @@ public:
}
enum {
-
+
NOTIFICATION_POSTINITIALIZE=0,
NOTIFICATION_PREDELETE=1
};
-
+
/* TYPE API */
static void get_inheritance_list_static(List<String>* p_inheritance_list) { p_inheritance_list->push_back("Object"); }
@@ -516,12 +532,20 @@ public:
virtual String get_type() const { return "Object"; }
virtual String get_save_type() const { return get_type(); } //type stored when saving
- virtual StringName get_type_name() const { return StringName("Object"); }
+
+
+
virtual bool is_type(const String& p_type) const { return (p_type=="Object"); }
virtual bool is_type_ptr(void *p_ptr) const { return get_type_ptr_static()==p_ptr; }
+ _FORCE_INLINE_ const StringName& get_type_name() const {
+ if (!_type_ptr) {
+ return *_get_type_namev();
+ } else {
+ return *_type_ptr;
+ }
+ }
-
/* IAPI */
// void set(const String& p_name, const Variant& p_value);
// Variant get(const String& p_name) const;
@@ -530,7 +554,7 @@ public:
Variant get(const StringName& p_name, bool *r_valid=NULL) const;
void get_property_list(List<PropertyInfo> *p_list,bool p_reversed=false) const;
-
+
bool has_method(const StringName& p_method) const;
void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName& p_method,const Array& p_args);
@@ -540,14 +564,14 @@ public:
Variant call(const StringName& p_name, VARIANT_ARG_LIST); // C++ helper
void call_multilevel(const StringName& p_name, VARIANT_ARG_LIST); // C++ helper
- void notification(int p_notification,bool p_reversed=false);
+ void notification(int p_notification,bool p_reversed=false);
//used mainly by script, get and set all INCLUDING string
virtual Variant getvar(const Variant& p_key, bool *r_valid=NULL) const;
virtual void setvar(const Variant& p_key, const Variant& p_value,bool *r_valid=NULL);
/* SCRIPT */
-
+
void set_script(const RefPtr& p_script);
RefPtr get_script() const;
@@ -571,6 +595,7 @@ public:
void emit_signal(const StringName& p_name,VARIANT_ARG_LIST);
void get_signal_list(List<MethodInfo> *p_signals ) const;
void get_signal_connection_list(const StringName& p_signal,List<Connection> *p_connections) const;
+ void get_all_signal_connections(List<Connection> *p_connections) const;
Error connect(const StringName& p_signal, Object *p_to_object, const StringName& p_to_method,const Vector<Variant>& p_binds=Vector<Variant>(),uint32_t p_flags=0);
void disconnect(const StringName& p_signal, Object *p_to_object, const StringName& p_to_method);
@@ -588,9 +613,15 @@ public:
StringName XL_MESSAGE(const StringName& p_message) const; //translate message (internationalization)
StringName tr(const StringName& p_message) const; //translate message (alternative)
+ bool _is_queued_for_deletion; // set to true by SceneTree::queue_delete()
+ bool is_queued_for_deletion() const;
+
_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate=p_enable; }
_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
- Object();
+
+ void clear_internal_resource_paths();
+
+ Object();
virtual ~Object();
};
@@ -618,13 +649,13 @@ class ObjectDB {
static HashMap<Object*,ObjectID,ObjectPtrHash> instance_checks;
static uint32_t instance_counter;
-friend class Object;
+friend class Object;
friend void unregister_core_types();
static void cleanup();
static uint32_t add_instance(Object *p_object);
static void remove_instance(Object *p_object);
-public:
+public:
typedef void (*DebugFunc)(Object *p_obj);
@@ -642,6 +673,8 @@ public:
#endif
+
+
};
//needed by macros
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index 62244cbd4f..a64b3d2715 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -191,6 +191,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
HashMap<StringName,ObjectTypeDB::TypeInfo,StringNameHasher> ObjectTypeDB::types;
HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::resource_base_extensions;
+HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::compat_types;
ObjectTypeDB::TypeInfo::TypeInfo() {
@@ -204,7 +205,7 @@ ObjectTypeDB::TypeInfo::~TypeInfo() {
}
-bool ObjectTypeDB::is_type(const String &p_type,const String& p_inherits) {
+bool ObjectTypeDB::is_type(const StringName &p_type,const StringName& p_inherits) {
OBJTYPE_LOCK;
@@ -219,7 +220,7 @@ bool ObjectTypeDB::is_type(const String &p_type,const String& p_inherits) {
return false;
}
-void ObjectTypeDB::get_type_list( List<String> *p_types) {
+void ObjectTypeDB::get_type_list( List<StringName> *p_types) {
OBJTYPE_LOCK;
@@ -234,7 +235,7 @@ void ObjectTypeDB::get_type_list( List<String> *p_types) {
}
-void ObjectTypeDB::get_inheriters_from( const String& p_type,List<String> *p_types) {
+void ObjectTypeDB::get_inheriters_from( const StringName& p_type,List<StringName> *p_types) {
OBJTYPE_LOCK;
@@ -248,7 +249,7 @@ void ObjectTypeDB::get_inheriters_from( const String& p_type,List<String> *p_typ
}
-String ObjectTypeDB::type_inherits_from(const String& p_type) {
+StringName ObjectTypeDB::type_inherits_from(const StringName& p_type) {
OBJTYPE_LOCK;
@@ -257,18 +258,28 @@ String ObjectTypeDB::type_inherits_from(const String& p_type) {
return ti->inherits;
}
-bool ObjectTypeDB::type_exists(const String &p_type) {
+bool ObjectTypeDB::type_exists(const StringName &p_type) {
OBJTYPE_LOCK;
return types.has(p_type);
}
-Object *ObjectTypeDB::instance(const String &p_type) {
+void ObjectTypeDB::add_compatibility_type(const StringName& p_type,const StringName& p_fallback) {
+
+ compat_types[p_type]=p_fallback;
+}
+
+Object *ObjectTypeDB::instance(const StringName &p_type) {
TypeInfo *ti;
{
OBJTYPE_LOCK;
ti=types.getptr(p_type);
+ if (!ti || ti->disabled || !ti->creation_func) {
+ if (compat_types.has(p_type)) {
+ ti=types.getptr(compat_types[p_type]);
+ }
+ }
ERR_FAIL_COND_V(!ti,NULL);
ERR_FAIL_COND_V(ti->disabled,NULL);
ERR_FAIL_COND_V(!ti->creation_func,NULL);
@@ -276,7 +287,7 @@ Object *ObjectTypeDB::instance(const String &p_type) {
return ti->creation_func();
}
-bool ObjectTypeDB::can_instance(const String &p_type) {
+bool ObjectTypeDB::can_instance(const StringName &p_type) {
OBJTYPE_LOCK;
@@ -639,7 +650,13 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c
Variant index=psg->index;
const Variant* arg[2]={&index,&p_value};
Variant::CallError ce;
- p_object->call(psg->setter,arg,2,ce);
+// p_object->call(psg->setter,arg,2,ce);
+ if (psg->_setptr) {
+ psg->_setptr->call(p_object,arg,2,ce);
+ } else {
+ p_object->call(psg->setter,arg,2,ce);
+ }
+
} else {
const Variant* arg[1]={&p_value};
@@ -729,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;
@@ -793,24 +829,38 @@ else goto set_defvals;
}
-void ObjectTypeDB::add_virtual_method(const StringName& p_type,const MethodInfo& p_method ) {
+void ObjectTypeDB::add_virtual_method(const StringName& p_type, const MethodInfo& p_method , bool p_virtual) {
ERR_FAIL_COND(!types.has(p_type));
#ifdef DEBUG_METHODS_ENABLED
MethodInfo mi=p_method;
- mi.flags|=METHOD_FLAG_VIRTUAL;
+ if (p_virtual)
+ mi.flags|=METHOD_FLAG_VIRTUAL;
types[p_type].virtual_methods.push_back(mi);
#endif
}
-void ObjectTypeDB::get_virtual_methods(const StringName& p_type,List<MethodInfo> * p_methods ) {
+void ObjectTypeDB::get_virtual_methods(const StringName& p_type, List<MethodInfo> * p_methods , bool p_no_inheritance) {
ERR_FAIL_COND(!types.has(p_type));
#ifdef DEBUG_METHODS_ENABLED
- *p_methods=types[p_type].virtual_methods;
+
+ TypeInfo *type=types.getptr(p_type);
+ TypeInfo *check=type;
+ while(check) {
+
+ for(List<MethodInfo>::Element *E=check->virtual_methods.front();E;E=E->next()) {
+ p_methods->push_back(E->get());
+ }
+
+ if (p_no_inheritance)
+ return;
+ check=check->inherits_ptr;
+ }
+
#endif
}
@@ -823,8 +873,15 @@ void ObjectTypeDB::set_type_enabled(StringName p_type,bool p_enable) {
bool ObjectTypeDB::is_type_enabled(StringName p_type) {
- ERR_FAIL_COND_V(!types.has(p_type),false);
- return !types[p_type].disabled;
+ TypeInfo *ti=types.getptr(p_type);
+ if (!ti || !ti->creation_func) {
+ if (compat_types.has(p_type)) {
+ ti=types.getptr(compat_types[p_type]);
+ }
+ }
+
+ ERR_FAIL_COND_V(!ti,false);
+ return !ti->disabled;
}
StringName ObjectTypeDB::get_category(const StringName& p_node) {
@@ -901,6 +958,7 @@ void ObjectTypeDB::cleanup() {
}
types.clear();
resource_base_extensions.clear();
+ compat_types.clear();
}
//
diff --git a/core/object_type_db.h b/core/object_type_db.h
index ae0644f9b3..bfa0f921e5 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -151,6 +151,7 @@ class ObjectTypeDB {
static Mutex *lock;
static HashMap<StringName,TypeInfo,StringNameHasher> types;
static HashMap<StringName,StringName,StringNameHasher> resource_base_extensions;
+ static HashMap<StringName,StringName,StringNameHasher> compat_types;
#ifdef DEBUG_METHODS_ENABLED
static MethodBind* bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
@@ -227,13 +228,13 @@ public:
T::register_custom_data_to_otdb();
}
- static void get_type_list( List<String> *p_types);
- static void get_inheriters_from( const String& p_type,List<String> *p_types);
- static String type_inherits_from(const String& p_type);
- static bool type_exists(const String &p_type);
- static bool is_type(const String &p_type,const String& p_inherits);
- static bool can_instance(const String &p_type);
- static Object *instance(const String &p_type);
+ static void get_type_list( List<StringName> *p_types);
+ static void get_inheriters_from( const StringName& p_type,List<StringName> *p_types);
+ static StringName type_inherits_from(const StringName& p_type);
+ static bool type_exists(const StringName &p_type);
+ static bool is_type(const StringName &p_type,const StringName& p_inherits);
+ static bool can_instance(const StringName &p_type);
+ static Object *instance(const StringName &p_type);
#if 0
template<class N, class M>
@@ -467,14 +468,16 @@ public:
static void get_method_list(StringName p_type,List<MethodInfo> *p_methods,bool p_no_inheritance=false);
static MethodBind *get_method(StringName p_type, StringName p_name);
- static void add_virtual_method(const StringName& p_type,const MethodInfo& p_method );
- static void get_virtual_methods(const StringName& p_type,List<MethodInfo> * p_methods );
+ static void add_virtual_method(const StringName& p_type,const MethodInfo& p_method,bool p_virtual=true );
+ static void get_virtual_methods(const StringName& p_type,List<MethodInfo> * p_methods,bool p_no_inheritance=false );
static void bind_integer_constant(const StringName& p_type, const StringName &p_name, int p_constant);
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);
@@ -482,6 +485,7 @@ public:
static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName& p_type,List<String> *p_extensions);
+ static void add_compatibility_type(const StringName& p_type,const StringName& p_fallback);
static void init();
static void cleanup();
};
diff --git a/core/os/SCsub b/core/os/SCsub
index c6ba1fa537..7b4a6acbc0 100644
--- a/core/os/SCsub
+++ b/core/os/SCsub
@@ -3,5 +3,3 @@ Import('env')
env.add_source_files(env.core_sources,"*.cpp")
Export('env')
-
-
diff --git a/core/os/copymem.cpp b/core/os/copymem.cpp
index 4a36b6f6d1..54baf1e232 100644
--- a/core/os/copymem.cpp
+++ b/core/os/copymem.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/copymem.h b/core/os/copymem.h
index 09e8c6903e..a5d640edbf 100644
--- a/core/os/copymem.h
+++ b/core/os/copymem.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 53fe792c46..d0baae5872 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,6 +56,17 @@ String DirAccess::_get_root_string() const {
return "";
}
+int DirAccess::get_current_drive() {
+
+ String path = get_current_dir().to_lower();
+ for(int i=0;i<get_drive_count();i++) {
+ String d = get_drive(i).to_lower();
+ if (path.begins_with(d))
+ return i;
+ }
+
+ return 0;
+}
static Error _erase_recursive(DirAccess *da) {
@@ -399,6 +410,15 @@ Error DirAccess::copy(String p_from,String p_to) {
return err;
}
+bool DirAccess::exists(String p_dir) {
+
+ DirAccess* da = DirAccess::create_for_path(p_dir);
+ bool valid = da->change_dir(p_dir)==OK;
+ memdelete(da);
+ return valid;
+
+}
+
DirAccess::DirAccess(){
_access_type=ACCESS_FILESYSTEM;
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index d8672218bd..8bacc96c60 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -78,11 +78,13 @@ public:
virtual String get_next(bool* p_is_dir); // compatibility
virtual String get_next()=0;
virtual bool current_is_dir() const=0;
+ virtual bool current_is_hidden() const=0;
virtual void list_dir_end()=0; ///<
virtual int get_drive_count()=0;
virtual String get_drive(int p_drive)=0;
+ virtual int get_current_drive();
virtual Error change_dir(String p_dir)=0; ///< can be relative or absolute, return false on success
virtual String get_current_dir()=0; ///< return current dir location
@@ -92,7 +94,7 @@ public:
virtual bool file_exists(String p_file)=0;
virtual bool dir_exists(String p_dir)=0;
-
+ static bool exists(String p_dir);
virtual size_t get_space_left()=0;
virtual Error copy(String p_from,String p_to);
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index ffa0cad8e4..ef7efd27e1 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 793e971a4c..8e34013796 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 4151c1b5a8..15872d02fd 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
#include "input.h"
#include "input_map.h"
#include "os/os.h"
+#include "globals.h"
Input *Input::singleton=NULL;
Input *Input::get_singleton() {
@@ -55,12 +56,15 @@ void Input::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_joy_axis","device","axis"),&Input::get_joy_axis);
ObjectTypeDB::bind_method(_MD("get_joy_name","device"),&Input::get_joy_name);
ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer);
- ObjectTypeDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos);
+ //ObjectTypeDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos); - this is not the function you want
ObjectTypeDB::bind_method(_MD("get_mouse_speed"),&Input::get_mouse_speed);
ObjectTypeDB::bind_method(_MD("get_mouse_button_mask"),&Input::get_mouse_button_mask);
ObjectTypeDB::bind_method(_MD("set_mouse_mode","mode"),&Input::set_mouse_mode);
ObjectTypeDB::bind_method(_MD("get_mouse_mode"),&Input::get_mouse_mode);
ObjectTypeDB::bind_method(_MD("warp_mouse_pos","to"),&Input::warp_mouse_pos);
+ ObjectTypeDB::bind_method(_MD("action_press"),&Input::action_press);
+ ObjectTypeDB::bind_method(_MD("action_release"),&Input::action_release);
+ ObjectTypeDB::bind_method(_MD("set_custom_mouse_cursor","image:Texture","hotspot"),&Input::set_custom_mouse_cursor,DEFVAL(Vector2()));
BIND_CONSTANT( MOUSE_MODE_VISIBLE );
BIND_CONSTANT( MOUSE_MODE_HIDDEN );
@@ -69,274 +73,35 @@ void Input::_bind_methods() {
ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) );
}
-Input::Input() {
-
- singleton=this;
-}
-
-
-//////////////////////////////////////////////////////////
-
-
-void InputDefault::SpeedTrack::update(const Vector2& p_delta_p) {
-
- uint64_t tick = OS::get_singleton()->get_ticks_usec();
- uint32_t tdiff = tick-last_tick;
- float delta_t = tdiff / 1000000.0;
- last_tick=tick;
-
-
- accum+=p_delta_p;
- accum_t+=delta_t;
-
- if (accum_t>max_ref_frame*10)
- accum_t=max_ref_frame*10;
-
- while( accum_t>=min_ref_frame ) {
-
- float slice_t = min_ref_frame / accum_t;
- Vector2 slice = accum*slice_t;
- accum=accum-slice;
- accum_t-=min_ref_frame;
-
- speed=(slice/min_ref_frame).linear_interpolate(speed,min_ref_frame/max_ref_frame);
- }
-
-
-
-}
-
-void InputDefault::SpeedTrack::reset() {
- last_tick = OS::get_singleton()->get_ticks_usec();
- speed=Vector2();
- accum_t=0;
-}
-
-InputDefault::SpeedTrack::SpeedTrack() {
-
- min_ref_frame=0.1;
- max_ref_frame=0.3;
- reset();
-}
-
-bool InputDefault::is_key_pressed(int p_scancode) {
-
- _THREAD_SAFE_METHOD_
- return keys_pressed.has(p_scancode);
-}
-
-bool InputDefault::is_mouse_button_pressed(int p_button) {
-
- _THREAD_SAFE_METHOD_
- return (mouse_button_mask&(1<<p_button))!=0;
-}
-
-
-static int _combine_device(int p_value,int p_device) {
-
- return p_value|(p_device<<20);
-}
-
-bool InputDefault::is_joy_button_pressed(int p_device, int p_button) {
-
- _THREAD_SAFE_METHOD_
- return joy_buttons_pressed.has(_combine_device(p_button,p_device));
-}
-
-bool InputDefault::is_action_pressed(const StringName& p_action) {
-
- if (custom_action_press.has(p_action))
- return true; //simpler
-
- const List<InputEvent> *alist = InputMap::get_singleton()->get_action_list(p_action);
- if (!alist)
- return NULL;
+void Input::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
+#ifdef TOOLS_ENABLED
+ String pf=p_function;
+ if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release")) {
- for (const List<InputEvent>::Element *E=alist->front();E;E=E->next()) {
+ List<PropertyInfo> pinfo;
+ Globals::get_singleton()->get_property_list(&pinfo);
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+ const PropertyInfo &pi=E->get();
- int device=E->get().device;
+ if (!pi.name.begins_with("input/"))
+ continue;
- switch(E->get().type) {
+ String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
+ r_options->push_back("\""+name+"\"");
- case InputEvent::KEY: {
-
- const InputEventKey &iek=E->get().key;
- if ((keys_pressed.has(iek.scancode)))
- return true;
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &iemb=E->get().mouse_button;
- if(mouse_button_mask&(1<<iemb.button_index))
- return true;
- } break;
- case InputEvent::JOYSTICK_BUTTON: {
-
- const InputEventJoystickButton &iejb=E->get().joy_button;
- int c = _combine_device(iejb.button_index,device);
- if (joy_buttons_pressed.has(c))
- return true;
- } break;
}
}
+#endif
- return false;
-}
-
-float InputDefault::get_joy_axis(int p_device,int p_axis) {
-
- _THREAD_SAFE_METHOD_
- int c = _combine_device(p_axis,p_device);
- if (joy_axis.has(c)) {
- return joy_axis[c];
- } else {
- return 0;
- }
}
-String InputDefault::get_joy_name(int p_idx) {
-
- _THREAD_SAFE_METHOD_
- return joy_names[p_idx];
-};
-
-void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_name) {
-
- _THREAD_SAFE_METHOD_
- joy_names[p_idx] = p_connected ? p_name : "";
-
- emit_signal("joy_connection_changed", p_idx, p_connected);
-};
-
-Vector3 InputDefault::get_accelerometer() {
-
- _THREAD_SAFE_METHOD_
- return accelerometer;
-}
-
-void InputDefault::parse_input_event(const InputEvent& p_event) {
-
- _THREAD_SAFE_METHOD_
- switch(p_event.type) {
-
- case InputEvent::KEY: {
-
- if (p_event.key.echo)
- break;
- if (p_event.key.scancode==0)
- break;
-
- // print_line(p_event);
-
- if (p_event.key.pressed)
- keys_pressed.insert(p_event.key.scancode);
- else
- keys_pressed.erase(p_event.key.scancode);
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- if (p_event.mouse_button.doubleclick)
- break;
-
- if (p_event.mouse_button.pressed)
- mouse_button_mask|=(1<<p_event.mouse_button.button_index);
- else
- mouse_button_mask&=~(1<<p_event.mouse_button.button_index);
- } break;
- case InputEvent::JOYSTICK_BUTTON: {
-
- int c = _combine_device(p_event.joy_button.button_index,p_event.device);
-
- if (p_event.joy_button.pressed)
- joy_buttons_pressed.insert(c);
- else
- joy_buttons_pressed.erase(c);
- } break;
- case InputEvent::JOYSTICK_MOTION: {
- set_joy_axis(p_event.device, p_event.joy_motion.axis, p_event.joy_motion.axis_value);
- } break;
-
- }
-
- if (main_loop)
- main_loop->input_event(p_event);
-
-}
-
-void InputDefault::set_joy_axis(int p_device,int p_axis,float p_value) {
-
- _THREAD_SAFE_METHOD_
- int c = _combine_device(p_axis,p_device);
- joy_axis[c]=p_value;
-}
-
-void InputDefault::set_accelerometer(const Vector3& p_accel) {
-
- _THREAD_SAFE_METHOD_
-
- accelerometer=p_accel;
-
-}
-
-void InputDefault::set_main_loop(MainLoop *p_main_loop) {
- main_loop=p_main_loop;
-
-}
-
-void InputDefault::set_mouse_pos(const Point2& p_posf) {
-
- mouse_speed_track.update(p_posf-mouse_pos);
- mouse_pos=p_posf;
-}
-
-Point2 InputDefault::get_mouse_pos() const {
-
- return mouse_pos;
-}
-Point2 InputDefault::get_mouse_speed() const {
-
- return mouse_speed_track.speed;
-}
-
-int InputDefault::get_mouse_button_mask() const {
-
- return OS::get_singleton()->get_mouse_button_state();
-}
-
-void InputDefault::warp_mouse_pos(const Vector2& p_to) {
-
- OS::get_singleton()->warp_mouse_pos(p_to);
-}
-
-
-void InputDefault::iteration(float p_step) {
-
-
-}
-
-void InputDefault::action_press(const StringName& p_action) {
-
- if (custom_action_press.has(p_action)) {
+Input::Input() {
- custom_action_press[p_action]++;
- } else {
- custom_action_press[p_action]=1;
- }
+ singleton=this;
}
-void InputDefault::action_release(const StringName& p_action){
-
- ERR_FAIL_COND(!custom_action_press.has(p_action));
- custom_action_press[p_action]--;
- if (custom_action_press[p_action]==0) {
- custom_action_press.erase(p_action);
- }
-}
-InputDefault::InputDefault() {
+//////////////////////////////////////////////////////////
- mouse_button_mask=0;
- main_loop=NULL;
-}
diff --git a/core/os/input.h b/core/os/input.h
index 1cb0f35d96..8aa0e6b18a 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -76,77 +76,17 @@ public:
virtual void action_press(const StringName& p_action)=0;
virtual void action_release(const StringName& p_action)=0;
+ void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
+
+ virtual bool is_emulating_touchscreen() const=0;
+
+ virtual void set_custom_mouse_cursor(const RES& p_cursor,const Vector2& p_hotspot=Vector2())=0;
+ virtual void set_mouse_in_window(bool p_in_window)=0;
Input();
};
VARIANT_ENUM_CAST(Input::MouseMode);
-class InputDefault : public Input {
-
- OBJ_TYPE( InputDefault, Input );
- _THREAD_SAFE_CLASS_
-
- int mouse_button_mask;
- Set<int> keys_pressed;
- Set<int> joy_buttons_pressed;
- Map<int,float> joy_axis;
- Map<StringName,int> custom_action_press;
- Map<int, String> joy_names;
- Vector3 accelerometer;
- Vector2 mouse_pos;
- MainLoop *main_loop;
-
- struct SpeedTrack {
-
- uint64_t last_tick;
- Vector2 speed;
- Vector2 accum;
- float accum_t;
- float min_ref_frame;
- float max_ref_frame;
-
- void update(const Vector2& p_delta_p);
- void reset();
- SpeedTrack();
- };
-
- SpeedTrack mouse_speed_track;
-
-public:
-
- virtual bool is_key_pressed(int p_scancode);
- virtual bool is_mouse_button_pressed(int p_button);
- virtual bool is_joy_button_pressed(int p_device, int p_button);
- virtual bool is_action_pressed(const StringName& p_action);
-
- virtual float get_joy_axis(int p_device,int p_axis);
- String get_joy_name(int p_idx);
- void joy_connection_changed(int p_idx, bool p_connected, String p_name);
-
- virtual Vector3 get_accelerometer();
-
- virtual Point2 get_mouse_pos() const;
- virtual Point2 get_mouse_speed() const;
- virtual int get_mouse_button_mask() const;
-
- virtual void warp_mouse_pos(const Vector2& p_to);
-
-
- void parse_input_event(const InputEvent& p_event);
- void set_accelerometer(const Vector3& p_accel);
- void set_joy_axis(int p_device,int p_axis,float p_value);
-
- void set_main_loop(MainLoop *main_loop);
- void set_mouse_pos(const Point2& p_posf);
-
- void action_press(const StringName& p_action);
- void action_release(const StringName& p_action);
-
- void iteration(float p_step);
-
- InputDefault();
-
-};
#endif // INPUT_H
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 27c7c10aef..2bd62927b0 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -173,6 +173,16 @@ bool InputEvent::is_action(const String& p_action) const {
return InputMap::get_singleton()->event_is_action(*this,p_action);
}
+bool InputEvent::is_action_pressed(const String& p_action) const {
+
+ return is_action(p_action) && is_pressed() && !is_echo();
+}
+
+bool InputEvent::is_action_released(const String& p_action) const {
+
+ return is_action(p_action) && !is_pressed();
+}
+
uint32_t InputEventKey::get_scancode_with_modifiers() const {
uint32_t sc=scancode;
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 218ff327d1..4bb122ebc1 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -287,6 +287,8 @@ struct InputEvent {
bool is_pressed() const;
bool is_action(const String& p_action) const;
+ bool is_action_pressed(const String& p_action) const;
+ bool is_action_released(const String& p_action) const;
bool is_echo() const;
void set_as_action(const String& p_action, bool p_pressed);
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index a4201c34ea..10e64c3961 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "keyboard.h"
-
+#include "os/os.h"
struct _KeyCodeText {
int code;
@@ -353,3 +353,106 @@ int find_keycode(const String& p_code) {
return 0;
}
+
+
+
+
+struct _KeyCodeReplace {
+ int from;
+ int to;
+};
+
+static const _KeyCodeReplace _keycode_replace_qwertz[]={
+{KEY_Y,KEY_Z},
+{KEY_Z,KEY_Y},
+{0,0}
+};
+
+static const _KeyCodeReplace _keycode_replace_azerty[]={
+{KEY_W,KEY_Z},
+{KEY_Z,KEY_W},
+{KEY_A,KEY_Q},
+{KEY_Q,KEY_A},
+{KEY_SEMICOLON,KEY_M},
+{KEY_M,KEY_SEMICOLON},
+{0,0}
+};
+
+static const _KeyCodeReplace _keycode_replace_qzerty[]={
+{KEY_W,KEY_Z},
+{KEY_Z,KEY_W},
+{KEY_SEMICOLON,KEY_M},
+{KEY_M,KEY_SEMICOLON},
+{0,0}
+};
+
+static const _KeyCodeReplace _keycode_replace_dvorak[]={
+{KEY_UNDERSCORE,KEY_BRACELEFT},
+{KEY_EQUAL,KEY_BRACERIGHT},
+{KEY_Q,KEY_APOSTROPHE},
+{KEY_W,KEY_COMMA},
+{KEY_E,KEY_PERIOD},
+{KEY_R,KEY_P},
+{KEY_T,KEY_Y},
+{KEY_Y,KEY_F},
+{KEY_U,KEY_G},
+{KEY_I,KEY_C},
+{KEY_O,KEY_R},
+{KEY_P,KEY_L},
+{KEY_BRACELEFT,KEY_SLASH},
+{KEY_BRACERIGHT,KEY_EQUAL},
+{KEY_A,KEY_A},
+{KEY_S,KEY_O},
+{KEY_D,KEY_E},
+{KEY_F,KEY_U},
+{KEY_G,KEY_I},
+{KEY_H,KEY_D},
+{KEY_J,KEY_H},
+{KEY_K,KEY_T},
+{KEY_L,KEY_N},
+{KEY_SEMICOLON,KEY_S},
+{KEY_APOSTROPHE,KEY_UNDERSCORE},
+{KEY_Z,KEY_SEMICOLON},
+{KEY_X,KEY_Q},
+{KEY_C,KEY_J},
+{KEY_V,KEY_K},
+{KEY_B,KEY_X},
+{KEY_N,KEY_B},
+{KEY_M,KEY_M},
+{KEY_COMMA,KEY_W},
+{KEY_PERIOD,KEY_V},
+{KEY_SLASH,KEY_Z},
+{0,0}
+};
+
+static const _KeyCodeReplace _keycode_replace_neo[]={
+{0,0}
+};
+
+
+int latin_keyboard_keycode_convert(int p_keycode) {
+
+ const _KeyCodeReplace *kcr=NULL;
+ switch(OS::get_singleton()->get_latin_keyboard_variant()) {
+
+ case OS::LATIN_KEYBOARD_QWERTY: return p_keycode; break;
+ case OS::LATIN_KEYBOARD_QWERTZ: kcr=_keycode_replace_qwertz; break;
+ case OS::LATIN_KEYBOARD_AZERTY: kcr=_keycode_replace_azerty; break;
+ case OS::LATIN_KEYBOARD_QZERTY: kcr=_keycode_replace_qzerty; break;
+ case OS::LATIN_KEYBOARD_DVORAK: kcr=_keycode_replace_dvorak; break;
+ case OS::LATIN_KEYBOARD_NEO: kcr=_keycode_replace_neo; break;
+ default: return p_keycode;
+ }
+
+ if (!kcr) {
+ return p_keycode;
+ }
+
+ while(kcr->from) {
+ if (kcr->from==p_keycode)
+ return kcr->to;
+ kcr++;
+ }
+
+ return p_keycode;
+}
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 18b56b5830..eaf656dd4d 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -328,5 +328,6 @@ enum KeyModifierMask {
String keycode_get_string(uint32_t p_code);
bool keycode_has_unicode(uint32_t p_unicode);
int find_keycode(const String& p_code);
+int latin_keyboard_keycode_convert(int p_keycode);
#endif
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index d01331a256..c37c281fb9 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,8 +31,22 @@
void MainLoop::_bind_methods() {
- ObjectTypeDB::bind_method("input_event",&MainLoop::input_event);
-
+ ObjectTypeDB::bind_method(_MD("input_event","ev"),&MainLoop::input_event);
+ ObjectTypeDB::bind_method(_MD("input_text","text"),&MainLoop::input_text);
+ ObjectTypeDB::bind_method(_MD("init"),&MainLoop::init);
+ ObjectTypeDB::bind_method(_MD("iteration","delta"),&MainLoop::iteration);
+ ObjectTypeDB::bind_method(_MD("idle","delta"),&MainLoop::idle);
+ ObjectTypeDB::bind_method(_MD("finish"),&MainLoop::finish);
+
+ BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) );
+ BIND_VMETHOD( MethodInfo("_input_text",PropertyInfo(Variant::STRING,"text")) );
+ BIND_VMETHOD( MethodInfo("_initialize") );
+ BIND_VMETHOD( MethodInfo("_iteration",PropertyInfo(Variant::REAL,"delta")) );
+ BIND_VMETHOD( MethodInfo("_idle",PropertyInfo(Variant::REAL,"delta")) );
+ BIND_VMETHOD( MethodInfo("_finalize") );
+
+ BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER);
+ BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
@@ -58,13 +72,15 @@ MainLoop::~MainLoop()
void MainLoop::input_text( const String& p_text ) {
+ if (get_script_instance())
+ get_script_instance()->call("_input_text",p_text);
}
void MainLoop::input_event( const InputEvent& p_event ) {
if (get_script_instance())
- get_script_instance()->call("input_event",p_event);
+ get_script_instance()->call("_input_event",p_event);
}
@@ -74,13 +90,13 @@ void MainLoop::init() {
set_script(init_script.get_ref_ptr());
if (get_script_instance())
- get_script_instance()->call("init");
+ get_script_instance()->call("_initialize");
}
bool MainLoop::iteration(float p_time) {
if (get_script_instance())
- return get_script_instance()->call("iteration",p_time);
+ return get_script_instance()->call("_iteration",p_time);
return false;
@@ -88,14 +104,14 @@ bool MainLoop::iteration(float p_time) {
bool MainLoop::idle(float p_time) {
if (get_script_instance())
- return get_script_instance()->call("idle",p_time);
+ return get_script_instance()->call("_idle",p_time);
return false;
}
void MainLoop::finish() {
if (get_script_instance()) {
- get_script_instance()->call("finish");
+ get_script_instance()->call("_finalize");
set_script(RefPtr()); //clear script
}
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 6eb5881175..c5d58120c5 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,6 +47,8 @@ protected:
public:
enum {
+ NOTIFICATION_WM_MOUSE_ENTER = 3,
+ NOTIFICATION_WM_MOUSE_EXIT = 4,
NOTIFICATION_WM_FOCUS_IN = 5,
NOTIFICATION_WM_FOCUS_OUT = 6,
NOTIFICATION_WM_QUIT_REQUEST = 7,
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index ca5bacf9cd..1d9ac4e302 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -112,13 +112,6 @@ size_t Memory::get_dynamic_mem_usage() {
return MemoryPoolDynamic::get_singleton()->get_total_usage();
}
-void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) {
-
- void *failptr=0;
- ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */
-
- return p_pointer;
-}
diff --git a/core/os/memory.h b/core/os/memory.h
index 6fc3d8f3eb..0a35c93fdb 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -236,11 +236,11 @@ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_de
#endif
-_FORCE_INLINE_ void postinitialize_handler(void *) {}
+_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
template<class T>
-_FORCE_INLINE_ T *_post_initialize(T *p_obj) {
+_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
postinitialize_handler(p_obj);
return p_obj;
@@ -249,19 +249,26 @@ _FORCE_INLINE_ T *_post_initialize(T *p_obj) {
#ifdef DEBUG_MEMORY_ENABLED
#define memnew(m_class) _post_initialize(new(__FILE__":"__STR(__LINE__)", memnew type: "__STR(m_class)) m_class)
-#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),__FILE__":"__STR(__LINE__)", type: "__STR(m_class)) m_class)
#else
#define memnew(m_class) _post_initialize(new("") m_class)
-#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),"") m_class)
#endif
+_ALWAYS_INLINE_ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) {
+// void *failptr=0;
+// ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */
+
+ return p_pointer;
+}
+
+
#define memnew_allocator(m_class,m_allocator) _post_initialize(new(m_allocator::alloc) m_class)
+#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),"") m_class)
-_FORCE_INLINE_ bool predelete_handler(void *) { return true; }
+_ALWAYS_INLINE_ bool predelete_handler(void *) { return true; }
template<class T>
void memdelete(T *p_class) {
diff --git a/core/os/memory_pool_dynamic.cpp b/core/os/memory_pool_dynamic.cpp
index 4df554f18d..d1c41aff84 100644
--- a/core/os/memory_pool_dynamic.cpp
+++ b/core/os/memory_pool_dynamic.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic.h b/core/os/memory_pool_dynamic.h
index ca517daf41..00999ee24d 100644
--- a/core/os/memory_pool_dynamic.h
+++ b/core/os/memory_pool_dynamic.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic_prealloc.cpp b/core/os/memory_pool_dynamic_prealloc.cpp
index c5823366c1..c7c25f32d1 100644
--- a/core/os/memory_pool_dynamic_prealloc.cpp
+++ b/core/os/memory_pool_dynamic_prealloc.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,91 +26,91 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "memory_pool_dynamic_prealloc.h"
-#include "os/memory.h"
-
-#include "print_string.h"
-MemoryPoolDynamicPrealloc::ID MemoryPoolDynamicPrealloc::alloc(size_t p_amount,const char* p_description) {
-
-
-// print_line("dynpool - allocating: "+itos(p_amount));
- ID id = pool_alloc->alloc(p_amount);
-// print_line("dynpool - free: "+itos(pool_alloc->get_free_mem()));
- return id;
-
-}
-
-void MemoryPoolDynamicPrealloc::free(ID p_id) {
-
- pool_alloc->free(p_id);
-}
-
-Error MemoryPoolDynamicPrealloc::realloc(ID p_id, size_t p_amount) {
-
- return pool_alloc->resize(p_id,p_amount);
-}
-
-bool MemoryPoolDynamicPrealloc::is_valid(ID p_id) {
-
- return true;
-}
-
-size_t MemoryPoolDynamicPrealloc::get_size(ID p_id) const {
-
- return pool_alloc->get_size(p_id);
-}
-
-const char* MemoryPoolDynamicPrealloc::get_description(ID p_id) const {
-
- return "";
-}
-
-Error MemoryPoolDynamicPrealloc::lock(ID p_id) {
-
-// print_line("lock: "+itos(p_id));
- return pool_alloc->lock(p_id);
-}
-
-void * MemoryPoolDynamicPrealloc::get(ID p_ID) {
-
-// print_line("get: "+itos(p_ID));
- return pool_alloc->get(p_ID);
-}
-
-Error MemoryPoolDynamicPrealloc::unlock(ID p_id) {
-
-// print_line("unlock: "+itos(p_id));
- pool_alloc->unlock(p_id);
- return OK;
-}
-
-bool MemoryPoolDynamicPrealloc::is_locked(ID p_id) const {
-
- return pool_alloc->is_locked(p_id);
-}
-
-
-size_t MemoryPoolDynamicPrealloc::get_available_mem() const {
-
- return pool_alloc->get_free_mem();
-}
-
-size_t MemoryPoolDynamicPrealloc::get_total_usage() const {
-
- return pool_alloc->get_used_mem();
-}
-
-
-
-MemoryPoolDynamicPrealloc::MemoryPoolDynamicPrealloc(void * p_mem,int p_size, int p_align, int p_max_entries) {
-
- pool_alloc = memnew( PoolAllocator(p_mem,p_size,p_align,true,p_max_entries));
-
-}
-
-MemoryPoolDynamicPrealloc::~MemoryPoolDynamicPrealloc() {
-
-
- memdelete( pool_alloc );
-}
-
+#include "memory_pool_dynamic_prealloc.h"
+#include "os/memory.h"
+
+#include "print_string.h"
+MemoryPoolDynamicPrealloc::ID MemoryPoolDynamicPrealloc::alloc(size_t p_amount,const char* p_description) {
+
+
+// print_line("dynpool - allocating: "+itos(p_amount));
+ ID id = pool_alloc->alloc(p_amount);
+// print_line("dynpool - free: "+itos(pool_alloc->get_free_mem()));
+ return id;
+
+}
+
+void MemoryPoolDynamicPrealloc::free(ID p_id) {
+
+ pool_alloc->free(p_id);
+}
+
+Error MemoryPoolDynamicPrealloc::realloc(ID p_id, size_t p_amount) {
+
+ return pool_alloc->resize(p_id,p_amount);
+}
+
+bool MemoryPoolDynamicPrealloc::is_valid(ID p_id) {
+
+ return true;
+}
+
+size_t MemoryPoolDynamicPrealloc::get_size(ID p_id) const {
+
+ return pool_alloc->get_size(p_id);
+}
+
+const char* MemoryPoolDynamicPrealloc::get_description(ID p_id) const {
+
+ return "";
+}
+
+Error MemoryPoolDynamicPrealloc::lock(ID p_id) {
+
+// print_line("lock: "+itos(p_id));
+ return pool_alloc->lock(p_id);
+}
+
+void * MemoryPoolDynamicPrealloc::get(ID p_ID) {
+
+// print_line("get: "+itos(p_ID));
+ return pool_alloc->get(p_ID);
+}
+
+Error MemoryPoolDynamicPrealloc::unlock(ID p_id) {
+
+// print_line("unlock: "+itos(p_id));
+ pool_alloc->unlock(p_id);
+ return OK;
+}
+
+bool MemoryPoolDynamicPrealloc::is_locked(ID p_id) const {
+
+ return pool_alloc->is_locked(p_id);
+}
+
+
+size_t MemoryPoolDynamicPrealloc::get_available_mem() const {
+
+ return pool_alloc->get_free_mem();
+}
+
+size_t MemoryPoolDynamicPrealloc::get_total_usage() const {
+
+ return pool_alloc->get_used_mem();
+}
+
+
+
+MemoryPoolDynamicPrealloc::MemoryPoolDynamicPrealloc(void * p_mem,int p_size, int p_align, int p_max_entries) {
+
+ pool_alloc = memnew( PoolAllocator(p_mem,p_size,p_align,true,p_max_entries));
+
+}
+
+MemoryPoolDynamicPrealloc::~MemoryPoolDynamicPrealloc() {
+
+
+ memdelete( pool_alloc );
+}
+
diff --git a/core/os/memory_pool_dynamic_prealloc.h b/core/os/memory_pool_dynamic_prealloc.h
index 698885561a..3523079bac 100644
--- a/core/os/memory_pool_dynamic_prealloc.h
+++ b/core/os/memory_pool_dynamic_prealloc.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,35 +26,35 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef MEMORY_POOL_DYNAMIC_PREALLOC_H
-#define MEMORY_POOL_DYNAMIC_PREALLOC_H
-
-#include "pool_allocator.h"
-#include "core/os/memory_pool_dynamic.h"
-
-class MemoryPoolDynamicPrealloc : public MemoryPoolDynamic {
-
- PoolAllocator *pool_alloc;
-
-public:
-
- virtual ID alloc(size_t p_amount,const char* p_description);
- virtual void free(ID p_id);
- virtual Error realloc(ID p_id, size_t p_amount);
- virtual bool is_valid(ID p_id);
- virtual size_t get_size(ID p_id) const;
- virtual const char* get_description(ID p_id) const;
-
- virtual Error lock(ID p_id);
- virtual void * get(ID p_ID);
- virtual Error unlock(ID p_id);
- virtual bool is_locked(ID p_id) const;
-
- virtual size_t get_available_mem() const;
- virtual size_t get_total_usage() const;
-
- MemoryPoolDynamicPrealloc(void * p_mem,int p_size, int p_align = 16, int p_max_entries=PoolAllocator::DEFAULT_MAX_ALLOCS);
- ~MemoryPoolDynamicPrealloc();
-};
-
-#endif // MEMORY_POOL_DYNAMIC_PREALLOC_H
+#ifndef MEMORY_POOL_DYNAMIC_PREALLOC_H
+#define MEMORY_POOL_DYNAMIC_PREALLOC_H
+
+#include "pool_allocator.h"
+#include "core/os/memory_pool_dynamic.h"
+
+class MemoryPoolDynamicPrealloc : public MemoryPoolDynamic {
+
+ PoolAllocator *pool_alloc;
+
+public:
+
+ virtual ID alloc(size_t p_amount,const char* p_description);
+ virtual void free(ID p_id);
+ virtual Error realloc(ID p_id, size_t p_amount);
+ virtual bool is_valid(ID p_id);
+ virtual size_t get_size(ID p_id) const;
+ virtual const char* get_description(ID p_id) const;
+
+ virtual Error lock(ID p_id);
+ virtual void * get(ID p_ID);
+ virtual Error unlock(ID p_id);
+ virtual bool is_locked(ID p_id) const;
+
+ virtual size_t get_available_mem() const;
+ virtual size_t get_total_usage() const;
+
+ MemoryPoolDynamicPrealloc(void * p_mem,int p_size, int p_align = 16, int p_max_entries=PoolAllocator::DEFAULT_MAX_ALLOCS);
+ ~MemoryPoolDynamicPrealloc();
+};
+
+#endif // MEMORY_POOL_DYNAMIC_PREALLOC_H
diff --git a/core/os/memory_pool_dynamic_static.cpp b/core/os/memory_pool_dynamic_static.cpp
index 93f94d7726..029ef450cd 100644
--- a/core/os/memory_pool_dynamic_static.cpp
+++ b/core/os/memory_pool_dynamic_static.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_dynamic_static.h b/core/os/memory_pool_dynamic_static.h
index d10cdb3d0a..a870f3070c 100644
--- a/core/os/memory_pool_dynamic_static.h
+++ b/core/os/memory_pool_dynamic_static.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_static.cpp b/core/os/memory_pool_static.cpp
index 9dd5baf4e4..d3617eac73 100644
--- a/core/os/memory_pool_static.cpp
+++ b/core/os/memory_pool_static.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/memory_pool_static.h b/core/os/memory_pool_static.h
index f2b372d03b..40bd1aaf0e 100644
--- a/core/os/memory_pool_static.h
+++ b/core/os/memory_pool_static.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp
index 03d423ae04..be984c080b 100644
--- a/core/os/mutex.cpp
+++ b/core/os/mutex.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/mutex.h b/core/os/mutex.h
index 241d70e232..ac6d36d635 100644
--- a/core/os/mutex.h
+++ b/core/os/mutex.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 081f7c1c5e..8caf95e4d1 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,7 +31,7 @@
#include <stdarg.h>
#include "dir_access.h"
#include "globals.h"
-
+#include "input.h"
OS* OS::singleton=NULL;
@@ -43,11 +43,16 @@ OS* OS::get_singleton() {
uint32_t OS::get_ticks_msec() const
{ return get_ticks_usec()/1000; }
+uint64_t OS::get_splash_tick_msec() const {
+ return _msec_splash;
+}
uint64_t OS::get_unix_time() const {
return 0;
};
-
+uint64_t OS::get_system_time_msec() const {
+ return 0;
+}
void OS::debug_break() {
// something
@@ -56,9 +61,16 @@ void OS::debug_break() {
void OS::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
+ const char* err_type;
+ switch(p_type) {
+ case ERR_ERROR: err_type="**ERROR**"; break;
+ case ERR_WARNING: err_type="**WARNING**"; break;
+ case ERR_SCRIPT: err_type="**SCRIPT ERROR**"; break;
+ }
+
if (p_rationale && *p_rationale)
- print("**ERROR**: %s\n ",p_rationale);
- print("**ERROR**: At: %s:%i:%s() - %s\n",p_file,p_line,p_function,p_code);
+ print("%s: %s\n ",err_type,p_rationale);
+ print("%s: At: %s:%i:%s() - %s\n",err_type,p_file,p_line,p_function,p_code);
}
void OS::print(const char* p_format, ...) {
@@ -358,7 +370,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 {
@@ -485,6 +497,11 @@ void OS::set_time_scale(float p_scale) {
_time_scale=p_scale;
}
+OS::LatinKeyboardVariant OS::get_latin_keyboard_variant() const {
+
+ return LATIN_KEYBOARD_QWERTY;
+}
+
float OS::get_time_scale() const {
return _time_scale;
@@ -506,6 +523,7 @@ OS::OS() {
_target_fps=0;
_render_thread_mode=RENDER_THREAD_SAFE;
_time_scale=1.0;
+ _pixel_snap=false;
Math::seed(1234567);
}
diff --git a/core/os/os.h b/core/os/os.h
index 805d6ac57d..e5338b4a02 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "vector.h"
#include "os/main_loop.h"
#include <stdarg.h>
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -50,12 +51,14 @@ class OS {
String _local_clipboard;
uint64_t frames_drawn;
uint32_t _frame_delay;
+ uint64_t _msec_splash;
bool _no_window;
int _exit_code;
int _orientation;
float _fps;
int _target_fps;
float _time_scale;
+ bool _pixel_snap;
char *last_error;
@@ -72,7 +75,7 @@ public:
bool fullscreen;
bool resizable;
float get_aspect() const { return (float)width/(float)height; }
- VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) { width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
+ VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) {width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
};
protected:
friend class Main;
@@ -148,7 +151,27 @@ public:
virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0)=0;
virtual VideoMode get_video_mode(int p_screen=0) const=0;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const=0;
-
+
+
+ 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) 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) {}
+ virtual Size2 get_window_size() const=0;
+ virtual void set_window_size(const Size2 p_size){}
+ virtual void set_window_fullscreen(bool p_enabled) {}
+ virtual bool is_window_fullscreen() const { return true; }
+ virtual void set_window_resizable(bool p_enabled) {}
+ virtual bool is_window_resizable() const { return false; }
+ virtual void set_window_minimized(bool p_enabled) {}
+ virtual bool is_window_minimized() const { return false; }
+ virtual void set_window_maximized(bool p_enabled) {}
+ virtual bool is_window_maximized() const { return true; }
+
+
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
@@ -222,14 +245,22 @@ public:
int min;
int sec;
};
-
- virtual Date get_date() const=0;
- virtual Time get_time() const=0;
+
+ struct TimeZoneInfo {
+ int bias;
+ String name;
+ };
+
+ virtual Date get_date(bool local=false) const=0;
+ virtual Time get_time(bool local=false) const=0;
+ virtual TimeZoneInfo get_time_zone_info() const=0;
virtual uint64_t get_unix_time() const;
+ virtual uint64_t get_system_time_msec() const;
virtual void delay_usec(uint32_t p_usec) const=0;
virtual uint64_t get_ticks_usec() const=0;
uint32_t get_ticks_msec() const;
+ uint64_t get_splash_tick_msec() const;
void set_frame_delay(uint32_t p_msec);
uint32_t get_frame_delay() const;
@@ -348,9 +379,23 @@ public:
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, Object* p_obj, String p_callback);
+ enum LatinKeyboardVariant {
+ LATIN_KEYBOARD_QWERTY,
+ LATIN_KEYBOARD_QWERTZ,
+ LATIN_KEYBOARD_AZERTY,
+ LATIN_KEYBOARD_QZERTY,
+ LATIN_KEYBOARD_DVORAK,
+ LATIN_KEYBOARD_NEO,
+ };
+
+
+ virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
+
void set_time_scale(float p_scale);
float get_time_scale() const;
+ _FORCE_INLINE_ bool get_use_pixel_snap() const { return _pixel_snap; }
+
OS();
virtual ~OS();
diff --git a/core/os/pc_joystick_map.h b/core/os/pc_joystick_map.h
index 171723439b..111dc9b3a8 100644
--- a/core/os/pc_joystick_map.h
+++ b/core/os/pc_joystick_map.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/semaphore.cpp b/core/os/semaphore.cpp
index 3abab34886..8cb431d2cc 100644
--- a/core/os/semaphore.cpp
+++ b/core/os/semaphore.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/semaphore.h b/core/os/semaphore.h
index b188f07399..e8ad9d3c3a 100644
--- a/core/os/semaphore.h
+++ b/core/os/semaphore.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/shell.cpp b/core/os/shell.cpp
index 565929eae5..3746dc6804 100644
--- a/core/os/shell.cpp
+++ b/core/os/shell.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/shell.h b/core/os/shell.h
index 38b29c6eca..7ef5abbdef 100644
--- a/core/os/shell.h
+++ b/core/os/shell.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index d8d9f3e291..96b0f561ca 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread.h b/core/os/thread.h
index 864fc6db05..590fee1fc6 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp
index 1974bf615b..4e139f6379 100644
--- a/core/os/thread_dummy.cpp
+++ b/core/os/thread_dummy.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h
index b681005fb6..a83e42ff98 100644
--- a/core/os/thread_dummy.h
+++ b/core/os/thread_dummy.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_safe.cpp b/core/os/thread_safe.cpp
index 9c7648be94..9a20db6a9d 100644
--- a/core/os/thread_safe.cpp
+++ b/core/os/thread_safe.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/os/thread_safe.h b/core/os/thread_safe.h
index 8b20c31cc9..62d2181279 100644
--- a/core/os/thread_safe.h
+++ b/core/os/thread_safe.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index 65a6433912..fa17e93aa8 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/packed_data_container.h b/core/packed_data_container.h
index b223d3bcfe..f4152bbb4d 100644
--- a/core/packed_data_container.h
+++ b/core/packed_data_container.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pair.cpp b/core/pair.cpp
index 4b6f350351..17076bb379 100644
--- a/core/pair.cpp
+++ b/core/pair.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pair.h b/core/pair.h
index d4cf3630ee..83fc837fff 100644
--- a/core/pair.h
+++ b/core/pair.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/path_db.cpp b/core/path_db.cpp
index 1027ce7318..c6ea25d966 100644
--- a/core/path_db.cpp
+++ b/core/path_db.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -286,6 +286,37 @@ NodePath::NodePath(const Vector<StringName>& p_path,const Vector<StringName>& p_
data->property=p_property;
}
+
+void NodePath::simplify() {
+
+ if (!data)
+ return;
+ for(int i=0;i<data->path.size();i++) {
+ if (data->path.size()==1)
+ break;
+ if (data->path[i].operator String()==".") {
+ data->path.remove(i);
+ i--;
+ } else if (data->path[i].operator String()==".." && i>0 && data->path[i-1].operator String()!="." && data->path[i-1].operator String()!="..") {
+ //remove both
+ data->path.remove(i-1);
+ data->path.remove(i-1);
+ i-=2;
+ if (data->path.size()==0) {
+ data->path.push_back(".");
+ break;
+ }
+ }
+ }
+}
+
+NodePath NodePath::simplified() const {
+
+ NodePath np=*this;
+ np.simplify();
+ return np;
+}
+
NodePath::NodePath(const String& p_path) {
data=NULL;
diff --git a/core/path_db.h b/core/path_db.h
index 561dc01672..de84216006 100644
--- a/core/path_db.h
+++ b/core/path_db.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -84,7 +84,10 @@ public:
bool operator==(const NodePath& p_path) const;
bool operator!=(const NodePath& p_path) const;
void operator=(const NodePath& p_path);
-
+
+ void simplify();
+ NodePath simplified() const;
+
NodePath(const Vector<StringName>& p_path,bool p_absolute,const String& p_property="");
NodePath(const Vector<StringName>& p_path,const Vector<StringName>& p_subpath,bool p_absolute,const String& p_property="");
NodePath(const NodePath& p_path);
diff --git a/core/path_remap.cpp b/core/path_remap.cpp
index 34675c4575..2ef39470a0 100644
--- a/core/path_remap.cpp
+++ b/core/path_remap.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,163 +26,163 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "path_remap.h"
-#include "globals.h"
-#include "os/os.h"
-#include "translation.h"
-PathRemap* PathRemap::singleton=NULL;
-
-PathRemap* PathRemap::get_singleton() {
-
- return singleton;
-}
-
-void PathRemap::add_remap(const String& p_from, const String& p_to,const String& p_locale) {
-
- if (!remap.has(p_from)) {
- remap[p_from]=RemapData();
- }
-
- if (p_locale==String())
- remap[p_from].always=p_to;
- else
- remap[p_from].locale[p_locale]=p_to;
-}
-
-
-String PathRemap::get_remap(const String& p_from) const {
-
- const RemapData *ptr=remap.getptr(p_from);
- if (!ptr) {
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("remap failed: "+p_from);
- return p_from;
- } else {
-
- String locale = TranslationServer::get_singleton()->get_locale();
-
- if (ptr->locale.has(locale)) {
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("remap found: "+p_from+" -> "+ptr->locale[locale]);
- return ptr->locale[locale];
- }
-
- int p = locale.find("_");
- if (p!=-1) {
- locale=locale.substr(0,p);
- if (ptr->locale.has(locale)) {
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("remap found: "+p_from+" -> "+ptr->locale[locale]);
- return ptr->locale[locale];
- }
- }
-
- if (ptr->always!=String()) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- print_line("remap found: "+p_from+" -> "+ptr->always);
- }
- return ptr->always;
- }
-
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("remap failed: "+p_from);
-
- return p_from;
- }
-}
-bool PathRemap::has_remap(const String& p_from) const{
-
- return remap.has(p_from);
-}
-
-void PathRemap::erase_remap(const String& p_from){
-
- ERR_FAIL_COND(!remap.has(p_from));
- remap.erase(p_from);
-}
-
-void PathRemap::clear_remaps() {
-
- remap.clear();
-}
-
-void PathRemap::load_remaps() {
-
- // default remaps first
- DVector<String> remaps = Globals::get_singleton()->get("remap/all");
-
- {
- int rlen = remaps.size();
-
- ERR_FAIL_COND( rlen%2 );
- DVector<String>::Read r = remaps.read();
- for(int i=0;i<rlen/2;i++) {
-
- String from = r[i*2+0];
- String to = r[i*2+1];
- add_remap(from,to);
- }
- }
-
-
- // platform remaps second, so override
- remaps = Globals::get_singleton()->get("remap/"+OS::get_singleton()->get_name());
-// remaps = Globals::get_singleton()->get("remap/PSP");
- {
- int rlen = remaps.size();
-
- ERR_FAIL_COND( rlen%2 );
- DVector<String>::Read r = remaps.read();
- for(int i=0;i<rlen/2;i++) {
-
- String from = r[i*2+0];
- String to = r[i*2+1];
-// print_line("add remap: "+from+" -> "+to);
- add_remap(from,to);
- }
- }
-
-
- //locale based remaps
-
- if (Globals::get_singleton()->has("locale/translation_remaps")) {
-
- Dictionary remaps = Globals::get_singleton()->get("locale/translation_remaps");
- List<Variant> rk;
- remaps.get_key_list(&rk);
- for(List<Variant>::Element *E=rk.front();E;E=E->next()) {
-
- String source = E->get();
- StringArray sa = remaps[E->get()];
- int sas = sa.size();
- StringArray::Read r = sa.read();
-
- for(int i=0;i<sas;i++) {
-
- String s = r[i];
- int qp = s.find_last(":");
- if (qp!=-1) {
- String path = s.substr(0,qp);
- String locale = s.substr(qp+1,s.length());
- add_remap(source,path,locale);
- }
- }
- }
-
- }
-
-}
-
-void PathRemap::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("add_remap","from","to","locale"),&PathRemap::add_remap,DEFVAL(String()));
- ObjectTypeDB::bind_method(_MD("has_remap","path"),&PathRemap::has_remap);
- ObjectTypeDB::bind_method(_MD("get_remap","path"),&PathRemap::get_remap);
- ObjectTypeDB::bind_method(_MD("erase_remap","path"),&PathRemap::erase_remap);
- ObjectTypeDB::bind_method(_MD("clear_remaps"),&PathRemap::clear_remaps);
-}
-
-PathRemap::PathRemap() {
-
- singleton=this;
-}
+#include "path_remap.h"
+#include "globals.h"
+#include "os/os.h"
+#include "translation.h"
+PathRemap* PathRemap::singleton=NULL;
+
+PathRemap* PathRemap::get_singleton() {
+
+ return singleton;
+}
+
+void PathRemap::add_remap(const String& p_from, const String& p_to,const String& p_locale) {
+
+ if (!remap.has(p_from)) {
+ remap[p_from]=RemapData();
+ }
+
+ if (p_locale==String())
+ remap[p_from].always=p_to;
+ else
+ remap[p_from].locale[p_locale]=p_to;
+}
+
+
+String PathRemap::get_remap(const String& p_from) const {
+
+ const RemapData *ptr=remap.getptr(p_from);
+ if (!ptr) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_line("remap failed: "+p_from);
+ return p_from;
+ } else {
+
+ String locale = TranslationServer::get_singleton()->get_locale();
+
+ if (ptr->locale.has(locale)) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_line("remap found: "+p_from+" -> "+ptr->locale[locale]);
+ return ptr->locale[locale];
+ }
+
+ int p = locale.find("_");
+ if (p!=-1) {
+ locale=locale.substr(0,p);
+ if (ptr->locale.has(locale)) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_line("remap found: "+p_from+" -> "+ptr->locale[locale]);
+ return ptr->locale[locale];
+ }
+ }
+
+ if (ptr->always!=String()) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_line("remap found: "+p_from+" -> "+ptr->always);
+ }
+ return ptr->always;
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_line("remap failed: "+p_from);
+
+ return p_from;
+ }
+}
+bool PathRemap::has_remap(const String& p_from) const{
+
+ return remap.has(p_from);
+}
+
+void PathRemap::erase_remap(const String& p_from){
+
+ ERR_FAIL_COND(!remap.has(p_from));
+ remap.erase(p_from);
+}
+
+void PathRemap::clear_remaps() {
+
+ remap.clear();
+}
+
+void PathRemap::load_remaps() {
+
+ // default remaps first
+ DVector<String> remaps = Globals::get_singleton()->get("remap/all");
+
+ {
+ int rlen = remaps.size();
+
+ ERR_FAIL_COND( rlen%2 );
+ DVector<String>::Read r = remaps.read();
+ for(int i=0;i<rlen/2;i++) {
+
+ String from = r[i*2+0];
+ String to = r[i*2+1];
+ add_remap(from,to);
+ }
+ }
+
+
+ // platform remaps second, so override
+ remaps = Globals::get_singleton()->get("remap/"+OS::get_singleton()->get_name());
+// remaps = Globals::get_singleton()->get("remap/PSP");
+ {
+ int rlen = remaps.size();
+
+ ERR_FAIL_COND( rlen%2 );
+ DVector<String>::Read r = remaps.read();
+ for(int i=0;i<rlen/2;i++) {
+
+ String from = r[i*2+0];
+ String to = r[i*2+1];
+// print_line("add remap: "+from+" -> "+to);
+ add_remap(from,to);
+ }
+ }
+
+
+ //locale based remaps
+
+ if (Globals::get_singleton()->has("locale/translation_remaps")) {
+
+ Dictionary remaps = Globals::get_singleton()->get("locale/translation_remaps");
+ List<Variant> rk;
+ remaps.get_key_list(&rk);
+ for(List<Variant>::Element *E=rk.front();E;E=E->next()) {
+
+ String source = E->get();
+ StringArray sa = remaps[E->get()];
+ int sas = sa.size();
+ StringArray::Read r = sa.read();
+
+ for(int i=0;i<sas;i++) {
+
+ String s = r[i];
+ int qp = s.find_last(":");
+ if (qp!=-1) {
+ String path = s.substr(0,qp);
+ String locale = s.substr(qp+1,s.length());
+ add_remap(source,path,locale);
+ }
+ }
+ }
+
+ }
+
+}
+
+void PathRemap::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("add_remap","from","to","locale"),&PathRemap::add_remap,DEFVAL(String()));
+ ObjectTypeDB::bind_method(_MD("has_remap","path"),&PathRemap::has_remap);
+ ObjectTypeDB::bind_method(_MD("get_remap","path"),&PathRemap::get_remap);
+ ObjectTypeDB::bind_method(_MD("erase_remap","path"),&PathRemap::erase_remap);
+ ObjectTypeDB::bind_method(_MD("clear_remaps"),&PathRemap::clear_remaps);
+}
+
+PathRemap::PathRemap() {
+
+ singleton=this;
+}
diff --git a/core/path_remap.h b/core/path_remap.h
index a463cf259e..cb2a045668 100644
--- a/core/path_remap.h
+++ b/core/path_remap.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,42 +26,42 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PATH_REMAP_H
-#define PATH_REMAP_H
-
-#include "hash_map.h"
-#include "ustring.h"
-#include "object.h"
-
-
-class PathRemap : public Object {
-
- OBJ_TYPE(PathRemap,Object);
-
- static PathRemap* singleton;
- struct RemapData {
- String always;
- Map<String,String> locale;
- };
-
- HashMap<String,RemapData> remap;
-protected:
-
- static void _bind_methods();
-public:
-
- void add_remap(const String& p_from, const String& p_to,const String& p_locale=String());
- bool has_remap(const String& p_from) const;
- //_FORCE_INLINE_ String get_remap(const String& p_from) const { const String *ptr=remap.getptr(p_from); if (!ptr) return p_from; else return *ptr; }
- String get_remap(const String& p_from) const;
- void erase_remap(const String& p_from);
- void clear_remaps();
-
- void load_remaps();
-
- static PathRemap* get_singleton();
-
- PathRemap();
-};
-
-#endif // PATH_REMAP_H
+#ifndef PATH_REMAP_H
+#define PATH_REMAP_H
+
+#include "hash_map.h"
+#include "ustring.h"
+#include "object.h"
+
+
+class PathRemap : public Object {
+
+ OBJ_TYPE(PathRemap,Object);
+
+ static PathRemap* singleton;
+ struct RemapData {
+ String always;
+ Map<String,String> locale;
+ };
+
+ HashMap<String,RemapData> remap;
+protected:
+
+ static void _bind_methods();
+public:
+
+ void add_remap(const String& p_from, const String& p_to,const String& p_locale=String());
+ bool has_remap(const String& p_from) const;
+ //_FORCE_INLINE_ String get_remap(const String& p_from) const { const String *ptr=remap.getptr(p_from); if (!ptr) return p_from; else return *ptr; }
+ String get_remap(const String& p_from) const;
+ void erase_remap(const String& p_from);
+ void clear_remaps();
+
+ void load_remaps();
+
+ static PathRemap* get_singleton();
+
+ PathRemap();
+};
+
+#endif // PATH_REMAP_H
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index 5af168ce82..d7dca45836 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/pool_allocator.h b/core/pool_allocator.h
index 4b94ae48d6..4b0f931eb3 100644
--- a/core/pool_allocator.h
+++ b/core/pool_allocator.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/print_string.cpp b/core/print_string.cpp
index ae15d05a35..42e018f303 100644
--- a/core/print_string.cpp
+++ b/core/print_string.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
static PrintHandlerList *print_handler_list=NULL;
bool _print_line_enabled=true;
+bool _print_error_enabled = true;
void add_print_handler(PrintHandlerList *p_handler) {
diff --git a/core/print_string.h b/core/print_string.h
index c3e91f32fa..4ea389b3a1 100644
--- a/core/print_string.h
+++ b/core/print_string.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,6 +52,7 @@ void add_print_handler(PrintHandlerList *p_handler);
void remove_print_handler(PrintHandlerList *p_handler);
extern bool _print_line_enabled;
+extern bool _print_error_enabled;
extern void print_line(String p_string);
#endif
diff --git a/core/ref_ptr.cpp b/core/ref_ptr.cpp
index f0758f66ce..ddb8054e3b 100644
--- a/core/ref_ptr.cpp
+++ b/core/ref_ptr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/ref_ptr.h b/core/ref_ptr.h
index 007977d993..d1ee6a3a7d 100644
--- a/core/ref_ptr.h
+++ b/core/ref_ptr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/reference.cpp b/core/reference.cpp
index 2fc941310d..509e132b5a 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -59,6 +59,10 @@ void Reference::_bind_methods() {
ObjectTypeDB::bind_method(_MD("unreference"),&Reference::unreference);
}
+int Reference::reference_get_count() const {
+ return refcount.get();
+}
+
void Reference::reference(){
refcount.ref();
diff --git a/core/reference.h b/core/reference.h
index 64d7a7acad..65f31f78f3 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,6 +53,7 @@ public:
bool init_ref();
void reference();
bool unreference();
+ int reference_get_count() const;
Reference();
~Reference();
@@ -293,6 +294,9 @@ public:
reference=NULL;
}
+ void instance() {
+ ref( memnew( T ));
+ }
Ref() {
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 2f16e31de6..8754946bb1 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -110,6 +110,7 @@ void register_core_types() {
ObjectTypeDB::register_type<Reference>();
+ ObjectTypeDB::register_type<WeakRef>();
ObjectTypeDB::register_type<ResourceImportMetadata>();
ObjectTypeDB::register_type<Resource>();
ObjectTypeDB::register_type<FuncRef>();
@@ -204,12 +205,14 @@ void unregister_core_types() {
if (ip)
memdelete(ip);
+
+ ObjectDB::cleanup();
+
unregister_variant_methods();
- CoreStringNames::free();
ObjectTypeDB::cleanup();
ResourceCache::clear();
- ObjectDB::cleanup();
+ CoreStringNames::free();
StringName::cleanup();
if (_global_mutex) {
diff --git a/core/register_core_types.h b/core/register_core_types.h
index 9f89a3ffeb..a84849c969 100644
--- a/core/register_core_types.h
+++ b/core/register_core_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/res_ptr.cpp b/core/res_ptr.cpp
index b9bd931570..fcff285e8f 100644
--- a/core/res_ptr.cpp
+++ b/core/res_ptr.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/res_ptr.h b/core/res_ptr.h
index 69da69bf52..21f7fb6a2c 100644
--- a/core/res_ptr.h
+++ b/core/res_ptr.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/resource.cpp b/core/resource.cpp
index 987bd772b0..6967599f96 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -130,7 +130,7 @@ void ResourceImportMetadata::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_editor","name"),&ResourceImportMetadata::set_editor);
ObjectTypeDB::bind_method(_MD("get_editor"),&ResourceImportMetadata::get_editor);
- ObjectTypeDB::bind_method(_MD("add_source","path","md5"),&ResourceImportMetadata::add_source);
+ ObjectTypeDB::bind_method(_MD("add_source","path","md5"),&ResourceImportMetadata::add_source, "");
ObjectTypeDB::bind_method(_MD("get_source_path","idx"),&ResourceImportMetadata::get_source_path);
ObjectTypeDB::bind_method(_MD("get_source_md5","idx"),&ResourceImportMetadata::get_source_md5);
ObjectTypeDB::bind_method(_MD("remove_source","idx"),&ResourceImportMetadata::remove_source);
@@ -195,6 +195,17 @@ String Resource::get_path() const {
return path_cache;
}
+void Resource::set_subindex(int p_sub_index) {
+
+ subindex=p_sub_index;
+}
+
+int Resource::get_subindex() const{
+
+ return subindex;
+}
+
+
void Resource::set_name(const String& p_name) {
name=p_name;
@@ -326,6 +337,7 @@ Resource::Resource() {
last_modified_time=0;
#endif
+ subindex=0;
}
diff --git a/core/resource.h b/core/resource.h
index 8a637e7996..3596abe673 100644
--- a/core/resource.h
+++ b/core/resource.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -99,6 +99,7 @@ friend class ResourceCache;
String name;
String path_cache;
+ int subindex;
virtual bool _use_builtin_script() const { return true; }
@@ -129,9 +130,12 @@ public:
void set_name(const String& p_name);
String get_name() const;
- void set_path(const String& p_path,bool p_take_over=false);
+ virtual void set_path(const String& p_path,bool p_take_over=false);
String get_path() const;
+ void set_subindex(int p_sub_index);
+ int get_subindex() const;
+
Ref<Resource> duplicate(bool p_subresources=false);
void set_import_metadata(const Ref<ResourceImportMetadata>& p_metadata);
diff --git a/core/rid.cpp b/core/rid.cpp
index 3dc4c6aed4..0870e6ab2d 100644
--- a/core/rid.cpp
+++ b/core/rid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/rid.h b/core/rid.h
index 4d4e11c251..e6582757ee 100644
--- a/core/rid.h
+++ b/core/rid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/ring_buffer.h b/core/ring_buffer.h
index 71105e7bf1..3cf9cf9064 100644
--- a/core/ring_buffer.h
+++ b/core/ring_buffer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -141,15 +141,15 @@ public:
inline int space_left() {
int left = read_pos - write_pos;
if (left < 0) {
- return size() + left;
+ return size() + left - 1;
};
if (left == 0) {
- return size();
+ return size()-1;
};
- return left;
+ return left -1;
};
inline int data_left() {
- return size() - space_left();
+ return size() - space_left() - 1;
};
inline int size() {
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index 3d867448e8..afe2a4eb33 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 4357786732..481b9fa7e9 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_debugger.cpp b/core/script_debugger_debugger.cpp
index 6ff60e6ff4..5c592a130c 100644
--- a/core/script_debugger_debugger.cpp
+++ b/core/script_debugger_debugger.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index 5e153a4912..649bbe89f0 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -60,7 +60,7 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) {
if (line.get_slice_count(" ")==1) {
print_line("*Frame "+itos(current_frame)+" - "+p_script->debug_get_stack_level_source(current_frame)+":"+itos(p_script->debug_get_stack_level_line(current_frame))+" in function '"+p_script->debug_get_stack_level_function(current_frame)+"'");
} else {
- int frame = line.get_slice(" ",1).to_int();
+ int frame = line.get_slicec(' ',1).to_int();
if (frame<0 || frame >=total_frames) {
print_line("Error: Invalid frame.");
} else {
@@ -108,7 +108,7 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) {
print_line("Usage: print <expre>");
} else {
- String expr = line.get_slice(" ",2);
+ String expr = line.get_slicec(' ',2);
String res = p_script->debug_parse_stack_level_expression(current_frame,expr);
print_line(res);
}
@@ -130,9 +130,9 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) {
} else {
- String bppos=line.get_slice(" ",1);
- String source=bppos.get_slice(":",0).strip_edges();
- int line=bppos.get_slice(":",1).strip_edges().to_int();
+ String bppos=line.get_slicec(' ',1);
+ String source=bppos.get_slicec(':',0).strip_edges();
+ int line=bppos.get_slicec(':',1).strip_edges().to_int();
source = breakpoint_find_source(source);
@@ -147,9 +147,9 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) {
clear_breakpoints();
} else {
- String bppos=line.get_slice(" ",1);
- String source=bppos.get_slice(":",0).strip_edges();
- int line=bppos.get_slice(":",1).strip_edges().to_int();
+ String bppos=line.get_slicec(' ',1);
+ String source=bppos.get_slicec(':',0).strip_edges();
+ int line=bppos.get_slicec(':',1).strip_edges().to_int();
source = breakpoint_find_source(source);
diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h
index 159dd15e58..45ff1d4466 100644
--- a/core/script_debugger_local.h
+++ b/core/script_debugger_local.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index cd8303b542..d72c9f7532 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,10 +31,36 @@
#include "io/ip.h"
#include "globals.h"
+void ScriptDebuggerRemote::_send_video_memory() {
+
+ List<ResourceUsage> usage;
+ if (resource_usage_func)
+ resource_usage_func(&usage);
+
+ usage.sort();
+
+ packet_peer_stream->put_var("message:video_mem");
+ packet_peer_stream->put_var(usage.size()*4);
+
+
+ for(List<ResourceUsage>::Element *E=usage.front();E;E=E->next()) {
+
+ packet_peer_stream->put_var(E->get().path);
+ packet_peer_stream->put_var(E->get().type);
+ packet_peer_stream->put_var(E->get().format);
+ packet_peer_stream->put_var(E->get().vram);
+ }
+
+}
+
Error ScriptDebuggerRemote::connect_to_host(const String& p_host,uint16_t p_port) {
- IP_Address ip = IP::get_singleton()->resolve_hostname(p_host);
+ IP_Address ip;
+ if (p_host.is_valid_ip_address())
+ ip=p_host;
+ else
+ ip = IP::get_singleton()->resolve_hostname(p_host);
int port = p_port;
@@ -127,7 +153,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING );
String command = cmd[0];
- cmd.remove(0);
+
if (command=="get_stack_dump") {
@@ -150,7 +176,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
} else if (command=="get_stack_frame_vars") {
-
+ cmd.remove(0);
ERR_CONTINUE( cmd.size()!=1 );
int lv = cmd[0];
@@ -243,6 +269,20 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
if (request_scene_tree)
request_scene_tree(request_scene_tree_ud);
+
+ } else if (command=="request_video_mem") {
+
+ _send_video_memory();
+ } else if (command=="breakpoint") {
+
+ bool set = cmd[3];
+ if (set)
+ insert_breakpoint(cmd[2],cmd[1]);
+ else
+ remove_breakpoint(cmd[2],cmd[1]);
+
+ } else {
+ _parse_live_edit(cmd);
}
@@ -287,6 +327,37 @@ void ScriptDebuggerRemote::_get_output() {
messages.pop_front();
locking=false;
}
+
+ while (errors.size()) {
+ locking=true;
+ packet_peer_stream->put_var("error");
+ OutputError oe = errors.front()->get();
+
+ packet_peer_stream->put_var(oe.callstack.size()+2);
+
+ Array error_data;
+
+ error_data.push_back(oe.hr);
+ error_data.push_back(oe.min);
+ error_data.push_back(oe.sec);
+ error_data.push_back(oe.msec);
+ error_data.push_back(oe.source_func);
+ error_data.push_back(oe.source_file);
+ error_data.push_back(oe.source_line);
+ error_data.push_back(oe.error);
+ error_data.push_back(oe.error_descr);
+ error_data.push_back(oe.warning);
+ packet_peer_stream->put_var(error_data);
+ packet_peer_stream->put_var(oe.callstack.size());
+ for(int i=0;i<oe.callstack.size();i++) {
+ packet_peer_stream->put_var(oe.callstack[i]);
+
+ }
+
+ errors.pop_front();
+ locking=false;
+
+ }
mutex->unlock();
}
@@ -301,6 +372,160 @@ void ScriptDebuggerRemote::line_poll() {
}
+void ScriptDebuggerRemote::_err_handler(void* ud,const char* p_func,const char*p_file,int p_line,const char *p_err, const char * p_descr,ErrorHandlerType p_type) {
+
+ if (p_type==ERR_HANDLER_SCRIPT)
+ return; //ignore script errors, those go through debugger
+
+ ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote*)ud;
+
+ OutputError oe;
+ oe.error=p_err;
+ oe.error_descr=p_descr;
+ oe.source_file=p_file;
+ oe.source_line=p_line;
+ oe.source_func=p_func;
+ oe.warning=p_type==ERR_HANDLER_WARNING;
+ uint64_t time = OS::get_singleton()->get_ticks_msec();
+ oe.hr=time/3600000;
+ oe.min=(time/60000)%60;
+ oe.sec=(time/1000)%60;
+ oe.msec=time%1000;
+ Array cstack;
+
+ Vector<ScriptLanguage::StackInfo> si;
+
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+ si=ScriptServer::get_language(i)->debug_get_current_stack_info();
+ if (si.size())
+ break;
+ }
+
+ cstack.resize(si.size()*2);
+ for(int i=0;i<si.size();i++) {
+ String path;
+ int line=0;
+ if (si[i].script.is_valid()) {
+ path=si[i].script->get_path();
+ line=si[i].line;
+ }
+ cstack[i*2+0]=path;
+ cstack[i*2+1]=line;
+ }
+
+ oe.callstack=cstack;
+
+
+ sdr->mutex->lock();
+
+ if (!sdr->locking && sdr->tcp_client->is_connected()) {
+
+ sdr->errors.push_back(oe);
+ }
+
+ sdr->mutex->unlock();
+}
+
+
+bool ScriptDebuggerRemote::_parse_live_edit(const Array& cmd) {
+
+ String cmdstr = cmd[0];
+ if (!live_edit_funcs || !cmdstr.begins_with("live_"))
+ return false;
+
+
+ //print_line(Variant(cmd).get_construct_string());
+ if (cmdstr=="live_set_root") {
+
+ if (!live_edit_funcs->root_func)
+ return true;
+ //print_line("root: "+Variant(cmd).get_construct_string());
+ live_edit_funcs->root_func(live_edit_funcs->udata,cmd[1],cmd[2]);
+
+ } else if (cmdstr=="live_node_path") {
+
+ if (!live_edit_funcs->node_path_func)
+ return true;
+ //print_line("path: "+Variant(cmd).get_construct_string());
+
+ live_edit_funcs->node_path_func(live_edit_funcs->udata,cmd[1],cmd[2]);
+
+ } else if (cmdstr=="live_res_path") {
+
+ if (!live_edit_funcs->res_path_func)
+ return true;
+ live_edit_funcs->res_path_func(live_edit_funcs->udata,cmd[1],cmd[2]);
+
+ } else if (cmdstr=="live_node_prop_res") {
+ if (!live_edit_funcs->node_set_res_func)
+ return true;
+
+ live_edit_funcs->node_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_node_prop") {
+
+ if (!live_edit_funcs->node_set_func)
+ return true;
+ live_edit_funcs->node_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_res_prop_res") {
+
+ if (!live_edit_funcs->res_set_res_func)
+ return true;
+ live_edit_funcs->res_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_res_prop") {
+
+ if (!live_edit_funcs->res_set_func)
+ return true;
+ live_edit_funcs->res_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_node_call") {
+
+ if (!live_edit_funcs->node_call_func)
+ return true;
+ live_edit_funcs->node_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]);
+
+ } else if (cmdstr=="live_res_call") {
+
+ if (!live_edit_funcs->res_call_func)
+ return true;
+ live_edit_funcs->res_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]);
+
+ } else if (cmdstr=="live_create_node") {
+
+ live_edit_funcs->tree_create_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_instance_node") {
+
+ live_edit_funcs->tree_instance_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_remove_node") {
+
+ live_edit_funcs->tree_remove_node_func(live_edit_funcs->udata,cmd[1]);
+
+ } else if (cmdstr=="live_remove_and_keep_node") {
+
+ live_edit_funcs->tree_remove_and_keep_node_func(live_edit_funcs->udata,cmd[1],cmd[2]);
+ } else if (cmdstr=="live_restore_node") {
+
+ live_edit_funcs->tree_restore_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]);
+
+ } else if (cmdstr=="live_duplicate_node") {
+
+ live_edit_funcs->tree_duplicate_node_func(live_edit_funcs->udata,cmd[1],cmd[2]);
+ } else if (cmdstr=="live_reparent_node") {
+
+ live_edit_funcs->tree_reparent_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3],cmd[4]);
+
+ } else {
+
+ return false;
+ }
+
+ return true;
+}
+
void ScriptDebuggerRemote::_poll_events() {
while(packet_peer_stream->get_available_packet_count()>0) {
@@ -321,7 +546,7 @@ void ScriptDebuggerRemote::_poll_events() {
ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING );
String command = cmd[0];
- cmd.remove(0);
+ //cmd.remove(0);
if (command=="break") {
@@ -331,6 +556,18 @@ void ScriptDebuggerRemote::_poll_events() {
if (request_scene_tree)
request_scene_tree(request_scene_tree_ud);
+ } else if (command=="request_video_mem") {
+
+ _send_video_memory();
+ } else if (command=="breakpoint") {
+
+ bool set = cmd[3];
+ if (set)
+ insert_breakpoint(cmd[2],cmd[1]);
+ else
+ remove_breakpoint(cmd[2],cmd[1]);
+ } else {
+ _parse_live_edit(cmd);
}
}
@@ -394,10 +631,35 @@ void ScriptDebuggerRemote::_print_handler(void *p_this,const String& p_string) {
ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote*)p_this;
+ uint64_t ticks = OS::get_singleton()->get_ticks_usec()/1000;
+ sdr->msec_count+=ticks-sdr->last_msec;
+ sdr->last_msec=ticks;
+
+ if (sdr->msec_count>1000) {
+ sdr->char_count=0;
+ sdr->msec_count=0;
+ }
+
+ String s = p_string;
+ int allowed_chars = MIN(MAX(sdr->max_cps - sdr->char_count,0), s.length());
+
+ if (allowed_chars==0)
+ return;
+
+ if (allowed_chars<s.length()) {
+ s=s.substr(0,allowed_chars);
+ }
+
+ sdr->char_count+=allowed_chars;
+
+ if (sdr->char_count>=sdr->max_cps) {
+ s+="\n[output overflow, print less text!]\n";
+ }
+
sdr->mutex->lock();
if (!sdr->locking && sdr->tcp_client->is_connected()) {
- sdr->output_strings .push_back(p_string);
+ sdr->output_strings.push_back(s);
}
sdr->mutex->unlock();
}
@@ -413,6 +675,13 @@ void ScriptDebuggerRemote::set_request_scene_tree_message_func(RequestSceneTreeM
request_scene_tree_ud=p_udata;
}
+void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) {
+
+ live_edit_funcs=p_funcs;
+}
+
+ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func=NULL;
+
ScriptDebuggerRemote::ScriptDebuggerRemote() {
tcp_client = StreamPeerTCP::create_ref();
@@ -429,13 +698,22 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() {
last_perf_time=0;
poll_every=0;
request_scene_tree=NULL;
+ live_edit_funcs=NULL;
+ max_cps = GLOBAL_DEF("debug/max_remote_stdout_chars_per_second",2048);
+ char_count=0;
+ msec_count=0;
+ last_msec=0;
+
+ eh.errfunc=_err_handler;
+ eh.userdata=this;
+ add_error_handler(&eh);
}
ScriptDebuggerRemote::~ScriptDebuggerRemote() {
remove_print_handler(&phl);
+ remove_error_handler(&eh);
memdelete(mutex);
-
}
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index 861bcccff7..973fa23212 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "io/stream_peer_tcp.h"
#include "io/packet_peer.h"
#include "list.h"
+
class ScriptDebuggerRemote : public ScriptDebugger {
struct Message {
@@ -42,6 +43,8 @@ class ScriptDebuggerRemote : public ScriptDebugger {
Array data;
};
+
+
Ref<StreamPeerTCP> tcp_client;
Ref<PacketPeerStream> packet_peer_stream;
@@ -49,8 +52,31 @@ class ScriptDebuggerRemote : public ScriptDebugger {
Object *performance;
bool requested_quit;
Mutex *mutex;
+
+ struct OutputError {
+
+ int hr;
+ int min;
+ int sec;
+ int msec;
+ String source_file;
+ String source_func;
+ int source_line;
+ String error;
+ String error_descr;
+ bool warning;
+ Array callstack;
+
+ };
+
List<String> output_strings;
List<Message> messages;
+ List<OutputError> errors;
+
+ int max_cps;
+ int char_count;
+ uint64_t last_msec;
+ uint64_t msec_count;
bool locking; //hack to avoid a deadloop
static void _print_handler(void *p_this,const String& p_string);
@@ -62,12 +88,34 @@ class ScriptDebuggerRemote : public ScriptDebugger {
uint32_t poll_every;
+ bool _parse_live_edit(const Array &p_command);
+
RequestSceneTreeMessageFunc request_scene_tree;
void *request_scene_tree_ud;
+ void _send_video_memory();
+ LiveEditFuncs *live_edit_funcs;
+
+ ErrorHandlerList eh;
+ static void _err_handler(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);
+
public:
+ struct ResourceUsage {
+
+ String path;
+ String format;
+ String type;
+ RID id;
+ int vram;
+ bool operator<(const ResourceUsage& p_img) const { return vram==p_img.vram ? id<p_img.id : vram > p_img.vram; }
+ };
+
+ typedef void (*ResourceUsageFunc)(List<ResourceUsage>*);
+
+ static ResourceUsageFunc resource_usage_func;
+
Error connect_to_host(const String& p_host,uint16_t p_port);
virtual void debug(ScriptLanguage *p_script,bool p_can_continue=true);
virtual void idle_poll();
@@ -79,6 +127,7 @@ public:
virtual void send_message(const String& p_message, const Array& p_args);
virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata);
+ virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs);
ScriptDebuggerRemote();
~ScriptDebuggerRemote();
diff --git a/core/script_language.cpp b/core/script_language.cpp
index 81a9e2b062..35c50b1022 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -136,6 +136,14 @@ ScriptInstance::~ScriptInstance() {
}
+
+ScriptCodeCompletionCache *ScriptCodeCompletionCache::singleton=NULL;
+ScriptCodeCompletionCache::ScriptCodeCompletionCache() {
+ singleton=this;
+}
+
+
+
void ScriptLanguage::frame() {
diff --git a/core/script_language.h b/core/script_language.h
index 802eff190a..5a0f673b94 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -94,6 +94,10 @@ public:
virtual ScriptLanguage *get_language() const=0;
+ virtual bool has_script_signal(const StringName& p_signal) const=0;
+ virtual void get_script_signal_list(List<MethodInfo> *r_signals) const=0;
+
+
virtual void update_exports() {} //editor tool
@@ -122,6 +126,19 @@ public:
virtual ~ScriptInstance();
};
+class ScriptCodeCompletionCache {
+
+ static ScriptCodeCompletionCache *singleton;
+public:
+
+ virtual RES get_cached_resource(const String& p_path)=0;
+
+ static ScriptCodeCompletionCache* get_sigleton() { return singleton; }
+
+ ScriptCodeCompletionCache();
+
+};
+
class ScriptLanguage {
public:
@@ -159,6 +176,13 @@ public:
virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1)=0;
virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1)=0;
+ struct StackInfo {
+ Ref<Script> script;
+ int line;
+ };
+
+ virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
+
/* LOADER FUNCTIONS */
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
@@ -221,6 +245,32 @@ public:
typedef void (*RequestSceneTreeMessageFunc)(void *);
+ struct LiveEditFuncs {
+
+ void *udata;
+ void (*node_path_func)(void *,const NodePath &p_path,int p_id);
+ void (*res_path_func)(void *,const String &p_path,int p_id);
+
+ void (*node_set_func)(void *,int p_id,const StringName& p_prop,const Variant& p_value);
+ void (*node_set_res_func)(void *,int p_id,const StringName& p_prop,const String& p_value);
+ void (*node_call_func)(void *,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE);
+ void (*res_set_func)(void *,int p_id,const StringName& p_prop,const Variant& p_value);
+ void (*res_set_res_func)(void *,int p_id,const StringName& p_prop,const String& p_value);
+ void (*res_call_func)(void *,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE);
+ void (*root_func)(void*, const NodePath& p_scene_path,const String& p_scene_from);
+
+ void (*tree_create_node_func)(void*,const NodePath& p_parent,const String& p_type,const String& p_name);
+ void (*tree_instance_node_func)(void*,const NodePath& p_parent,const String& p_path,const String& p_name);
+ void (*tree_remove_node_func)(void*,const NodePath& p_at);
+ void (*tree_remove_and_keep_node_func)(void*,const NodePath& p_at,ObjectID p_keep_id);
+ void (*tree_restore_node_func)(void*,ObjectID p_id,const NodePath& p_at,int p_at_pos);
+ void (*tree_duplicate_node_func)(void*,const NodePath& p_at,const String& p_new_name);
+ void (*tree_reparent_node_func)(void*,const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name,int p_at_pos);
+
+ };
+
+
+
_FORCE_INLINE_ static ScriptDebugger * get_singleton() { return singleton; }
void set_lines_left(int p_left);
int get_lines_left() const;
@@ -235,10 +285,12 @@ public:
bool is_breakpoint_line(int p_line) const;
void clear_breakpoints();
+
virtual void debug(ScriptLanguage *p_script,bool p_can_continue=true)=0;
virtual void idle_poll();
virtual void line_poll();
+
void set_break_language(ScriptLanguage *p_lang);
ScriptLanguage* get_break_language() const;
@@ -248,6 +300,7 @@ public:
virtual void request_quit() {}
virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {}
+ virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs) {}
ScriptDebugger();
virtual ~ScriptDebugger() {singleton=NULL;}
diff --git a/core/self_list.h b/core/self_list.h
index 729b9fb680..b414baaba6 100644
--- a/core/self_list.h
+++ b/core/self_list.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/set.h b/core/set.h
index d87f635577..91c4e3f9c4 100644
--- a/core/set.h
+++ b/core/set.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -249,6 +249,37 @@ private:
return (node!=_data._nil)?node:NULL;
}
+ Element *_lower_bound(const T& p_value) const {
+
+ Element *node = _data._root->left;
+ Element *prev = NULL;
+ C less;
+
+ while(node!=_data._nil) {
+ prev=node;
+
+ if (less(p_value,node->value))
+ node=node->left;
+ else if (less(node->value,p_value))
+ node=node->right;
+ else
+ break; // found
+ }
+
+ if (node==_data._nil) {
+ if (prev==NULL)
+ return NULL;
+ if (less(prev->value,p_value)) {
+
+ prev=prev->_next;
+ }
+
+ return prev;
+
+ } else
+ return node;
+ }
+
Element *_insert(const T& p_value, bool& r_exists) {
@@ -582,6 +613,12 @@ public:
return e;
}
+
+ Element *lower_bound(const T& p_value) const {
+
+ return _lower_bound(p_value);
+ }
+
inline int size() const { return _data.size_cache; }
int calculate_depth() const {
diff --git a/core/simple_type.h b/core/simple_type.h
index fac6dceee8..84e08bf0b4 100644
--- a/core/simple_type.h
+++ b/core/simple_type.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/sort.h b/core/sort.h
index 583437a099..65664d0ed8 100644
--- a/core/sort.h
+++ b/core/sort.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/string_db.cpp b/core/string_db.cpp
index ffb7dc194b..b48d9f37d4 100644
--- a/core/string_db.cpp
+++ b/core/string_db.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "string_db.h"
#include "print_string.h"
-
+#include "os/os.h"
StaticCString StaticCString::create(const char *p_ptr) {
StaticCString scs; scs.ptr=p_ptr; return scs;
}
@@ -55,15 +55,29 @@ void StringName::setup() {
void StringName::cleanup() {
_global_lock();
+ int lost_strings=0;
for(int i=0;i<STRING_TABLE_LEN;i++) {
while(_table[i]) {
_Data*d=_table[i];
- _table[i]=_table[i]->next;
+ lost_strings++;
+ if (OS::get_singleton()->is_stdout_verbose()) {
+
+ if (d->cname) {
+ print_line("Orphan StringName: "+String(d->cname));
+ } else {
+ print_line("Orphan StringName: "+String(d->name));
+ }
+ }
+
+ _table[i]=_table[i]->next;
memdelete(d);
}
}
+ if (OS::get_singleton()->is_stdout_verbose() && lost_strings) {
+ print_line("StringName: "+itos(lost_strings)+" unclaimed string names at exit.");
+ }
_global_unlock();
}
@@ -144,7 +158,7 @@ void StringName::operator=(const StringName& p_name) {
_data = p_name._data;
}
}
-
+/* was inlined
StringName::operator String() const {
if (_data)
@@ -152,7 +166,7 @@ StringName::operator String() const {
return "";
}
-
+*/
StringName::StringName(const StringName& p_name) {
ERR_FAIL_COND(!configured);
diff --git a/core/string_db.h b/core/string_db.h
index 45afbbe6fc..3b3249bf5e 100644
--- a/core/string_db.h
+++ b/core/string_db.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -114,7 +114,17 @@ public:
}
bool operator!=(const StringName& p_name) const;
- operator String() const;
+ _FORCE_INLINE_ operator String() const {
+
+ if (_data) {
+ if (_data->cname )
+ return String(_data->cname);
+ else
+ return _data->name;
+ }
+
+ return String();
+ }
static StringName search(const char *p_name);
static StringName search(const CharType *p_name);
diff --git a/core/translation.cpp b/core/translation.cpp
index 81f2c36075..8247cd1201 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -550,7 +550,7 @@ StringName TranslationServer::translate(const StringName& p_message) const {
continue; // locale not match
//near match
- bool match = (l!=lptr);
+ bool match = (l!=locale);
if (near_match && !match)
continue; //only near-match once
@@ -570,6 +570,42 @@ StringName TranslationServer::translate(const StringName& p_message) const {
}
+ if (!res) {
+ //try again with fallback
+ if (fallback.length()>=2) {
+
+ const CharType *fptr=&fallback[0];
+ bool near_match=false;
+ for (const Set< Ref<Translation> >::Element *E=translations.front();E;E=E->next()) {
+
+ const Ref<Translation>& t = E->get();
+ String l = t->get_locale();
+ if (fptr[0]!=l[0] || fptr[1]!=l[1])
+ continue; // locale not match
+
+ //near match
+ bool match = (l!=fallback);
+
+ if (near_match && !match)
+ continue; //only near-match once
+
+ StringName r=t->get_message(p_message);
+
+ if (!r)
+ continue;
+
+ res=r;
+
+ if (match)
+ break;
+ else
+ near_match=true;
+
+ }
+ }
+ }
+
+
if (!res)
return p_message;
@@ -604,9 +640,27 @@ bool TranslationServer::_load_translations(const String& p_from) {
void TranslationServer::setup() {
-
- set_locale( GLOBAL_DEF("locale/default",OS::get_singleton()->get_locale()) );
- fallback = GLOBAL_DEF("locale/fallback","");
+ String test = GLOBAL_DEF("locale/test","");
+ test=test.strip_edges();
+ if (test!="")
+ set_locale( test );
+ else
+ set_locale( OS::get_singleton()->get_locale() );
+ fallback = GLOBAL_DEF("locale/fallback","en");
+#ifdef TOOLS_ENABLED
+
+ {
+ String options="";
+ int idx=0;
+ while(locale_list[idx]) {
+ if (idx>0)
+ options+=", ";
+ options+=locale_list[idx];
+ idx++;
+ }
+ Globals::get_singleton()->set_custom_property_info("locale/fallback",PropertyInfo(Variant::STRING,"locale/fallback",PROPERTY_HINT_ENUM,options));
+ }
+#endif
//load translations
}
@@ -629,6 +683,7 @@ void TranslationServer::load_translations() {
String locale = get_locale();
bool found = _load_translations("locale/translations"); //all
+
if (_load_translations("locale/translations_"+locale.substr(0,2)))
found=true;
if ( locale.substr(0,2) != locale ) {
@@ -637,17 +692,6 @@ void TranslationServer::load_translations() {
}
- if (!found && fallback!="") { //none found anywhere, use fallback
-
- _load_translations("locale/translations_"+fallback.substr(0,2));
- if ( fallback.substr(0,2) != fallback ) {
- _load_translations("locale/translations_"+fallback);
- }
-
- this->locale=fallback;
-
- }
-
}
TranslationServer::TranslationServer() {
diff --git a/core/translation.h b/core/translation.h
index d690320cd0..54118cd3b5 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/typedefs.h b/core/typedefs.h
index 442ed9ae0b..6ca31fd137 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -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/undo_redo.cpp b/core/undo_redo.cpp
index 2c4d9e16a8..85cc2bbc7f 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -234,11 +234,22 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
ERR_FAIL_COND(!obj);
}
+
switch(op.type) {
case Operation::TYPE_METHOD: {
- obj->call(op.name,VARIANT_ARGS_FROM_ARRAY(op.args));
+ obj->call(op.name,VARIANT_ARGS_FROM_ARRAY(op.args));
+#ifdef TOOLS_ENABLED
+ Resource* res = obj->cast_to<Resource>();
+ if (res)
+ res->set_edited(true);
+
+#endif
+
+ if (method_callback) {
+ method_callback(method_callbck_ud,obj,op.name,VARIANT_ARGS_FROM_ARRAY(op.args));
+ }
} break;
case Operation::TYPE_PROPERTY: {
@@ -248,6 +259,9 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
if (res)
res->set_edited(true);
#endif
+ if (property_callback) {
+ property_callback(prop_callback_ud,obj,op.name,op.args[0]);
+ }
} break;
case Operation::TYPE_REFERENCE: {
//do nothing
@@ -276,6 +290,7 @@ void UndoRedo::undo() {
return; //nothing to redo
_process_operation_list(actions[current_action].undo_ops.front());
current_action--;
+ version--;
}
void UndoRedo::clear_history() {
@@ -286,7 +301,7 @@ void UndoRedo::clear_history() {
while(actions.size())
_pop_history_tail();
- version++;
+ //version++;
}
String UndoRedo::get_current_action_name() const {
@@ -318,18 +333,160 @@ void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback,void*
callback_ud=p_ud;
}
+void UndoRedo::set_method_notify_callback(MethodNotifyCallback p_method_callback,void* p_ud) {
+
+ method_callback=p_method_callback;
+ method_callbck_ud=p_ud;
+}
+
+void UndoRedo::set_property_notify_callback(PropertyNotifyCallback p_property_callback,void* p_ud){
+
+ property_callback=p_property_callback;
+ prop_callback_ud=p_ud;
+}
+
+
UndoRedo::UndoRedo() {
- version=0;
+ version=1;
action_level=0;
current_action=-1;
max_steps=-1;
merging=true;
callback=NULL;
callback_ud=NULL;
+
+ method_callbck_ud=NULL;
+ prop_callback_ud=NULL;
+ method_callback=NULL;
+ property_callback=NULL;
+
}
UndoRedo::~UndoRedo() {
clear_history();
}
+
+Variant UndoRedo::_add_do_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
+
+ if (p_argcount<2) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=0;
+ return Variant();
+ }
+
+ if (p_args[0]->get_type()!=Variant::OBJECT) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::OBJECT;
+ return Variant();
+ }
+
+ if (p_args[1]->get_type()!=Variant::STRING) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=1;
+ r_error.expected=Variant::STRING;
+ return Variant();
+ }
+
+ r_error.error=Variant::CallError::CALL_OK;
+
+ Object* object = *p_args[0];
+ String method = *p_args[1];
+
+ Variant v[VARIANT_ARG_MAX];
+
+
+ for(int i=0;i<MIN(VARIANT_ARG_MAX,p_argcount-2);++i) {
+
+ v[i]=*p_args[i+2];
+ }
+
+ add_do_method(object,method,v[0],v[1],v[2],v[3],v[4]);
+ return Variant();
+}
+
+Variant UndoRedo::_add_undo_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {
+
+ if (p_argcount<2) {
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=0;
+ return Variant();
+ }
+
+ if (p_args[0]->get_type()!=Variant::OBJECT) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::OBJECT;
+ return Variant();
+ }
+
+ if (p_args[1]->get_type()!=Variant::STRING) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=1;
+ r_error.expected=Variant::STRING;
+ return Variant();
+ }
+
+ r_error.error=Variant::CallError::CALL_OK;
+
+ Object* object = *p_args[0];
+ String method = *p_args[1];
+
+ Variant v[VARIANT_ARG_MAX];
+
+
+ for(int i=0;i<MIN(VARIANT_ARG_MAX,p_argcount-2);++i) {
+
+ v[i]=*p_args[i+2];
+ }
+
+ add_undo_method(object,method,v[0],v[1],v[2],v[3],v[4]);
+ return Variant();
+}
+
+void UndoRedo::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("create_action","name","mergeable"),&UndoRedo::create_action, DEFVAL(false) );
+ ObjectTypeDB::bind_method(_MD("commit_action"),&UndoRedo::commit_action);
+
+ //ObjectTypeDB::bind_method(_MD("add_do_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_do_method);
+ //ObjectTypeDB::bind_method(_MD("add_undo_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_undo_method);
+
+ {
+ MethodInfo mi;
+ mi.name="add_do_method";
+ mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object"));
+ mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
+ Vector<Variant> defargs;
+ for(int i=0;i<VARIANT_ARG_MAX;++i) {
+ mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
+ defargs.push_back(Variant());
+ }
+
+ ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi,defargs);
+ }
+
+ {
+ MethodInfo mi;
+ mi.name="add_undo_method";
+ mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object"));
+ mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
+ Vector<Variant> defargs;
+ for(int i=0;i<VARIANT_ARG_MAX;++i) {
+ mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
+ defargs.push_back(Variant());
+ }
+
+ ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi,defargs);
+ }
+
+ ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:var"),&UndoRedo::add_do_property);
+ ObjectTypeDB::bind_method(_MD("add_undo_property","object", "property", "value:var"),&UndoRedo::add_undo_property);
+ ObjectTypeDB::bind_method(_MD("add_do_reference","object"),&UndoRedo::add_do_reference);
+ ObjectTypeDB::bind_method(_MD("add_undo_reference","object"),&UndoRedo::add_undo_reference);
+ ObjectTypeDB::bind_method(_MD("clear_history"),&UndoRedo::clear_history);
+ ObjectTypeDB::bind_method(_MD("get_current_action_name"),&UndoRedo::get_current_action_name);
+ ObjectTypeDB::bind_method(_MD("get_version"),&UndoRedo::get_version);
+}
diff --git a/core/undo_redo.h b/core/undo_redo.h
index ff729e1767..141a413c2a 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,9 +38,15 @@
class UndoRedo : public Object {
OBJ_TYPE(UndoRedo,Object);
+ OBJ_SAVE_TYPE( UndoRedo );
public:
typedef void (*CommitNotifyCallback)(void *p_ud,const String& p_name);
+ Variant _add_do_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
+ Variant _add_undo_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
+
+ typedef void (*MethodNotifyCallback)(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE);
+ typedef void (*PropertyNotifyCallback)(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value);
private:
struct Operation {
@@ -80,6 +86,15 @@ private:
CommitNotifyCallback callback;
void* callback_ud;
+ void* method_callbck_ud;
+ void* prop_callback_ud;
+
+ MethodNotifyCallback method_callback;
+ PropertyNotifyCallback property_callback;
+
+
+protected:
+ static void _bind_methods();
public:
@@ -106,6 +121,9 @@ public:
void set_commit_notify_callback(CommitNotifyCallback p_callback,void* p_ud);
+ void set_method_notify_callback(MethodNotifyCallback p_method_callback,void* p_ud);
+ void set_property_notify_callback(PropertyNotifyCallback p_property_callback,void* p_ud);
+
UndoRedo();
~UndoRedo();
};
diff --git a/core/ustring.cpp b/core/ustring.cpp
index d75c21d16e..f3c89a7908 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,6 +34,7 @@
#include "io/md5.h"
#include "ucaps.h"
#include "color.h"
+#include "variant.h"
#define MAX_DIGITS 6
#define UPPERCASE(m_c) (((m_c)>='a' && (m_c)<='z')?((m_c)-('a'-'A')):(m_c))
#define LOWERCASE(m_c) (((m_c)>='A' && (m_c)<='Z')?((m_c)+('a'-'A')):(m_c))
@@ -43,6 +44,11 @@
#include <stdlib.h>
#include <stdio.h>
#endif
+
+#if defined(MINGW_ENABLED) || defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
/** STRING **/
const char *CharString::get_data() const {
@@ -66,11 +72,14 @@ void String::copy_from(const char *p_cstr) {
return;
}
+
resize(len+1); // include 0
- for(int i=0;i<len+1;i++) {
-
- set(i,p_cstr[i]);
+ CharType *dst = this->ptr();
+
+ for (int i=0;i<len+1;i++) {
+
+ dst[i]=p_cstr[i];
}
}
@@ -485,7 +494,7 @@ String String::capitalize() const {
String cap;
for (int i=0;i<aux.get_slice_count(" ");i++) {
- String slice=aux.get_slice(" ",i);
+ String slice=aux.get_slicec(' ',i);
if (slice.length()>0) {
slice[0]=_find_upper(slice[0]);
@@ -497,6 +506,27 @@ String String::capitalize() const {
return cap;
}
+
+String String::camelcase_to_underscore() const {
+ const CharType * cstr = c_str();
+ String newString;
+ const char A = 'A', Z = 'Z';
+ int startIndex = 0;
+
+ for ( int i = 1; i < this->size()-1; i++ ) {
+ bool isCapital = cstr[i] >= A && cstr[i] <= Z;
+
+ if ( isCapital ) {
+ newString += "_" + this->substr(startIndex, i-startIndex);
+ startIndex = i;
+ }
+ }
+
+ newString += "_" + this->substr(startIndex, this->size()-startIndex);
+
+ return newString;
+}
+
int String::get_slice_count(String p_splitter) const{
if (empty())
@@ -555,6 +585,41 @@ String String::get_slice(String p_splitter, int p_slice) const {
}
+String String::get_slicec(CharType p_splitter, int p_slice) const {
+
+ if (empty())
+ return String();
+
+ if (p_slice<0)
+ return String();
+
+ const CharType *c=this->ptr();
+ int i=0;
+ int prev=0;
+ int count=0;
+ while(true) {
+
+
+ if (c[i]==0 || c[i]==p_splitter) {
+
+ if (p_slice==count) {
+
+ return substr(prev,i-prev);
+ } else {
+ count++;
+ prev=i+1;
+ }
+
+ }
+
+ i++;
+
+ }
+
+ return String(); //no find!
+
+}
+
Vector<String> String::split_spaces() const {
@@ -626,7 +691,7 @@ Vector<float> String::split_floats(const String &p_splitter,bool p_allow_empty)
if (end<0)
end=len;
if (p_allow_empty || (end>from))
- ret.push_back(String::to_double(&c_str()[from],end-from));
+ ret.push_back(String::to_double(&c_str()[from]));
if (end==len)
break;
@@ -654,8 +719,9 @@ Vector<float> String::split_floats_mk(const Vector<String> &p_splitters,bool p_a
spl_len=p_splitters[idx].length();
}
- if (p_allow_empty || (end>from))
- ret.push_back(String::to_double(&c_str()[from],end-from));
+ if (p_allow_empty || (end>from)) {
+ ret.push_back(String::to_double(&c_str()[from]));
+ }
if (end==len)
break;
@@ -980,7 +1046,7 @@ String String::num(double p_num,int p_decimals) {
}
-String String::num_int64(int64_t p_num) {
+String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
bool sign=p_num<0;
int64_t num=ABS(p_num);
@@ -989,7 +1055,7 @@ String String::num_int64(int64_t p_num) {
int chars=0;
do {
- n/=10;
+ n/=base;
chars++;
} while(n);
@@ -1001,8 +1067,15 @@ String String::num_int64(int64_t p_num) {
c[chars]=0;
n=num;
do {
- c[--chars]='0'+(n%10);
- n/=10;
+ int mod = n%base;
+ if (mod >= 10) {
+ char a = (capitalize_hex ? 'A' : 'a');
+ c[--chars]=a+(mod - 10);
+ } else {
+ c[--chars]='0'+mod;
+ }
+
+ n/=base;
} while(n);
if (sign)
@@ -1959,8 +2032,10 @@ float String::to_float() const {
return to_double();
}
-double String::to_double(const CharType* p_str, int p_len, const CharType **r_end) {
+double String::to_double(const CharType* p_str, const CharType **r_end) {
+ return built_in_strtod<CharType>(p_str,(CharType**)r_end);
+#if 0
#if 0
//ndef NO_USE_STDLIB
return wcstod(p_str,p_len<0?NULL:p_str+p_len);
@@ -2053,6 +2128,7 @@ double String::to_double(const CharType* p_str, int p_len, const CharType **r_en
return sign*(integer+decimal)*Math::pow(10,exp_sign*exp);
#endif
+#endif
}
int64_t String::to_int(const CharType* p_str,int p_len) {
@@ -2977,6 +3053,79 @@ 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)+"\n";
+ from=i+1;
+ last_space=-1;
+ }
+ }
+
+ if (from<length()) {
+ ret+=substr(from,length());
+ }
+
+ return ret;
+}
+
+String String::http_escape() const {
+ const CharString temp = utf8();
+ String res;
+ for (int i = 0; i < length(); ++i) {
+ CharType ord = temp[i];
+ if (ord == '.' || ord == '-' || ord == '_' || ord == '~' ||
+ (ord >= 'a' && ord <= 'z') ||
+ (ord >= 'A' && ord <= 'Z') ||
+ (ord >= '0' && ord <= '9')) {
+ res += ord;
+ } else {
+ char h_Val[3];
+ snprintf(h_Val, 3, "%.2X", ord);
+ res += "%";
+ res += h_Val;
+ }
+ }
+ return res;
+}
+
+String String::http_unescape() const {
+ String res;
+ for (int i = 0; i < length(); ++i) {
+ if (ord_at(i) == '%' && i+2 < length()) {
+ CharType ord1 = ord_at(i+1);
+ if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) {
+ CharType ord2 = ord_at(i+2);
+ if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) {
+ char bytes[2] = {ord1, ord2};
+ res += (char)strtol(bytes, NULL, 16);
+ i+=2;
+ }
+ } else {
+ res += ord_at(i);
+ }
+ } else {
+ res += ord_at(i);
+ }
+ }
+ return String::utf8(res.ascii());
+}
+
String String::c_unescape() const {
String escaped=*this;
@@ -3017,8 +3166,8 @@ String String::xml_escape(bool p_escape_quotes) const {
String str=*this;
str=str.replace("&","&amp;");
- str=str.replace("<","&gt;");
- str=str.replace(">","&lt;");
+ str=str.replace("<","&lt;");
+ str=str.replace(">","&gt;");
if (p_escape_quotes) {
str=str.replace("'","&apos;");
str=str.replace("\"","&quot;");
@@ -3070,12 +3219,12 @@ static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src,int p_src_len,Char
} else if (p_src_len>=4 && p_src[1]=='g' && p_src[2]=='t' && p_src[3]==';') {
if (p_dst)
- *p_dst='<';
+ *p_dst='>';
eat=4;
} else if (p_src_len>=4 && p_src[1]=='l' && p_src[2]=='t' && p_src[3]==';') {
if (p_dst)
- *p_dst='>';
+ *p_dst='<';
eat=4;
} else if (p_src_len>=5 && p_src[1]=='a' && p_src[2]=='m' && p_src[3]=='p' && p_src[4]==';') {
@@ -3264,8 +3413,11 @@ String String::path_to_file(const String& p_path) const {
String src=this->replace("\\","/").get_base_dir();
String dst=p_path.replace("\\","/").get_base_dir();
-
- return src.path_to(dst)+p_path.get_file();
+ String rel = src.path_to(dst);
+ if (rel==dst) // failed
+ return p_path;
+ else
+ return rel+p_path.get_file();
}
String String::path_to(const String& p_path) const {
@@ -3297,10 +3449,12 @@ String String::path_to(const String& p_path) const {
//nothing
} else {
//dos style
- String src_begin=src.get_slice("/",0);
- String dst_begin=dst.get_slice("/",0);
+ String src_begin=src.get_slicec('/',0);
+ String dst_begin=dst.get_slicec('/',0);
+
+ if (src_begin!=dst_begin)
+ return p_path; //impossible to do this
- ERR_FAIL_COND_V(src_begin!=dst_begin,p_path); //return dst absolute path
base=src_begin;
src=src.substr(src_begin.length(),src.length());
dst=dst.substr(dst_begin.length(),dst.length());
@@ -3437,7 +3591,7 @@ String String::percent_encode() const {
uint8_t c = cs[i];
if ( (c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='-' || c=='_' || c=='~' || c=='.') {
- char p[2]={c,0};
+ char p[2]={(char)c,0};
encoded+=p;
} else {
char p[4]={'%',0,0,0};
@@ -3514,4 +3668,270 @@ String rtoss(double p_val) {
return String::num_scientific(p_val);
}
+// Right-pad with a character.
+String String::rpad(int min_length, const String& character) const {
+ String s = *this;
+ int padding = min_length - s.length();
+ if (padding > 0) {
+ for (int i = 0; i < padding; i++) s = s + character;
+ }
+
+ return s;
+}
+// Left-pad with a character.
+String String::lpad(int min_length, const String& character) const {
+ String s = *this;
+ int padding = min_length - s.length();
+ if (padding > 0) {
+ for (int i = 0; i < padding; i++) s = character + s;
+ }
+ return s;
+}
+
+// sprintf is implemented in GDScript via:
+// "fish %s pie" % "frog"
+// "fish %s %d pie" % ["frog", 12]
+// In case of an error, the string returned is the error description and "error" is true.
+String String::sprintf(const Array& values, bool* error) const {
+ String formatted;
+ CharType* self = (CharType*)c_str();
+ int num_items = values.size();
+ bool in_format = false;
+ int value_index = 0;
+ int min_chars;
+ int min_decimals;
+ bool in_decimals;
+ bool pad_with_zeroes;
+ bool left_justified;
+ bool show_sign;
+
+ *error = true;
+
+ for (; *self; self++) {
+ const CharType c = *self;
+
+ if (in_format) { // We have % - lets see what else we get.
+ switch (c) {
+ case '%': { // Replace %% with %
+ formatted += chr(c);
+ in_format = false;
+ break;
+ }
+ case 'd': // Integer (signed)
+ case 'o': // Octal
+ case 'x': // Hexadecimal (lowercase)
+ case 'X': { // Hexadecimal (uppercase)
+ if (value_index >= values.size()) {
+ return "not enough arguments for format string";
+ }
+
+ if (!values[value_index].is_num()) {
+ return "a number is required";
+ }
+
+ int64_t value = values[value_index];
+ int base;
+ bool capitalize = false;
+ switch (c) {
+ case 'd': base = 10; break;
+ case 'o': base = 8; break;
+ case 'x': base = 16; break;
+ case 'X': base = 16; capitalize = true; break;
+ }
+ // Get basic number.
+ String str = String::num_int64(value, base, capitalize);
+
+ // Sign.
+ if (show_sign && value >= 0) {
+ str = str.insert(0, "+");
+ }
+
+ // Padding.
+ String pad_char = pad_with_zeroes ? String("0") : String(" ");
+ if (left_justified) {
+ str = str.rpad(min_chars, pad_char);
+ } else {
+ str = str.lpad(min_chars, pad_char);
+ }
+
+ formatted += str;
+ ++value_index;
+ in_format = false;
+
+ break;
+ }
+ case 'f': { // Float
+ if (value_index >= values.size()) {
+ return "not enough arguments for format string";
+ }
+
+ if (!values[value_index].is_num()) {
+ return "a number is required";
+ }
+
+ double value = values[value_index];
+ String str = String::num(value, min_decimals);
+
+ // Pad decimals out.
+ str = str.pad_decimals(min_decimals);
+
+ // Show sign
+ if (show_sign && value >= 0) {
+ str = str.insert(0, "+");
+ }
+
+ // Padding
+ if (left_justified) {
+ str = str.rpad(min_chars);
+ } else {
+ str = str.lpad(min_chars);
+ }
+
+ formatted += str;
+ ++value_index;
+ in_format = false;
+
+ break;
+ }
+ case 's': { // String
+ if (value_index >= values.size()) {
+ return "not enough arguments for format string";
+ }
+
+ String str = values[value_index];
+ // Padding.
+ if (left_justified) {
+ str = str.rpad(min_chars);
+ } else {
+ str = str.lpad(min_chars);
+ }
+
+ formatted += str;
+ ++value_index;
+ in_format = false;
+ break;
+ }
+ case 'c': {
+ if (value_index >= values.size()) {
+ return "not enough arguments for format string";
+ }
+
+ // Convert to character.
+ String str;
+ if (values[value_index].is_num()) {
+ int value = values[value_index];
+ if (value < 0) {
+ return "unsigned byte integer is lower than maximum";
+ } else if (value > 255) {
+ return "unsigned byte integer is greater than maximum";
+ }
+ str = chr(values[value_index]);
+ } else if (values[value_index].get_type() == Variant::STRING) {
+ str = values[value_index];
+ if (str.length() != 1) {
+ return "%c requires number or single-character string";
+ }
+ } else {
+ return "%c requires number or single-character string";
+ }
+
+ // Padding.
+ if (left_justified) {
+ str = str.rpad(min_chars);
+ } else {
+ str = str.lpad(min_chars);
+ }
+
+ formatted += str;
+ ++value_index;
+ in_format = false;
+ break;
+ }
+ case '-': { // Left justify
+ left_justified = true;
+ break;
+ }
+ case '+': { // Show + if positive.
+ show_sign = true;
+ break;
+ }
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9': {
+ int n = c - '0';
+ if (in_decimals) {
+ min_decimals *= 10;
+ min_decimals += n;
+ } else {
+ if (c == '0' && min_chars == 0) {
+ pad_with_zeroes = true;
+ } else {
+ min_chars *= 10;
+ min_chars += n;
+ }
+ }
+ break;
+ }
+ case '.': { // Float separtor.
+ if (in_decimals) {
+ return "too many decimal points in format";
+ }
+ in_decimals = true;
+ min_decimals = 0; // We want to add the value manually.
+ break;
+ }
+
+ case '*': { // Dyanmic width, based on value.
+ if (value_index >= values.size()) {
+ return "not enough arguments for format string";
+ }
+
+ if (!values[value_index].is_num()) {
+ return "* wants number";
+ }
+
+ int size = values[value_index];
+
+ if (in_decimals) {
+ min_decimals = size;
+ } else {
+ min_chars = size;
+ }
+
+ ++value_index;
+ break;
+ }
+
+ default: {
+ return "unsupported format character";
+ }
+ }
+ } else { // Not in format string.
+ switch (c) {
+ case '%':
+ in_format = true;
+ // Back to defaults:
+ min_chars = 0;
+ min_decimals = 6;
+ pad_with_zeroes = false;
+ left_justified = false;
+ show_sign = false;
+ in_decimals = false;
+ break;
+ default:
+ formatted += chr(c);
+ }
+ }
+ }
+
+ if (in_format) {
+ return "incomplete format";
+ }
+
+ if (value_index != values.size()) {
+ return "not all arguments converted during string formatting";
+ }
+
+ *error = false;
+ return formatted;
+}
diff --git a/core/ustring.h b/core/ustring.h
index 8fe3a95463..2f3c4bff4d 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#include "typedefs.h"
#include "vector.h"
+#include "array.h"
/**
@author red <red@killy>
@@ -127,10 +128,13 @@ public:
String insert(int p_at_pos,String p_string) const;
String pad_decimals(int p_digits) const;
String pad_zeros(int p_digits) const;
+ String lpad(int min_length,const String& character=" ") const;
+ String rpad(int min_length,const String& character=" ") const;
+ String sprintf(const Array& values, bool* error) const;
static String num(double p_num,int p_decimals=-1);
static String num_scientific(double p_num);
static String num_real(double p_num);
- static String num_int64(int64_t p_num);
+ static String num_int64(int64_t p_num,int base=10,bool capitalize_hex=false);
static String chr(CharType p_char);
static String md5(const uint8_t *p_md5);
bool is_numeric() const;
@@ -142,12 +146,14 @@ public:
int64_t to_int64() const;
static int to_int(const char* p_str);
static double to_double(const char* p_str);
- static double to_double(const CharType* p_str, int p_len=-1, const CharType **r_end=NULL);
+ static double to_double(const CharType* p_str, const CharType **r_end=NULL);
static int64_t to_int(const CharType* p_str,int p_len=-1);
String capitalize() const;
+ String camelcase_to_underscore() const;
int get_slice_count(String p_splitter) const;
String get_slice(String p_splitter,int p_slice) const;
+ String get_slicec(CharType splitter,int p_slice) const;
Vector<String> split(const String &p_splitter,bool p_allow_empty=true) const;
Vector<String> split_spaces() const;
@@ -201,9 +207,12 @@ public:
String xml_escape(bool p_escape_quotes=false) const;
String xml_unescape() const;
+ String http_escape() const;
+ String http_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 2f0eca9e91..c6a55b10e6 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,7 +32,7 @@
#include "scene/main/node.h"
#include "scene/gui/control.h"
#include "io/marshalls.h"
-
+#include "core_string_names.h"
@@ -258,12 +258,12 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) {
case MATRIX32: {
- static const Type invalid[]={
+ static const Type valid[]={
TRANSFORM,
NIL
};
- invalid_types=invalid;
+ valid_types=valid;
} break;
case QUAT: {
@@ -445,6 +445,256 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) {
}
+bool Variant::can_convert_strict(Variant::Type p_type_from,Variant::Type p_type_to) {
+
+ if (p_type_from==p_type_to)
+ return true;
+ if (p_type_to==NIL && p_type_from!=NIL) //nil can convert to anything
+ return true;
+
+ if (p_type_from == NIL) {
+ return (p_type_to == OBJECT);
+ };
+
+ const Type *valid_types=NULL;
+ const Type *invalid_types=NULL;
+
+ switch(p_type_to) {
+ case BOOL: {
+
+ static const Type valid[]={
+ INT,
+ REAL,
+ //STRING,
+ NIL,
+ };
+
+ valid_types=valid;
+ } break;
+ case INT: {
+
+ static const Type valid[]={
+ BOOL,
+ REAL,
+ //STRING,
+ NIL,
+ };
+
+ valid_types=valid;
+
+ } break;
+ case REAL: {
+
+ static const Type valid[]={
+ BOOL,
+ INT,
+ //STRING,
+ NIL,
+ };
+
+ valid_types=valid;
+
+ } break;
+ case STRING: {
+
+
+ static const Type valid[]={
+ NODE_PATH,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case MATRIX32: {
+
+
+ static const Type valid[]={
+ TRANSFORM,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case QUAT: {
+
+ static const Type valid[]={
+ MATRIX3,
+ NIL
+ };
+
+ valid_types=valid;
+
+ } break;
+ case MATRIX3: {
+
+ static const Type valid[]={
+ QUAT,
+ NIL
+ };
+
+ valid_types=valid;
+
+
+ } break;
+ case TRANSFORM: {
+
+ static const Type valid[]={
+ MATRIX32,
+ QUAT,
+ MATRIX3,
+ NIL
+ };
+
+ valid_types=valid;
+
+ } break;
+
+ case COLOR: {
+
+ static const Type valid[] = {
+ STRING,
+ INT,
+ NIL,
+ };
+
+ valid_types = valid;
+
+ } break;
+
+ case _RID: {
+
+ static const Type valid[]={
+ OBJECT,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case OBJECT: {
+
+ static const Type valid[]={
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case NODE_PATH: {
+
+ static const Type valid[]={
+ STRING,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case ARRAY: {
+
+
+ static const Type valid[]={
+ RAW_ARRAY,
+ INT_ARRAY,
+ STRING_ARRAY,
+ REAL_ARRAY,
+ COLOR_ARRAY,
+ VECTOR2_ARRAY,
+ VECTOR3_ARRAY,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ // arrays
+ case RAW_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case INT_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+ valid_types=valid;
+ } break;
+ case REAL_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+
+ valid_types=valid;
+ } break;
+ case STRING_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+ valid_types=valid;
+ } break;
+ case VECTOR2_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+ valid_types=valid;
+
+ } break;
+ case VECTOR3_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+ valid_types=valid;
+
+ } break;
+ case COLOR_ARRAY: {
+
+ static const Type valid[]={
+ ARRAY,
+ NIL
+ };
+
+ valid_types=valid;
+
+ } break;
+ default: {}
+ }
+
+
+ if (valid_types) {
+
+ int i=0;
+ while(valid_types[i]!=NIL) {
+
+ if (p_type_from==valid_types[i])
+ return true;
+ i++;
+ }
+ } else if (invalid_types) {
+
+
+ int i=0;
+ while(invalid_types[i]!=NIL) {
+
+ if (p_type_from==invalid_types[i])
+ return false;
+ i++;
+ }
+ }
+
+ return false;
+
+}
+
bool Variant::operator==(const Variant& p_variant) const {
if (type!=p_variant.type) //evaluation of operator== needs to be more strict
@@ -456,6 +706,15 @@ bool Variant::operator==(const Variant& p_variant) const {
}
+bool Variant::operator<(const Variant& p_variant) const {
+ if (type!=p_variant.type) //if types differ, then order by type first
+ return type<p_variant.type;
+ bool v;
+ Variant r;
+ evaluate(OP_LESS,*this,p_variant,r,v);
+ return r;
+}
+
bool Variant::is_zero() const {
switch( type ) {
@@ -523,7 +782,7 @@ bool Variant::is_zero() const {
} break;
case QUAT: {
- *reinterpret_cast<const Quat*>(_data._mem)==Quat();
+ return *reinterpret_cast<const Quat*>(_data._mem)==Quat();
} break;
case MATRIX3: {
@@ -619,6 +878,63 @@ bool Variant::is_zero() const {
return false;
}
+
+bool Variant::is_one() const {
+
+ switch( type ) {
+ case NIL: {
+
+ return true;
+ } break;
+
+ // atomic types
+ case BOOL: {
+
+ return _data._bool==true;
+ } break;
+ case INT: {
+
+ return _data._int==1;
+
+ } break;
+ case REAL: {
+
+ return _data._real==1;
+
+ } break;
+ case VECTOR2: {
+
+ return *reinterpret_cast<const Vector2*>(_data._mem)==Vector2(1,1);
+
+ } break;
+ case RECT2: {
+
+ return *reinterpret_cast<const Rect2*>(_data._mem)==Rect2(1,1,1,1);
+
+ } break;
+ case VECTOR3: {
+
+ return *reinterpret_cast<const Vector3*>(_data._mem)==Vector3(1,1,1);
+
+ } break;
+ case PLANE: {
+
+ return *reinterpret_cast<const Plane*>(_data._mem)==Plane(1,1,1,1);
+
+ } break;
+ case COLOR: {
+
+ return *reinterpret_cast<const Color*>(_data._mem)==Color(1,1,1,1);
+
+ } break;
+
+ default: { return !is_zero(); }
+ }
+
+ return false;
+}
+
+
void Variant::reference(const Variant& p_variant) {
@@ -1276,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;
@@ -1394,6 +1718,10 @@ Variant::operator Color() const {
if (type==COLOR)
return *reinterpret_cast<const Color*>(_data._mem);
+ else if (type==STRING)
+ return Color::html( operator String() );
+ else if (type==INT)
+ return Color::hex( operator int() );
else
return Color();
}
@@ -1430,8 +1758,16 @@ Variant::operator RID() const {
return *reinterpret_cast<const RID*>(_data._mem);
else if (type==OBJECT && !_get_obj().ref.is_null()) {
return _get_obj().ref.get_rid();
- } else
+ } else if (type==OBJECT && _get_obj().obj) {
+ Variant::CallError ce;
+ Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid,NULL,0,ce);
+ if (ce.error==Variant::CallError::CALL_OK && ret.get_type()==Variant::_RID) {
+ return ret;
+ }
return RID();
+ } else {
+ return RID();
+ }
}
Variant::operator Object*() const {
@@ -2631,8 +2967,13 @@ Variant Variant::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
return ret;
}
+void Variant::construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct,void *p_construct_ud) {
+
+ r_value=Variant();
+}
+
-String Variant::get_construct_string() const {
+String Variant::get_construct_string(ObjectDeConstruct p_obj_deconstruct,void *p_deconstruct_ud) const {
switch( type ) {
@@ -2640,7 +2981,7 @@ String Variant::get_construct_string() const {
case BOOL: return _data._bool ? "true" : "false";
case INT: return String::num(_data._int);
case REAL: return String::num(_data._real);
- case STRING: return "\""+*reinterpret_cast<const String*>(_data._mem)+"\"";
+ case STRING: return "\""+reinterpret_cast<const String*>(_data._mem)->c_escape()+"\"";
case VECTOR2: return "Vector2("+operator Vector2()+")";
case RECT2: return "Rect2("+operator Rect2()+")";
case MATRIX32: return "Matrix32("+operator Matrix32()+")";
@@ -2651,7 +2992,7 @@ String Variant::get_construct_string() const {
case QUAT: return "Quat("+operator Quat()+")";
case MATRIX3: return "Matrix3("+operator Matrix3()+")";
case TRANSFORM: return "Transform("+operator Transform()+")";
- case NODE_PATH: return "@\""+operator NodePath()+"\"";
+ case NODE_PATH: return "@\""+String(operator NodePath()).c_escape()+"\"";
case INPUT_EVENT: return "InputEvent()";
case COLOR: return "Color("+String::num( operator Color().r)+","+String::num( operator Color().g)+","+String::num( operator Color().b)+","+String::num( operator Color().a)+")" ;
case DICTIONARY: {
@@ -2667,8 +3008,8 @@ String Variant::get_construct_string() const {
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
_VariantStrPair sp;
- sp.key=E->get().get_construct_string();
- sp.value=d[E->get()].get_construct_string();
+ sp.key=E->get().get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
+ sp.value=d[E->get()].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
pairs.push_back(sp);
}
@@ -2686,50 +3027,50 @@ String Variant::get_construct_string() const {
case VECTOR3_ARRAY: {
DVector<Vector3> vec = operator DVector<Vector3>();
- String str="[";
+ String str="Vector3Array([";
for(int i=0;i<vec.size();i++) {
if (i>0)
str+=", ";
str+=Variant( vec[i] ).get_construct_string();
}
- return str+"]";
+ return str+"])";
} break;
case STRING_ARRAY: {
DVector<String> vec = operator DVector<String>();
- String str="[";
+ String str="StringArray([";
for(int i=0;i<vec.size();i++) {
if (i>0)
str+=", ";
str=str+=Variant( vec[i] ).get_construct_string();
}
- return str+"]";
+ return str+"])";
} break;
case INT_ARRAY: {
DVector<int> vec = operator DVector<int>();
- String str="[";
+ String str="IntArray([";
for(int i=0;i<vec.size();i++) {
if (i>0)
str+=", ";
str=str+itos(vec[i]);
}
- return str+"]";
+ return str+"])";
} break;
case REAL_ARRAY: {
DVector<real_t> vec = operator DVector<real_t>();
- String str="[";
+ String str="FloatArray([";
for(int i=0;i<vec.size();i++) {
if (i>0)
str+=", ";
str=str+rtos(vec[i]);
}
- return str+"]";
+ return str+"])";
} break;
case ARRAY: {
@@ -2738,16 +3079,20 @@ String Variant::get_construct_string() const {
for (int i=0; i<arr.size(); i++) {
if (i)
str+=", ";
- str += arr[i].get_construct_string();
+ str += arr[i].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
};
return str+"]";
} break;
case OBJECT: {
- if (_get_obj().obj)
- return _get_obj().obj->get_type()+".new()";
- else
+ if (_get_obj().obj) {
+ if (p_obj_deconstruct) {
+ return "Object(\""+p_obj_deconstruct(Variant(*this),p_deconstruct_ud).c_escape()+")";
+ } else {
+ return _get_obj().obj->get_type()+".new()";
+ }
+ } else
return "null";
} break;
diff --git a/core/variant.h b/core/variant.h
index 47fc3f43ac..8fd9662c36 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -165,7 +165,8 @@ public:
_FORCE_INLINE_ Type get_type() const { return type; }
static String get_type_name(Variant::Type p_type);
- static bool can_convert(Type p_type_from,Type p_type_to);
+ static bool can_convert(Type p_type_from, Type p_type_to);
+ static bool can_convert_strict(Type p_type_from, Type p_type_to);
@@ -184,6 +185,7 @@ public:
_FORCE_INLINE_ bool is_array() const { return type>=ARRAY; };
bool is_shared() const;
bool is_zero() const;
+ bool is_one() const;
operator bool() const;
operator signed int() const;
@@ -408,7 +410,8 @@ public:
//argsVariant call()
- bool operator==(const Variant& p_variant) const;
+ bool operator==(const Variant& p_variant) const;
+ bool operator<(const Variant& p_variant) const;
uint32_t hash() const;
bool booleanize(bool &valid) const;
@@ -419,7 +422,11 @@ public:
static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value);
- String get_construct_string() const;
+ typedef String (*ObjectDeConstruct)(const Variant& p_object,void *ud);
+ typedef void (*ObjectConstruct)(const String& p_text,void *ud,Variant& r_value);
+
+ String get_construct_string(ObjectDeConstruct p_obj_deconstruct=NULL,void *p_deconstruct_ud=NULL) const;
+ static void construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct=NULL,void *p_construct_ud=NULL);
void operator=(const Variant& p_variant); // only this is enough for all the other types
Variant(const Variant& p_variant);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 93a9e6475f..51d683f1fe 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -285,6 +285,36 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1R(String,pad_decimals);
VCALL_LOCALMEM1R(String,pad_zeros);
+ static void _call_String_to_ascii(Variant& r_ret,Variant& p_self,const Variant** p_args) {
+
+ String *s = reinterpret_cast<String*>(p_self._data._mem);
+ CharString charstr = s->ascii();
+
+ ByteArray retval;
+ size_t len = charstr.length();
+ retval.resize(len);
+ ByteArray::Write w = retval.write();
+ copymem(w.ptr(), charstr.ptr(), len);
+ w = DVector<uint8_t>::Write();
+
+ r_ret = retval;
+ }
+
+ static void _call_String_to_utf8(Variant& r_ret,Variant& p_self,const Variant** p_args) {
+
+ String *s = reinterpret_cast<String*>(p_self._data._mem);
+ CharString charstr = s->utf8();
+
+ ByteArray retval;
+ size_t len = charstr.length();
+ retval.resize(len);
+ ByteArray::Write w = retval.write();
+ copymem(w.ptr(), charstr.ptr(), len);
+ w = DVector<uint8_t>::Write();
+
+ r_ret = retval;
+ }
+
VCALL_LOCALMEM0R(Vector2,normalized);
VCALL_LOCALMEM0R(Vector2,length);
@@ -303,7 +333,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1R(Vector2,dot);
VCALL_LOCALMEM1R(Vector2,slide);
VCALL_LOCALMEM1R(Vector2,reflect);
- VCALL_LOCALMEM0R(Vector2,atan2);
+ VCALL_LOCALMEM0R(Vector2,angle);
// VCALL_LOCALMEM1R(Vector2,cross);
VCALL_LOCALMEM0R(Rect2,get_area);
@@ -329,6 +359,8 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1R(Vector3, dot);
VCALL_LOCALMEM1R(Vector3, cross);
VCALL_LOCALMEM0R(Vector3, abs);
+ VCALL_LOCALMEM0R(Vector3, floor);
+ VCALL_LOCALMEM0R(Vector3, ceil);
VCALL_LOCALMEM1R(Vector3, distance_to);
VCALL_LOCALMEM1R(Vector3, distance_squared_to);
VCALL_LOCALMEM1R(Vector3, slide);
@@ -377,6 +409,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(Quat,normalized);
VCALL_LOCALMEM0R(Quat,inverse);
VCALL_LOCALMEM1R(Quat,dot);
+ VCALL_LOCALMEM1R(Quat,xform);
VCALL_LOCALMEM2R(Quat,slerp);
VCALL_LOCALMEM2R(Quat,slerpni);
VCALL_LOCALMEM4R(Quat,cubic_slerp);
@@ -426,6 +459,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0(Array,sort);
VCALL_LOCALMEM2(Array,sort_custom);
VCALL_LOCALMEM0(Array,invert);
+ VCALL_LOCALMEM0R(Array,is_shared);
static void _call_ByteArray_get_string_from_ascii(Variant& r_ret,Variant& p_self,const Variant** p_args) {
@@ -511,7 +545,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1(ColorArray,append_array);
#define VCALL_PTR0(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
#define VCALL_PTR0R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
#define VCALL_PTR1(m_type,m_method)\
@@ -519,7 +553,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
#define VCALL_PTR1R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
#define VCALL_PTR2(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
#define VCALL_PTR2R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
#define VCALL_PTR3(m_type,m_method)\
@@ -531,7 +565,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
#define VCALL_PTR4R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3]); }
#define VCALL_PTR5(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
#define VCALL_PTR5R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
@@ -684,8 +718,10 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_PTR0R( InputEvent, is_pressed );
VCALL_PTR1R( InputEvent, is_action );
+ VCALL_PTR1R( InputEvent, is_action_pressed );
+ VCALL_PTR1R( InputEvent, is_action_released );
VCALL_PTR0R( InputEvent, is_echo );
- //VCALL_PTR2( InputEvent, set_as_action );
+ VCALL_PTR2( InputEvent, set_as_action );
struct ConstructData {
@@ -719,6 +755,12 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
r_ret=Rect2(*p_args[0],*p_args[1],*p_args[2],*p_args[3]);
}
+ static void Matrix32_init2(Variant& r_ret,const Variant** p_args) {
+
+ Matrix32 m(*p_args[0], *p_args[1]);
+ r_ret=m;
+ }
+
static void Matrix32_init3(Variant& r_ret,const Variant** p_args) {
Matrix32 m;
@@ -757,6 +799,11 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
r_ret=Quat(*p_args[0],*p_args[1],*p_args[2],*p_args[3]);
}
+ static void Quat_init2(Variant& r_ret,const Variant** p_args) {
+
+ r_ret=Quat(((Vector3)(*p_args[0])),((float)(*p_args[1])));
+ }
+
static void Color_init1(Variant& r_ret,const Variant** p_args) {
r_ret=Color(*p_args[0],*p_args[1],*p_args[2],*p_args[3]);
@@ -1026,7 +1073,7 @@ Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int
case STRING_ARRAY: return (StringArray(*p_args[0]));
case VECTOR2_ARRAY: return (Vector2Array(*p_args[0])); // 25
case VECTOR3_ARRAY: return (Vector3Array(*p_args[0])); // 25
- case COLOR_ARRAY: return (Color(*p_args[0]));
+ case COLOR_ARRAY: return (ColorArray(*p_args[0]));
default: return Variant();
}
}
@@ -1089,7 +1136,7 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
if (fd.returns)
ret.name="ret";
mi.return_val=ret;
-#endif
+#endif
p_list->push_back(mi);
}
@@ -1106,6 +1153,7 @@ void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_lis
const _VariantCall::ConstructData &cd = E->get();
MethodInfo mi;
mi.name=Variant::get_type_name(p_type);
+ mi.return_val.type=p_type;
for(int i=0;i<cd.arg_count;i++) {
PropertyInfo pi;
@@ -1128,6 +1176,7 @@ void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_lis
pi.name="from";
pi.type=Variant::Type(i);
mi.arguments.push_back(pi);
+ mi.return_val.type=p_type;
p_list->push_back(mi);
}
}
@@ -1207,9 +1256,10 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(STRING,STRING,String,capitalize,varray());
ADDFUNC2(STRING,STRING_ARRAY,String,split,STRING,"divisor",BOOL,"allow_empty",varray(true));
ADDFUNC2(STRING,REAL_ARRAY,String,split_floats,STRING,"divisor",BOOL,"allow_empty",varray(true));
- ADDFUNC0(STRING,STRING,String,to_upper,varray());
+ ADDFUNC0(STRING,STRING,String,to_upper,varray());
ADDFUNC0(STRING,STRING,String,to_lower,varray());
+
ADDFUNC1(STRING,STRING,String,left,INT,"pos",varray());
ADDFUNC1(STRING,STRING,String,right,INT,"pos",varray());
ADDFUNC0(STRING,STRING,String,strip_edges,varray());
@@ -1241,9 +1291,13 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(STRING,STRING,String,pad_decimals,INT,"digits",varray());
ADDFUNC1(STRING,STRING,String,pad_zeros,INT,"digits",varray());
+ ADDFUNC0(STRING,STRING,String,to_ascii,varray());
+ ADDFUNC0(STRING,STRING,String,to_utf8,varray());
+
+
ADDFUNC0(VECTOR2,VECTOR2,Vector2,normalized,varray());
ADDFUNC0(VECTOR2,REAL,Vector2,length,varray());
- ADDFUNC0(VECTOR2,REAL,Vector2,atan2,varray());
+ ADDFUNC0(VECTOR2,REAL,Vector2,angle,varray());
ADDFUNC0(VECTOR2,REAL,Vector2,length_squared,varray());
ADDFUNC1(VECTOR2,REAL,Vector2,distance_to,VECTOR2,"to",varray());
ADDFUNC1(VECTOR2,REAL,Vector2,distance_squared_to,VECTOR2,"to",varray());
@@ -1258,8 +1312,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(VECTOR2,VECTOR2,Vector2,snapped,VECTOR2,"by",varray());
ADDFUNC0(VECTOR2,REAL,Vector2,get_aspect,varray());
ADDFUNC1(VECTOR2,REAL,Vector2,dot,VECTOR2,"with",varray());
- ADDFUNC1(VECTOR2,REAL,Vector2,slide,VECTOR2,"vec",varray());
- ADDFUNC1(VECTOR2,REAL,Vector2,reflect,VECTOR2,"vec",varray());
+ ADDFUNC1(VECTOR2,VECTOR2,Vector2,slide,VECTOR2,"vec",varray());
+ ADDFUNC1(VECTOR2,VECTOR2,Vector2,reflect,VECTOR2,"vec",varray());
//ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
ADDFUNC0(RECT2,REAL,Rect2,get_area,varray());
@@ -1285,6 +1339,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(VECTOR3,REAL,Vector3,dot,VECTOR3,"b",varray());
ADDFUNC1(VECTOR3,VECTOR3,Vector3,cross,VECTOR3,"b",varray());
ADDFUNC0(VECTOR3,VECTOR3,Vector3,abs,varray());
+ ADDFUNC0(VECTOR3,VECTOR3,Vector3,floor,varray());
+ ADDFUNC0(VECTOR3,VECTOR3,Vector3,ceil,varray());
ADDFUNC1(VECTOR3,REAL,Vector3,distance_to,VECTOR3,"b",varray());
ADDFUNC1(VECTOR3,REAL,Vector3,distance_squared_to,VECTOR3,"b",varray());
ADDFUNC1(VECTOR3,VECTOR3,Vector3,slide,VECTOR3,"by",varray());
@@ -1306,6 +1362,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(QUAT,QUAT,Quat,normalized,varray());
ADDFUNC0(QUAT,QUAT,Quat,inverse,varray());
ADDFUNC1(QUAT,REAL,Quat,dot,QUAT,"b",varray());
+ ADDFUNC1(QUAT,VECTOR3,Quat,xform,VECTOR3,"v",varray());
ADDFUNC2(QUAT,QUAT,Quat,slerp,QUAT,"b",REAL,"t",varray());
ADDFUNC2(QUAT,QUAT,Quat,slerpni,QUAT,"b",REAL,"t",varray());
ADDFUNC4(QUAT,QUAT,Quat,cubic_slerp,QUAT,"b",QUAT,"pre_a",QUAT,"post_b",REAL,"t",varray());
@@ -1373,6 +1430,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(ARRAY,NIL,Array,sort,varray());
ADDFUNC2(ARRAY,NIL,Array,sort_custom,OBJECT,"obj",STRING,"func",varray());
ADDFUNC0(ARRAY,NIL,Array,invert,varray());
+ ADDFUNC0(ARRAY,BOOL,Array,is_shared,varray());
ADDFUNC0(RAW_ARRAY,INT,ByteArray,size,varray());
ADDFUNC2(RAW_ARRAY,NIL,ByteArray,set,INT,"idx",INT,"byte",varray());
@@ -1483,15 +1541,17 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(TRANSFORM,NIL,Transform,xform,NIL,"v",varray());
ADDFUNC1(TRANSFORM,NIL,Transform,xform_inv,NIL,"v",varray());
-#ifdef DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
_VariantCall::type_funcs[Variant::TRANSFORM].functions["xform"].returns=true;
_VariantCall::type_funcs[Variant::TRANSFORM].functions["xform_inv"].returns=true;
-#endif
+#endif
ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_pressed,varray());
ADDFUNC1(INPUT_EVENT,BOOL,InputEvent,is_action,STRING,"action",varray());
+ ADDFUNC1(INPUT_EVENT,BOOL,InputEvent,is_action_pressed,STRING,"is_action_pressed",varray());
+ ADDFUNC1(INPUT_EVENT,BOOL,InputEvent,is_action_released,STRING,"is_action_released",varray());
ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_echo,varray());
- //ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray());
+ ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray());
/* REGISTER CONSTRUCTORS */
@@ -1500,6 +1560,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
_VariantCall::add_constructor(_VariantCall::Rect2_init1,Variant::RECT2,"pos",Variant::VECTOR2,"size",Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Rect2_init2,Variant::RECT2,"x",Variant::REAL,"y",Variant::REAL,"width",Variant::REAL,"height",Variant::REAL);
+ _VariantCall::add_constructor(_VariantCall::Matrix32_init2,Variant::MATRIX32,"rot",Variant::REAL,"pos",Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Matrix32_init3,Variant::MATRIX32,"x_axis",Variant::VECTOR2,"y_axis",Variant::VECTOR2,"origin",Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Vector3_init1,Variant::VECTOR3,"x",Variant::REAL,"y",Variant::REAL,"z",Variant::REAL);
@@ -1509,6 +1570,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
_VariantCall::add_constructor(_VariantCall::Plane_init3,Variant::PLANE,"normal",Variant::VECTOR3,"d",Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Quat_init1,Variant::QUAT,"x",Variant::REAL,"y",Variant::REAL,"z",Variant::REAL,"w",Variant::REAL);
+ _VariantCall::add_constructor(_VariantCall::Quat_init2,Variant::QUAT,"axis",Variant::VECTOR3,"angle",Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Color_init1,Variant::COLOR,"r",Variant::REAL,"g",Variant::REAL,"b",Variant::REAL,"a",Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Color_init2,Variant::COLOR,"r",Variant::REAL,"g",Variant::REAL,"b",Variant::REAL);
@@ -1579,9 +1641,3 @@ void unregister_variant_methods() {
}
-
-
-
-
-
-
diff --git a/core/variant_call_bind.h b/core/variant_call_bind.h
index 39fe25e8c7..613669203d 100644
--- a/core/variant_call_bind.h
+++ b/core/variant_call_bind.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/variant_construct_string.cpp b/core/variant_construct_string.cpp
new file mode 100644
index 0000000000..0308fd3180
--- /dev/null
+++ b/core/variant_construct_string.cpp
@@ -0,0 +1,433 @@
+
+#include "variant.h"
+
+class VariantConstruct {
+
+ enum TokenType {
+ TK_CURLY_BRACKET_OPEN,
+ TK_CURLY_BRACKET_CLOSE,
+ TK_BRACKET_OPEN,
+ TK_BRACKET_CLOSE,
+ TK_IDENTIFIER,
+ TK_STRING,
+ TK_NUMBER,
+ TK_COLON,
+ TK_COMMA,
+ TK_EOF,
+ TK_MAX
+ };
+
+ enum Expecting {
+
+ EXPECT_OBJECT,
+ EXPECT_OBJECT_KEY,
+ EXPECT_COLON,
+ EXPECT_OBJECT_VALUE,
+ };
+
+ struct Token {
+
+ TokenType type;
+ Variant value;
+ };
+
+ static const char * tk_name[TK_MAX];
+
+ static String _print_var(const Variant& p_var);
+
+ static Error _get_token(const CharType *p_str,int &index, int p_len,Token& r_token,int &line,String &r_err_str);
+ static Error _parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
+ static Error _parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
+ static Error _parse_dict(Dictionary &object,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
+
+public:
+
+ static Error parse(const String& p_string,Variant& r_ret,String &r_err_str,int &r_err_line,Variant::ObjectConstruct* p_construct,void* p_ud);
+};
+
+
+const char * VariantConstruct::tk_name[TK_MAX] = {
+ "'{'",
+ "'}'",
+ "'['",
+ "']'",
+ "identifier",
+ "string",
+ "number",
+ "':'",
+ "','",
+ "EOF",
+};
+
+
+
+Error VariantConstruct::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_token,int &line,String &r_err_str) {
+
+ while (true) {
+ switch(p_str[idx]) {
+
+ case '\n': {
+
+ line++;
+ idx++;
+ break;
+ };
+ case 0: {
+ r_token.type=TK_EOF;
+ return OK;
+ } break;
+ case '{': {
+
+ r_token.type=TK_CURLY_BRACKET_OPEN;
+ idx++;
+ return OK;
+ };
+ case '}': {
+
+ r_token.type=TK_CURLY_BRACKET_CLOSE;
+ idx++;
+ return OK;
+ };
+ case '[': {
+
+ r_token.type=TK_BRACKET_OPEN;
+ idx++;
+ return OK;
+ };
+ case ']': {
+
+ r_token.type=TK_BRACKET_CLOSE;
+ idx++;
+ return OK;
+ };
+ case ':': {
+
+ r_token.type=TK_COLON;
+ idx++;
+ return OK;
+ };
+ case ',': {
+
+ r_token.type=TK_COMMA;
+ idx++;
+ return OK;
+ };
+ case '"': {
+
+ idx++;
+ String str;
+ while(true) {
+ if (p_str[idx]==0) {
+ r_err_str="Unterminated String";
+ return ERR_PARSE_ERROR;
+ } else if (p_str[idx]=='"') {
+ idx++;
+ break;
+ } else if (p_str[idx]=='\\') {
+ //escaped characters...
+ idx++;
+ CharType next = p_str[idx];
+ if (next==0) {
+ r_err_str="Unterminated String";
+ return ERR_PARSE_ERROR;
+ }
+ CharType res=0;
+
+ switch(next) {
+
+ case 'b': res=8; break;
+ case 't': res=9; break;
+ case 'n': res=10; break;
+ case 'f': res=12; break;
+ case 'r': res=13; break;
+ case '\"': res='\"'; break;
+ case '\\': res='\\'; break;
+ case '/': res='/'; break; //wtf
+ case 'u': {
+ //hexnumbarh - oct is deprecated
+
+
+ for(int j=0;j<4;j++) {
+ CharType c = p_str[idx+j+1];
+ if (c==0) {
+ r_err_str="Unterminated String";
+ return ERR_PARSE_ERROR;
+ }
+ if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) {
+
+ r_err_str="Malformed hex constant in string";
+ return ERR_PARSE_ERROR;
+ }
+ CharType v;
+ if (c>='0' && c<='9') {
+ v=c-'0';
+ } else if (c>='a' && c<='f') {
+ v=c-'a';
+ v+=10;
+ } else if (c>='A' && c<='F') {
+ v=c-'A';
+ v+=10;
+ } else {
+ ERR_PRINT("BUG");
+ v=0;
+ }
+
+ res<<=4;
+ res|=v;
+
+
+ }
+ idx+=4; //will add at the end anyway
+
+
+ } break;
+ default: {
+
+ r_err_str="Invalid escape sequence";
+ return ERR_PARSE_ERROR;
+ } break;
+ }
+
+ str+=res;
+
+ } else {
+ if (p_str[idx]=='\n')
+ line++;
+ str+=p_str[idx];
+ }
+ idx++;
+ }
+
+ r_token.type=TK_STRING;
+ r_token.value=str;
+ return OK;
+
+ } break;
+ default: {
+
+ if (p_str[idx]<=32) {
+ idx++;
+ break;
+ }
+
+ if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) {
+ //a number
+ const CharType *rptr;
+ double number = String::to_double(&p_str[idx],&rptr);
+ idx+=(rptr - &p_str[idx]);
+ r_token.type=TK_NUMBER;
+ r_token.value=number;
+ return OK;
+
+ } else if ((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
+
+ String id;
+
+ while((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
+
+ id+=p_str[idx];
+ idx++;
+ }
+
+ r_token.type=TK_IDENTIFIER;
+ r_token.value=id;
+ return OK;
+ } else {
+ r_err_str="Unexpected character.";
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+ }
+ }
+
+ return ERR_PARSE_ERROR;
+}
+
+
+
+Error VariantConstruct::_parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+
+ if (token.type==TK_CURLY_BRACKET_OPEN) {
+
+ Dictionary d;
+ Error err = _parse_dict(d,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+ if (err)
+ return err;
+ value=d;
+ return OK;
+ } else if (token.type==TK_BRACKET_OPEN) {
+
+ Array a;
+ Error err = _parse_array(a,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+ if (err)
+ return err;
+ value=a;
+ return OK;
+
+ } else if (token.type==TK_IDENTIFIER) {
+
+ String id = token.value;
+ if (id=="true")
+ value=true;
+ else if (id=="false")
+ value=false;
+ else if (id=="null")
+ value=Variant();
+ else {
+ r_err_str="Expected 'true','false' or 'null', got '"+id+"'.";
+ return ERR_PARSE_ERROR;
+ }
+ return OK;
+
+ } else if (token.type==TK_NUMBER) {
+
+ value=token.value;
+ return OK;
+ } else if (token.type==TK_STRING) {
+
+ value=token.value;
+ return OK;
+ } else {
+ r_err_str="Expected value, got "+String(tk_name[token.type])+".";
+ return ERR_PARSE_ERROR;
+ }
+
+ return ERR_PARSE_ERROR;
+}
+
+
+Error VariantConstruct::_parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+ Token token;
+ bool need_comma=false;
+
+
+ while(index<p_len) {
+
+ Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
+ if (err!=OK)
+ return err;
+
+ if (token.type==TK_BRACKET_CLOSE) {
+
+ return OK;
+ }
+
+ if (need_comma) {
+
+ if (token.type!=TK_COMMA) {
+
+ r_err_str="Expected ','";
+ return ERR_PARSE_ERROR;
+ } else {
+ need_comma=false;
+ continue;
+ }
+ }
+
+ Variant v;
+ err = _parse_value(v,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+ if (err)
+ return err;
+
+ array.push_back(v);
+ need_comma=true;
+
+ }
+
+ return OK;
+
+}
+
+Error VariantConstruct::_parse_dict(Dictionary &dict,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+ bool at_key=true;
+ Variant key;
+ Token token;
+ bool need_comma=false;
+
+
+ while(index<p_len) {
+
+
+ if (at_key) {
+
+ Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
+ if (err!=OK)
+ return err;
+
+ if (token.type==TK_CURLY_BRACKET_CLOSE) {
+
+ return OK;
+ }
+
+ if (need_comma) {
+
+ if (token.type!=TK_COMMA) {
+
+ r_err_str="Expected '}' or ','";
+ return ERR_PARSE_ERROR;
+ } else {
+ need_comma=false;
+ continue;
+ }
+ }
+
+ err = _parse_value(key,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+
+
+ if (err!=OK)
+ return err;
+
+ err = _get_token(p_str,index,p_len,token,line,r_err_str);
+
+ if (err!=OK)
+ return err;
+
+ if (token.type!=TK_COLON) {
+
+ r_err_str="Expected ':'";
+ return ERR_PARSE_ERROR;
+ }
+ at_key=false;
+ } else {
+
+
+ Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
+ if (err!=OK)
+ return err;
+
+ Variant v;
+ err = _parse_value(v,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+ if (err)
+ return err;
+ dict[key]=v;
+ need_comma=true;
+ at_key=true;
+ }
+ }
+
+ return OK;
+}
+
+
+Error VariantConstruct::parse(const String& p_string,Variant& r_ret,String &r_err_str,int &r_err_line,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+
+ const CharType *str = p_string.ptr();
+ int idx = 0;
+ int len = p_string.length();
+ Token token;
+ r_err_line=0;
+ String aux_key;
+
+ Error err = _get_token(str,idx,len,token,r_err_line,r_err_str);
+ if (err)
+ return err;
+
+ return _parse_value(r_ret,token,str,idx,len,r_err_line,r_err_str,p_construct,p_ud);
+}
+
+
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 9c489c5ef2..eabd647837 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -165,6 +165,12 @@ r_valid=false;\
return;}
#define DEFAULT_OP_ARRAY_EQ(m_name,m_type)\
+DEFAULT_OP_ARRAY_OP(m_name,m_type,!=,!=,true,false,false)
+
+#define DEFAULT_OP_ARRAY_LT(m_name,m_type)\
+DEFAULT_OP_ARRAY_OP(m_name,m_type,<,!=,false,a_len<array_b.size(),true)
+
+#define DEFAULT_OP_ARRAY_OP(m_name,m_type,m_opa,m_opb,m_ret_def,m_ret_s,m_ret_f)\
case m_name: { \
if (p_a.type!=p_b.type) {\
r_valid=false;\
@@ -174,19 +180,19 @@ case m_name: { \
const DVector<m_type> &array_b=*reinterpret_cast<const DVector<m_type> *>(p_b._data._mem);\
\
int a_len = array_a.size();\
- if (a_len!=array_b.size()){\
- _RETURN( false);\
+ if (a_len m_opa array_b.size()){\
+ _RETURN( m_ret_s);\
}else {\
\
DVector<m_type>::Read ra = array_a.read();\
DVector<m_type>::Read rb = array_b.read();\
\
for(int i=0;i<a_len;i++) {\
- if (ra[i]!=rb[i])\
- _RETURN( false);\
+ if (ra[i] m_opb rb[i])\
+ _RETURN( m_ret_f);\
}\
\
- _RETURN( true);\
+ _RETURN( m_ret_def);\
}\
}
@@ -290,8 +296,9 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
if (arr_b->size()!=l)
_RETURN( false );
for(int i=0;i<l;i++) {
- if (!(arr_a[i]==arr_b[i]))
+ if (!((*arr_a)[i]==(*arr_b)[i])) {
_RETURN( false );
+ }
}
_RETURN( true );
@@ -356,14 +363,33 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
} break;
DEFAULT_OP_FAIL(INPUT_EVENT);
DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(RAW_ARRAY);
- DEFAULT_OP_FAIL(INT_ARRAY);
- DEFAULT_OP_FAIL(REAL_ARRAY);
- DEFAULT_OP_FAIL(STRING_ARRAY);
- DEFAULT_OP_FAIL(VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(COLOR_ARRAY);
+ case ARRAY: {
+
+ if (p_b.type!=ARRAY)
+ _RETURN( false );
+
+ const Array *arr_a=reinterpret_cast<const Array*>(p_a._data._mem);
+ const Array *arr_b=reinterpret_cast<const Array*>(p_b._data._mem);
+
+ int l = arr_a->size();
+ if (arr_b->size()<l)
+ _RETURN( false );
+ for(int i=0;i<l;i++) {
+ if (!((*arr_a)[i]<(*arr_b)[i])) {
+ _RETURN( true );
+ }
+ }
+
+ _RETURN( false );
+
+ } break;
+ DEFAULT_OP_ARRAY_LT(RAW_ARRAY,uint8_t);
+ DEFAULT_OP_ARRAY_LT(INT_ARRAY,int);
+ DEFAULT_OP_ARRAY_LT(REAL_ARRAY,real_t);
+ DEFAULT_OP_ARRAY_LT(STRING_ARRAY,String);
+ DEFAULT_OP_ARRAY_LT(VECTOR2_ARRAY,Vector3);
+ DEFAULT_OP_ARRAY_LT(VECTOR3_ARRAY,Vector3);
+ DEFAULT_OP_ARRAY_LT(COLOR_ARRAY,Color);
case VARIANT_MAX: {
r_valid=false;
return;
@@ -471,7 +497,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
}
const Array &array_a=*reinterpret_cast<const Array *>(p_a._data._mem);
const Array &array_b=*reinterpret_cast<const Array *>(p_b._data._mem);
- Array sum;
+ Array sum(array_a.is_shared() || array_b.is_shared());
int asize=array_a.size();
int bsize=array_b.size();
sum.resize(asize+bsize);
@@ -552,12 +578,29 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
if (p_b.type==MATRIX32) {
_RETURN( *p_a._data._matrix32 * *p_b._data._matrix32 );
};
+ if (p_b.type==VECTOR2) {
+ _RETURN( p_a._data._matrix32->xform( *(const Vector2*)p_b._data._mem) );
+ };
r_valid=false;
return;
} break;
DEFAULT_OP_LOCALMEM_NUM(*,VECTOR3,Vector3);
DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_FAIL(QUAT);
+ case QUAT: {
+
+ switch(p_b.type) {
+ case VECTOR3: {
+
+ _RETURN( reinterpret_cast<const Quat*>(p_a._data._mem)->xform( *(const Vector3*)p_b._data._mem) );
+ } break;
+ case QUAT: {
+
+ _RETURN( *reinterpret_cast<const Quat*>(p_a._data._mem) * *reinterpret_cast<const Quat*>(p_b._data._mem) );
+ } break;
+ };
+ r_valid=false;
+ return;
+ } break;
DEFAULT_OP_FAIL(_AABB);
case MATRIX3: {
@@ -736,6 +779,24 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
}
#endif
_RETURN( p_a._data._int % p_b._data._int );
+
+ } else if (p_a.type==STRING) {
+ const String* format=reinterpret_cast<const String*>(p_a._data._mem);
+
+ String result;
+ bool error;
+ if (p_b.type==ARRAY) {
+ // e.g. "frog %s %d" % ["fish", 12]
+ const Array* args=reinterpret_cast<const Array*>(p_b._data._mem);
+ result=format->sprintf(*args, &error);
+ } else {
+ // e.g. "frog %d" % 12
+ Array args;
+ args.push_back(p_b);
+ result=format->sprintf(args, &error);
+ }
+ r_valid = !error;
+ _RETURN(result);
}
r_valid=false;
@@ -922,21 +983,31 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
case REAL: { return; } break;
case STRING: {
- if (p_value.type!=Variant::STRING)
+
+ if (p_index.type!=Variant::INT && p_index.type!=Variant::REAL)
return;
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
- //string index
- int idx=p_index;
- String *str=reinterpret_cast<String*>(_data._mem);
- if (idx >=0 && idx<str->length()) {
- String chr = p_value;
- *str = str->substr(0,idx-1)+chr+str->substr(idx+1,str->length());
- valid=true;
- return;
- }
+ int idx=p_index;
+ String *str=reinterpret_cast<String*>(_data._mem);
+ if (idx <0 || idx>=str->length())
+ return;
+
+ String chr;
+ if (p_value.type==Variant::INT || p_value.type==Variant::REAL) {
+
+ chr = String::chr(p_value);
+ } else if (p_value.type==Variant::STRING) {
+
+ chr = p_value;
+ } else {
+ return;
}
+ *str = str->substr(0,idx-1)+chr+str->substr(idx+1,str->length());
+ valid=true;
+ return;
+
+
} break;
case VECTOR2: {
@@ -951,7 +1022,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
Vector2 *v=reinterpret_cast<Vector2*>(_data._mem);
valid=true;
- v[idx]=p_value;
+ (*v)[idx]=p_value;
return;
}
} else if (p_index.get_type()==Variant::STRING) {
@@ -1045,7 +1116,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
Vector3 *v=reinterpret_cast<Vector3*>(_data._mem);
valid=true;
- v[idx]=p_value;
+ (*v)[idx]=p_value;
return;
}
} else if (p_index.get_type()==Variant::STRING) {
@@ -1677,6 +1748,19 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
return;
}
}
+ if (ie.type == InputEvent::ACTION) {
+
+ if (str =="action") {
+ valid=true;
+ ie.action.action=p_value;
+ return;
+ }
+ else if (str == "pressed") {
+ valid=true;
+ ie.action.pressed=p_value;
+ return;
+ }
+ }
} break;
case DICTIONARY: {
@@ -2355,6 +2439,17 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
return Vector2(ie.screen_drag.speed_x,ie.screen_drag.speed_y);
}
}
+ if (ie.type == InputEvent::ACTION) {
+
+ if (str =="action") {
+ valid=true;
+ return ie.action.action;
+ }
+ else if (str == "pressed") {
+ valid=true;
+ return ie.action.pressed;
+ }
+ }
} break;
case DICTIONARY: {
@@ -2492,7 +2587,7 @@ bool Variant::in(const Variant& p_index, bool *r_valid) const {
String idx=p_index;
const String *str=reinterpret_cast<const String*>(_data._mem);
- return str->find("idx")!=-1;
+ return str->find(idx)!=-1;
}
} break;
@@ -3307,7 +3402,15 @@ Variant Variant::iter_get(const Variant& r_iter,bool &r_valid) const {
void Variant::interpolate(const Variant& a, const Variant& b, float c,Variant &r_dst) {
if (a.type!=b.type) {
- r_dst=a;
+ if (a.is_num() && b.is_num()) {
+ //not as efficient but..
+ real_t va=a;
+ real_t vb=b;
+ r_dst=(1.0-c) * va + vb * c;
+
+ } else {
+ r_dst=a;
+ }
return;
}
diff --git a/core/vector.h b/core/vector.h
index 90a9bf715b..d103400622 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -104,7 +104,7 @@ public:
template <class T_val>
- int find(T_val& p_val) const;
+ int find(const T_val& p_val) const;
void set(int p_index,T p_elem);
T get(int p_index) const;
@@ -149,7 +149,16 @@ public:
sort_custom<_DefaultComparator<T> >();
}
+ void ordered_insert(const T& p_val) {
+ int i;
+ for (i=0; i<size(); i++) {
+ if (p_val < operator[](i)) {
+ break;
+ };
+ };
+ insert(i, p_val);
+ }
void operator=(const Vector& p_from);
Vector(const Vector& p_from);
@@ -212,7 +221,7 @@ void Vector<T>::_copy_on_write() {
}
template<class T> template<class T_val>
-int Vector<T>::find(T_val& p_val) const {
+int Vector<T>::find(const T_val &p_val) const {
int ret = -1;
if (size() == 0)
@@ -331,12 +340,14 @@ template<class T>
void Vector<T>::remove(int p_index) {
ERR_FAIL_INDEX(p_index, size());
- for (int i=p_index; i<size()-1; i++) {
+ T*p=ptr();
+ int len=size();
+ for (int i=p_index; i<len-1; i++) {
- set(i, get(i+1));
+ p[i]=p[i+1];
};
- resize(size()-1);
+ resize(len-1);
};
template<class T>
diff --git a/core/vmap.cpp b/core/vmap.cpp
index 4903a878b1..32481eb9eb 100644
--- a/core/vmap.cpp
+++ b/core/vmap.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/vmap.h b/core/vmap.h
index 516299280b..5ff8f73978 100644
--- a/core/vmap.h
+++ b/core/vmap.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/vset.cpp b/core/vset.cpp
index ffdd158996..c849bf3367 100644
--- a/core/vset.cpp
+++ b/core/vset.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/core/vset.h b/core/vset.h
index 3764b015b0..e1e02ab435 100644
--- a/core/vset.h
+++ b/core/vset.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */