diff options
1123 files changed, 48927 insertions, 17825 deletions
diff --git a/.gitignore b/.gitignore index 45bf531311..07af81a6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -12,12 +12,19 @@ drivers/gles2/shaders/*.h modules/register_module_types.cpp core/version.h core/method_bind.inc +core/method_bind_ext.inc core/script_encryption_key.cpp core/global_defaults.cpp tools/editor/register_exporters.cpp tools/editor/doc_data_compressed.h tools/editor/editor_icons.cpp -fpic +.fscache +make.bat +log.txt + +# Javascript specific +*.bc # Android specific platform/android/java/local.properties @@ -257,3 +264,4 @@ Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ logo.h +*.autosave diff --git a/.travis.yml b/.travis.yml index 73b07acb7f..6dd21dae0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,4 +11,4 @@ before_script: - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi -script: scons bin/godot +script: scons platform=x11 diff --git a/LICENSE.md b/LICENSE.md index 122736f5f1..ca0a9702f7 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -21,3 +21,7 @@ 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. + + +********************************************************************** + @@ -10,11 +10,6 @@ The editor, language and APIs are feature rich, yet simple to learn, allowing yo Godot has been developed by Juan Linietsky and Ariel Manzur for several years, and was born as an in-house engine, used to publish several work-for-hire titles. Development is sponsored by OKAM Studio (http://www.okamstudio.com). -### Godot is BETA. Collaborate!! - -Having been developed as in-house means that the user experience may still not be ideal for everyone. The features needed to make a great game are there, but we really need your help to fix all the rough edges and improve usability (via feedback and/or code contributions). -We know we are close to having an awesome, open source, game engine with nothing to envy from the best commercial offerings, but we can't do this alone. This is why Godot is now open source, so everyone can help us reach this goal. - ### Documentation Documentation has been moved to the [GitHub Wiki](https://github.com/okamstudio/godot/wiki). diff --git a/SConstruct b/SConstruct index 7589ab3e6c..537bb0e395 100644 --- a/SConstruct +++ b/SConstruct @@ -6,7 +6,6 @@ import os.path import glob import sys import methods -import multiprocessing methods.update_version() @@ -68,12 +67,16 @@ env_base.android_source_modules=[] env_base.android_source_files=[] env_base.android_module_libraries=[] env_base.android_manifest_chunk="" +env_base.android_permission_chunk="" +env_base.android_appattributes_chunk="" env_base.disabled_modules=[] env_base.__class__.android_module_source = methods.android_module_source env_base.__class__.android_module_library = methods.android_module_library env_base.__class__.android_module_file = methods.android_module_file env_base.__class__.android_module_manifest = methods.android_module_manifest +env_base.__class__.android_module_permission = methods.android_module_permission +env_base.__class__.android_module_attribute = methods.android_module_attribute env_base.__class__.disable_module = methods.disable_module env_base.__class__.add_source_files = methods.add_source_files @@ -99,6 +102,7 @@ opts.Add('vorbis','Build Ogg Vorbis Support: (yes/no)','yes') opts.Add('minizip','Build Minizip Archive Support: (yes/no)','yes') opts.Add('squish','Squish BC Texture Compression in editor (yes/no)','yes') opts.Add('theora','Theora Video (yes/no)','yes') +opts.Add('use_theoraplayer_binary', "Use precompiled binaries from libtheoraplayer for ogg/theora/vorbis (yes/no)", "no") opts.Add('freetype','Freetype support in editor','yes') opts.Add('speex','Speex Audio (yes/no)','yes') opts.Add('xml','XML Save/Load support (yes/no)','yes') @@ -107,6 +111,7 @@ opts.Add('jpg','JPG Image loader support (yes/no)','yes') opts.Add('webp','WEBP Image loader support (yes/no)','yes') opts.Add('dds','DDS Texture loader support (yes/no)','yes') opts.Add('pvr','PVR (PowerVR) Texture loader support (yes/no)','yes') +opts.Add('etc1','etc1 Texture compression support (yes/no)','yes') opts.Add('builtin_zlib','Use built-in zlib (yes/no)','yes') opts.Add('openssl','Use OpenSSL (yes/no/builtin)','no') opts.Add('musepack','Musepack Audio (yes/no)','yes') @@ -116,6 +121,8 @@ opts.Add("CFLAGS", "Custom flags for the C compiler"); opts.Add("LINKFLAGS", "Custom flags for the linker"); opts.Add('disable_3d', 'Disable 3D nodes for smaller executable (yes/no)', "no") opts.Add('disable_advanced_gui', 'Disable advance 3D gui nodes and behaviors (yes/no)', "no") +opts.Add('colored', 'Enable colored output for the compilation (yes/no)', 'no') +opts.Add('extra_suffix', 'Custom extra suffix added to the base filename of all generated binary files.', '') # add platform specific options @@ -133,8 +140,8 @@ Help(opts.GenerateHelpText(env_base)) # generate help # add default include paths env_base.Append(CPPPATH=['#core','#core/math','#tools','#drivers','#']) - -# configure ENV for platform + +# configure ENV for platform env_base.platform_exporters=platform_exporters """ @@ -171,6 +178,9 @@ if selected_platform in platform_list: env = env_base.Clone() env.extra_suffix="" + + if env["extra_suffix"] != '' : + env.extra_suffix += '.'+env["extra_suffix"] CCFLAGS = env.get('CCFLAGS', '') env['CCFLAGS'] = '' @@ -299,6 +309,11 @@ if selected_platform in platform_list: if (env['xml']=='yes'): env.Append(CPPFLAGS=['-DXML_ENABLED']) + if (env['colored']=='yes'): + methods.colored(sys,env) + + if (env['etc1']=='yes'): + env.Append(CPPFLAGS=['-DETC1_ENABLED']) Export('env') diff --git a/bin/tests/test_gdscript.cpp b/bin/tests/test_gdscript.cpp index b62deee2cd..4b4030954a 100644 --- a/bin/tests/test_gdscript.cpp +++ b/bin/tests/test_gdscript.cpp @@ -738,6 +738,26 @@ static void _disassemble_class(const Ref<GDScript>& p_class,const Vector<String> incr=4+argc; } break; + case GDFunction::OPCODE_YIELD: { + + txt+=" yield "; + incr=1; + + } break; + case GDFunction::OPCODE_YIELD_SIGNAL: { + + txt+=" yield_signal "; + txt+=DADDR(1); + txt+=","; + txt+=DADDR(2); + incr=3; + } break; + case GDFunction::OPCODE_YIELD_RESUME: { + + txt+=" yield resume: "; + txt+=DADDR(1); + incr=2; + } break; case GDFunction::OPCODE_JUMP: { txt+=" jump "; diff --git a/bin/tests/test_gui.cpp b/bin/tests/test_gui.cpp index f814b0282b..70cff12c44 100644 --- a/bin/tests/test_gui.cpp +++ b/bin/tests/test_gui.cpp @@ -58,7 +58,7 @@ namespace TestGUI { -class TestMainLoop : public SceneMainLoop { +class TestMainLoop : public SceneTree { Control *control; @@ -72,7 +72,7 @@ public: } virtual void init() { - SceneMainLoop::init(); + SceneTree::init(); #if 0 @@ -132,7 +132,7 @@ public: frame->add_child( button ); -#if 0 + Sprite *tf = memnew( Sprite ); frame->add_child(tf); Image img; @@ -140,14 +140,14 @@ public: img.resize(512,512); img.generate_mipmaps(); - img.compress(); - Ref<Texture> text = memnew( Texture ); - text->create_from_image(img); - tf->set_texture(text); + img.compress(Image::COMPRESS_PVRTC4); + Ref<ImageTexture> tt = memnew( ImageTexture ); + tt->create_from_image(img); + tf->set_texture(tt); tf->set_pos(Point2(50,50)); //tf->set_scale(Point2(0.3,0.3)); - +#if 0 return; #endif diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp index 2db945d5fd..ea324a7381 100644 --- a/bin/tests/test_math.cpp +++ b/bin/tests/test_math.cpp @@ -80,6 +80,7 @@ MainLoop* test() { { + // print_line("NUM: "+itos(237641278346127)); print_line("NUM: "+itos(-128)); return NULL; diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp index 66238b066d..2a048f2f67 100644 --- a/bin/tests/test_string.cpp +++ b/bin/tests/test_string.cpp @@ -487,7 +487,7 @@ struct test_27_data { bool test_27() { - OS::get_singleton()->print("\n\nTest 26: begins_with\n"); + OS::get_singleton()->print("\n\nTest 27: begins_with\n"); test_27_data tc[] = { {"res://foobar", "res://", true}, {"res", "res://", false}, @@ -504,11 +504,349 @@ bool test_27() { } if (!state) { OS::get_singleton()->print("\n\t Failure on:\n\t\tstring: ", tc[i].data, "\n\t\tbegin: ", tc[i].begin, "\n\t\texpected: ", tc[i].expected ? "true" : "false", "\n"); + break; } }; return state; }; + +bool test_28() { + + OS::get_singleton()->print("\n\nTest 28: sprintf\n"); + + bool success, state = true; + char output_format[] = "\tTest:\t%ls => %ls (%s)\n"; + String format, output; + Array args; + bool error; + + // %% + format = "fish %% frog"; + args.clear(); + output = format.sprintf(args, &error); + success = (output == String("fish % frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + //////// INTS + + // Int + format = "fish %d frog"; + args.clear(); + args.push_back(5); + output = format.sprintf(args, &error); + success = (output == String("fish 5 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Int left padded with zeroes. + format = "fish %05d frog"; + args.clear(); + args.push_back(5); + output = format.sprintf(args, &error); + success = (output == String("fish 00005 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Int left padded with spaces. + format = "fish %5d frog"; + args.clear(); + args.push_back(5); + output = format.sprintf(args, &error); + success = (output == String("fish 5 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Int right padded with spaces. + format = "fish %-5d frog"; + args.clear(); + args.push_back(5); + output = format.sprintf(args, &error); + success = (output == String("fish 5 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Int with sign (positive). + format = "fish %+d frog"; + args.clear(); + args.push_back(5); + output = format.sprintf(args, &error); + success = (output == String("fish +5 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Negative int. + format = "fish %d frog"; + args.clear(); + args.push_back(-5); + output = format.sprintf(args, &error); + success = (output == String("fish -5 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Hex (lower) + format = "fish %x frog"; + args.clear(); + args.push_back(45); + output = format.sprintf(args, &error); + success = (output == String("fish 2d frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Hex (upper) + format = "fish %X frog"; + args.clear(); + args.push_back(45); + output = format.sprintf(args, &error); + success = (output == String("fish 2D frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Octal + format = "fish %o frog"; + args.clear(); + args.push_back(99); + output = format.sprintf(args, &error); + success = (output == String("fish 143 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ////// REALS + + // Real + format = "fish %f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 99.990000 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real left-padded + format = "fish %11f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 99.990000 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real right-padded + format = "fish %-11f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 99.990000 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real given int. + format = "fish %f frog"; + args.clear(); + args.push_back(99); + output = format.sprintf(args, &error); + success = (output == String("fish 99.000000 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real with sign (positive). + format = "fish %+f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish +99.990000 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real with 1 decimals. + format = "fish %.1f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 100.0 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real with 12 decimals. + format = "fish %.12f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 99.990000000000 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Real with no decimals. + format = "fish %.f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 100 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + /////// Strings. + + // String + format = "fish %s frog"; + args.clear(); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == String("fish cheese frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // String left-padded + format = "fish %10s frog"; + args.clear(); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == String("fish cheese frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // String right-padded + format = "fish %-10s frog"; + args.clear(); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == String("fish cheese frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ///// Characters + + // Character as string. + format = "fish %c frog"; + args.clear(); + args.push_back("A"); + output = format.sprintf(args, &error); + success = (output == String("fish A frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Character as int. + format = "fish %c frog"; + args.clear(); + args.push_back(65); + output = format.sprintf(args, &error); + success = (output == String("fish A frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ///// Dynamic width + + // String dynamic width + format = "fish %*s frog"; + args.clear(); + args.push_back(10); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == String("fish cheese frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Int dynamic width + format = "fish %*d frog"; + args.clear(); + args.push_back(10); + args.push_back(99); + output = format.sprintf(args, &error); + success = (output == String("fish 99 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Float dynamic width + format = "fish %*.*f frog"; + args.clear(); + args.push_back(10); + args.push_back(3); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == String("fish 99.990 frog") && !error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + ///// Errors + + // More formats than arguments. + format = "fish %s %s frog"; + args.clear(); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == "not enough arguments for format string" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // More arguments than formats. + format = "fish %s frog"; + args.clear(); + args.push_back("hello"); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == "not all arguments converted during string formatting" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Incomplete format. + format = "fish %10"; + args.clear(); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == "incomplete format" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Bad character in format string + format = "fish %&f frog"; + args.clear(); + args.push_back("cheese"); + output = format.sprintf(args, &error); + success = (output == "unsupported format character" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Too many decimals. + format = "fish %2.2.2f frog"; + args.clear(); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == "too many decimal points in format" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // * not a number + format = "fish %*f frog"; + args.clear(); + args.push_back("cheese"); + args.push_back(99.99); + output = format.sprintf(args, &error); + success = (output == "* wants number" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Character too long. + format = "fish %c frog"; + args.clear(); + args.push_back("sc"); + output = format.sprintf(args, &error); + success = (output == "%c requires number or single-character string" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + // Character bad type. + format = "fish %c frog"; + args.clear(); + args.push_back(Array()); + output = format.sprintf(args, &error); + success = (output == "%c requires number or single-character string" && error); + OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); + if (!success) state = false; + + return state; +} + typedef bool (*TestFunc)(void); TestFunc test_funcs[] = { @@ -540,6 +878,7 @@ TestFunc test_funcs[] = { test_25, test_26, test_27, + test_28, 0 }; diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index c66416ea6d..439855fbb7 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -12,9 +12,9 @@ Ref<ResourceInteractiveLoader> _ResourceLoader::load_interactive(const String& p 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, @@ -577,9 +651,9 @@ float _OS::get_frames_per_second() const { return OS::get_singleton()->get_frames_per_second(); } -Error _OS::native_video_play(String p_path, float p_volume) { +Error _OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { - return OS::get_singleton()->native_video_play(p_path, p_volume); + return OS::get_singleton()->native_video_play(p_path, p_volume, p_audio_track, p_subtitle_track); }; bool _OS::native_video_is_playing() { @@ -597,6 +671,20 @@ void _OS::native_video_stop() { OS::get_singleton()->native_video_stop(); }; +bool _OS::is_debug_build() const { + +#ifdef DEBUG_ENABLED + return true; +#else + return false; +#endif + +} + +String _OS::get_system_dir(SystemDir p_dir) const { + + return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir)); +} String _OS::get_custom_level() const { @@ -618,6 +706,26 @@ 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_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); @@ -628,7 +736,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); @@ -668,6 +776,8 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("can_use_threads"),&_OS::can_use_threads); + ObjectTypeDB::bind_method(_MD("is_debug_build"),&_OS::is_debug_build); + //ObjectTypeDB::bind_method(_MD("get_mouse_button_state"),&_OS::get_mouse_button_state); ObjectTypeDB::bind_method(_MD("dump_memory_to_file","file"),&_OS::dump_memory_to_file); @@ -680,8 +790,11 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_dynamic_memory_usage"),&_OS::get_dynamic_memory_usage); ObjectTypeDB::bind_method(_MD("get_data_dir"),&_OS::get_data_dir); + 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); @@ -718,6 +831,14 @@ void _OS::_bind_methods() { BIND_CONSTANT( MONTH_NOVEMBER ); BIND_CONSTANT( MONTH_DECEMBER ); + BIND_CONSTANT( SYSTEM_DIR_DESKTOP); + BIND_CONSTANT( SYSTEM_DIR_DCIM ); + BIND_CONSTANT( SYSTEM_DIR_DOCUMENTS ); + BIND_CONSTANT( SYSTEM_DIR_DOWNLOADS ); + BIND_CONSTANT( SYSTEM_DIR_MOVIES ); + BIND_CONSTANT( SYSTEM_DIR_MUSIC ); + BIND_CONSTANT( SYSTEM_DIR_PICTURES ); + BIND_CONSTANT( SYSTEM_DIR_RINGTONES ); } @@ -813,6 +934,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; @@ -913,6 +1040,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); @@ -1096,6 +1224,7 @@ String _File::get_as_text() const { text+=l+"\n"; l = get_line(); } + text+=l; return text; diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 2d824955df..f3601e35fb 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,7 +108,27 @@ public: bool is_video_mode_resizable(int p_screen=0) const; Array get_fullscreen_mode_list(int p_screen=0) const; - Error native_video_play(String p_path, float p_volume); + + 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(); void native_video_stop(); @@ -154,6 +174,8 @@ public: bool has_touchscreen_ui_hint() const; + bool is_debug_build() const; + String get_unique_ID() const; /* @@ -199,16 +221,35 @@ public: int get_processor_count() const; + enum SystemDir { + SYSTEM_DIR_DESKTOP, + SYSTEM_DIR_DCIM, + SYSTEM_DIR_DOCUMENTS, + SYSTEM_DIR_DOWNLOADS, + SYSTEM_DIR_MOVIES, + SYSTEM_DIR_MUSIC, + SYSTEM_DIR_PICTURES, + SYSTEM_DIR_RINGTONES, + }; + + String get_system_dir(SystemDir p_dir) const; + + String get_data_dir() 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); + + class _Geometry : public Object { OBJ_TYPE(_Geometry, Object); @@ -229,6 +270,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); diff --git a/core/color.cpp b/core/color.cpp index 1528db6aaa..3116c33a31 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -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/dictionary.cpp b/core/dictionary.cpp index 16ee397382..2d503bae50 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -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/dvector.h b/core/dvector.h index 72661882cd..29be417844 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -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/event_queue.cpp b/core/event_queue.cpp index cf6e742f79..161fb4fedd 100644 --- a/core/event_queue.cpp +++ b/core/event_queue.cpp @@ -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/global_constants.cpp b/core/global_constants.cpp index ae4abc627d..fc48a105db 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -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 ), diff --git a/core/globals.cpp b/core/globals.cpp index 5be53fd853..a39ace7360 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -566,9 +566,11 @@ static Variant _decode_variant(const String& p_string) { ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant()); int scode=0; - if (params[0].is_numeric()) + if (params[0].is_numeric()) { scode=params[0].to_int(); - else + if (scode<10) + scode+=KEY_0; + } else scode=find_keycode(params[0]); InputEvent ie; @@ -672,7 +674,7 @@ static Variant _decode_variant(const String& p_string) { int w=params[2].to_int(); int h=params[3].to_int(); - if (w == 0 && w == 0) { + if (w == 0 && h == 0) { //r_v = Image(w, h, imgformat); return Image(); }; diff --git a/core/image.cpp b/core/image.cpp index ae9fb0adc4..ea09787f01 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -34,6 +34,7 @@ #include "print_string.h" #include <stdio.h> +SavePNGFunc Image::save_png_func = NULL; void Image::_put_pixel(int p_x,int p_y, const BColor& p_color, unsigned char *p_data) { @@ -133,6 +134,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); @@ -1200,6 +1213,14 @@ Error Image::load(const String& p_path) { return ImageLoader::load_image(p_path, this); } +Error Image::save_png(const String& p_path) { + + if (save_png_func == NULL) + return ERR_UNAVAILABLE; + + return save_png_func(p_path, *this); +}; + bool Image::operator==(const Image& p_image) const { if (data.size() == 0 && p_image.data.size() == 0) diff --git a/core/image.h b/core/image.h index 0084a3616f..8ef7a54c78 100644 --- a/core/image.h +++ b/core/image.h @@ -40,7 +40,9 @@ * Images can be loaded from a file, or registered into the Render object as textures. */ +class Image; +typedef Error (*SavePNGFunc)(const String &p_path, Image& p_img); class Image { @@ -50,6 +52,8 @@ class Image { }; public: + static SavePNGFunc save_png_func; + enum Format { FORMAT_GRAYSCALE, ///< one byte per pixel, 0-255 FORMAT_INTENSITY, ///< one byte per pixel, 0-255 @@ -232,6 +236,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. @@ -278,6 +283,7 @@ public: DVector<uint8_t> get_data() const; Error load(const String& p_path); + Error save_png(const String& p_path); /** * create an empty image diff --git a/core/int_types.h b/core/int_types.h index 15ef68e915..31f05b2d35 100644 --- a/core/int_types.h +++ b/core/int_types.h @@ -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/config_file.cpp b/core/io/config_file.cpp index 45e8cf69ab..17ee72f2eb 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -471,9 +471,12 @@ static Variant _decode_variant(const String& p_string) { ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant()); int scode=0; - if (params[0].is_numeric()) + if (params[0].is_numeric()) { scode=params[0].to_int(); - else + if (scode < 10) { + scode=KEY_0+scode; + } + } else scode=find_keycode(params[0]); InputEvent ie; @@ -577,7 +580,7 @@ static Variant _decode_variant(const String& p_string) { int w=params[2].to_int(); int h=params[3].to_int(); - if (w == 0 && w == 0) { + if (w == 0 && h == 0) { //r_v = Image(w, h, imgformat); return Image(); }; diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 6e03819aac..afbd7e3d46 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -362,6 +362,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..2d0cf5b32e 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -208,6 +208,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/http_client.cpp b/core/io/http_client.cpp index 60a200af12..c7906018e9 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -29,6 +29,8 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" +VARIANT_ENUM_CAST(HTTPClient::Status); + Error HTTPClient::connect_url(const String& p_url) { return OK; @@ -271,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; @@ -415,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; @@ -469,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; } @@ -500,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) { @@ -555,6 +562,20 @@ 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() { @@ -572,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); @@ -662,6 +684,11 @@ 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; +} + HTTPClient::HTTPClient(){ tcp_connection = StreamPeerTCP::create_ref(); @@ -675,7 +702,7 @@ HTTPClient::HTTPClient(){ response_num=0; ssl=false; blocking=false; - tmp_read.resize(4096); + read_chunk_size=4096; } HTTPClient::~HTTPClient(){ diff --git a/core/io/http_client.h b/core/io/http_client.h index 09ad64f48a..d0ebaa4596 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -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,6 +188,7 @@ 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(); diff --git a/core/io/ip.cpp b/core/io/ip.cpp index d2a685f6b0..6ef6b31188 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -31,7 +31,7 @@ #include "os/semaphore.h" #include "hash_map.h" - +VARIANT_ENUM_CAST(IP::ResolverStatus); /************* RESOLVER ******************/ diff --git a/core/io/ip_address.h b/core/io/ip_address.h index cd39aa6c81..3cd8bb7733 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -39,6 +39,12 @@ struct IP_Address { }; //operator Variant() const; + bool operator==(const IP_Address& p_ip) const { + return host==p_ip.host; + } + bool operator!=(const IP_Address& p_ip) const { + return host!=p_ip.host; + } operator String() const; IP_Address(const String& p_string); IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d); diff --git a/core/io/json.cpp b/core/io/json.cpp index a83d7e4d6e..88a23eb4cd 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -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/packet_peer.cpp b/core/io/packet_peer.cpp index 37fc9c4a0a..b566ce4b7b 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -111,7 +111,7 @@ Variant PacketPeer::_bnd_get_var() const { void PacketPeer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var); - ObjectTypeDB::bind_method(_MD("put_var", "var:Variant"),&PacketPeer::put_var); + ObjectTypeDB::bind_method(_MD("put_var", "var:var"),&PacketPeer::put_var); ObjectTypeDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count); }; diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp new file mode 100644 index 0000000000..83217ffc41 --- /dev/null +++ b/core/io/packet_peer_udp.cpp @@ -0,0 +1,63 @@ +#include "packet_peer_udp.h" +#include "io/ip.h" + + +PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL; + +int PacketPeerUDP::_get_packet_address() const { + + IP_Address ip = get_packet_address(); + return ip.host; +} + +String PacketPeerUDP::_get_packet_ip() const { + + return get_packet_address(); +} + +Error PacketPeerUDP::_set_send_address(const String& p_address,int p_port) { + + IP_Address ip; + if (p_address.is_valid_ip_address()) { + ip=p_address; + } else { + ip=IP::get_singleton()->resolve_hostname(p_address); + if (ip==IP_Address()) + return ERR_CANT_RESOLVE; + } + + set_send_address(ip,p_port); + return OK; +} + +void PacketPeerUDP::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("listen:Error","port","recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536)); + ObjectTypeDB::bind_method(_MD("close"),&PacketPeerUDP::close); + ObjectTypeDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); + ObjectTypeDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening); + ObjectTypeDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip); + ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address); + ObjectTypeDB::bind_method(_MD("get_packet_port"),&PacketPeerUDP::get_packet_port); + ObjectTypeDB::bind_method(_MD("set_send_address","host","port"),&PacketPeerUDP::_set_send_address); + + +} + +Ref<PacketPeerUDP> PacketPeerUDP::create_ref() { + + if (!_create) + return Ref<PacketPeerUDP>(); + return Ref<PacketPeerUDP>(_create()); +} + +PacketPeerUDP* PacketPeerUDP::create() { + + if (!_create) + return NULL; + return _create(); +} + +PacketPeerUDP::PacketPeerUDP() +{ +} diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h new file mode 100644 index 0000000000..73ff487b19 --- /dev/null +++ b/core/io/packet_peer_udp.h @@ -0,0 +1,37 @@ +#ifndef PACKET_PEER_UDP_H +#define PACKET_PEER_UDP_H + + +#include "io/packet_peer.h" + +class PacketPeerUDP : public PacketPeer { + OBJ_TYPE(PacketPeerUDP,PacketPeer); + +protected: + + static PacketPeerUDP* (*_create)(); + static void _bind_methods(); + + int _get_packet_address() const; + String _get_packet_ip() const; + + virtual Error _set_send_address(const String& p_address,int p_port); + +public: + + virtual Error listen(int p_port,int p_recv_buffer_size=65536)=0; + virtual void close()=0; + virtual Error wait()=0; + virtual bool is_listening() const=0; + virtual IP_Address get_packet_address() const=0; + virtual int get_packet_port() const=0; + virtual void set_send_address(const IP_Address& p_address,int p_port)=0; + + + static Ref<PacketPeerUDP> create_ref(); + static PacketPeerUDP* create(); + + PacketPeerUDP(); +}; + +#endif // PACKET_PEER_UDP_H diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index e2371fe24f..ead6984650 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1778,6 +1778,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(); @@ -1910,6 +1915,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(); diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index e6eede7de6..033b4d5e5a 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -193,6 +193,7 @@ Error ResourceInteractiveLoaderXML::close_tag(const String& p_name) { void ResourceInteractiveLoaderXML::unquote(String& p_str) { + p_str=p_str.strip_edges().replace("\"","").xml_unescape(); /*p_str=p_str.strip_edges(); @@ -571,7 +572,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) int w=width.to_int(); int h=height.to_int(); - if (w == 0 && w == 0) { + if (w == 0 && h == 0) { //r_v = Image(w, h, imgformat); r_v=Image(); String sdfsdfg; @@ -1851,7 +1852,10 @@ void ResourceFormatSaverXMLInstance::escape(String& p_str) { for (int i=1;i<32;i++) { char chr[2]={i,0}; - p_str=p_str.replace(chr,"&#"+String::num(i)+";"); + const char hexn[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + const char hex[8]={'&','#','0','0',hexn[i>>4],hexn[i&0xf],';',0}; + + p_str=p_str.replace(chr,hex); } @@ -2588,6 +2592,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); diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 0e75e22767..f83c174084 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -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/xml_parser.cpp b/core/io/xml_parser.cpp index 5d3e4f61ad..1d69f8e5e7 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -30,9 +30,11 @@ #include "print_string.h" //#define DEBUG_XML +VARIANT_ENUM_CAST(XMLParser::NodeType); + static bool _equalsn(const CharType* str1, const CharType* str2, int len) { int i; - for(i=0; str1[i] && str2[i] && i < len; ++i) + for(i=0; i < len && str1[i] && str2[i] ; ++i) if (str1[i] != str2[i]) return false; diff --git a/core/list.h b/core/list.h index f581feb735..ef30e43d21 100644 --- a/core/list.h +++ b/core/list.h @@ -30,7 +30,7 @@ #define GLOBALS_LIST_H #include "os/memory.h" - +#include "sort.h" /** * Generic Templatized Linked List Implementation. @@ -551,7 +551,7 @@ public: } template<class C> - void sort_custom() { + void sort_custom_inplace() { if(size()<2) return; @@ -603,6 +603,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/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index a60dea7379..fbe5f8c741 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -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/geometry.h b/core/math/geometry.h index 81530e30c0..4ad4db8523 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -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.h b/core/math/math_2d.h index fa40d305f5..5bc1b5f0be 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -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 { @@ -224,6 +226,8 @@ struct Rect2 { return true; } + _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 +601,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_funcs.cpp b/core/math/math_funcs.cpp index 92236a374f..ad48ceaac0 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -76,7 +76,7 @@ void Math::seed(uint32_t x) { void Math::randomize() { OS::Time time = OS::get_singleton()->get_time(); - seed(OS::get_singleton()->get_ticks_usec()*time.hour*time.min*time.sec*rand()); /* *OS::get_singleton()->get_time().sec); // windows doesn't have get_time(), returns always 0 */ + seed(OS::get_singleton()->get_ticks_usec()*(time.hour+1)*(time.min+1)*(time.sec+1)*rand()); /* *OS::get_singleton()->get_time().sec); // windows doesn't have get_time(), returns always 0 */ } uint32_t Math::rand() { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index c98a088912..6d43ed8e64 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -136,7 +136,10 @@ public: static int b; -#if defined(_MSC_VER) && _MSC_VER < 1800 +#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 __asm fld a __asm fistp b /*#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) @@ -147,6 +150,7 @@ public: "fistpl %0 \n\t" : "=m" (b) : "m" (a));*/ + #else b=lrintf(a); //assuming everything but msvc 2012 or earlier has lrint #endif diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 136a103eef..a417cdaddf 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -63,7 +63,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me Vector3 sp = p_points[i].snapped(0.0001); if (valid_cache.has(sp)) { valid_points[i]=false; - print_line("INVALIDATED: "+itos(i)); + //print_line("INVALIDATED: "+itos(i)); }else { valid_points[i]=true; valid_cache.insert(sp); 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/method_bind.cpp b/core/method_bind.cpp index 739745f70f..6ee4882571 100644 --- a/core/method_bind.cpp +++ b/core/method_bind.cpp @@ -87,7 +87,9 @@ Vector<StringName> MethodBind::get_argument_names() const { void MethodBind::set_default_arguments(const Vector<Variant>& p_defargs) { - default_arguments=p_defargs; default_argument_count=default_arguments.size(); + default_arguments=p_defargs; + default_argument_count=default_arguments.size(); + } #ifdef DEBUG_METHODS_ENABLED diff --git a/core/method_bind.h b/core/method_bind.h index 3f08c70af8..6ea9340ad5 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -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 { diff --git a/core/object.cpp b/core/object.cpp index b011d1ad3d..f71521a0ff 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1033,6 +1033,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; @@ -1431,6 +1438,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())); @@ -1489,12 +1497,14 @@ void Object::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_block_signals","enable"),&Object::set_block_signals); ObjectTypeDB::bind_method(_MD("is_blocking_signals"),&Object::is_blocking_signals); ObjectTypeDB::bind_method(_MD("set_message_translation","enable"),&Object::set_message_translation); - ObjectTypeDB::bind_method(_MD("can_translate_messages"),&Object::set_message_translation); + ObjectTypeDB::bind_method(_MD("can_translate_messages"),&Object::can_translate_messages); ObjectTypeDB::bind_method(_MD("property_list_changed_notify"),&Object::property_list_changed_notify); 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); + ADD_SIGNAL( MethodInfo("script_changed")); BIND_VMETHOD( MethodInfo("_notification",PropertyInfo(Variant::INT,"what")) ); @@ -1558,6 +1568,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) { @@ -1579,6 +1593,7 @@ Object::Object() { _instance_ID=0; _instance_ID = ObjectDB::add_instance(this); _can_translate=true; + _is_queued_for_deletion=false; script_instance=NULL; #ifdef TOOLS_ENABLED @@ -1694,6 +1709,11 @@ void ObjectDB::debug_objects(DebugFunc p_func) { } +void Object::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + +} + int ObjectDB::get_object_count() { GLOBAL_LOCK_FUNCTION; diff --git a/core/object.h b/core/object.h index 8e0164b13b..0bd3d09c21 100644 --- a/core/object.h +++ b/core/object.h @@ -81,6 +81,7 @@ 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_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, @@ -385,6 +386,7 @@ friend void postinitialize_handler(Object*); Dictionary metadata; 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; @@ -395,7 +397,6 @@ friend void postinitialize_handler(Object*); protected: - virtual bool _use_builtin_script() const { return false; } virtual void _initialize_typev() { initialize_type(); } virtual bool _setv(const StringName& p_name,const Variant &p_property) { return false; }; @@ -582,10 +583,14 @@ public: virtual void get_translatable_strings(List<String> *p_strings) const; + virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; 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(); diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index 62244cbd4f..1047d7eba5 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -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() { @@ -263,12 +264,22 @@ bool ObjectTypeDB::type_exists(const String &p_type) { return types.has(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 String &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); @@ -805,12 +816,25 @@ void ObjectTypeDB::add_virtual_method(const StringName& p_type,const MethodInfo& } -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 +847,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 +932,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..617a0a7c20 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -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); @@ -468,7 +469,7 @@ public: 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 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); @@ -482,6 +483,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/dir_access.h b/core/os/dir_access.h index d8672218bd..dc56f2308e 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -78,6 +78,7 @@ 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; ///< diff --git a/core/os/input.cpp b/core/os/input.cpp index 4151c1b5a8..5d4b3a834d 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -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() { @@ -61,6 +62,8 @@ void Input::_bind_methods() { 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); BIND_CONSTANT( MOUSE_MODE_VISIBLE ); BIND_CONSTANT( MOUSE_MODE_HIDDEN ); @@ -69,6 +72,30 @@ void Input::_bind_methods() { ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) ); } +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")) { + + 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(); + + if (!pi.name.begins_with("input/")) + continue; + + String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); + r_options->push_back("\""+name+"\""); + + } + } +#endif + +} + Input::Input() { singleton=this; diff --git a/core/os/input.h b/core/os/input.h index 1cb0f35d96..387a43a35a 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -76,6 +76,8 @@ 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; + Input(); }; diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 499ec0c08e..27c7c10aef 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -141,11 +141,11 @@ InputEvent::operator String() const { return ""; } -void InputEvent::set_as_action(const String& p_action) { +void InputEvent::set_as_action(const String& p_action, bool p_pressed) { type=ACTION; action.action=InputMap::get_singleton()->get_action_id(p_action); - action.pressed=false; + action.pressed=p_pressed; } bool InputEvent::is_pressed() const { diff --git a/core/os/input_event.h b/core/os/input_event.h index 2c10bffcd2..218ff327d1 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -288,7 +288,7 @@ struct InputEvent { bool is_pressed() const; bool is_action(const String& p_action) const; bool is_echo() const; - void set_as_action(const String& p_action); + void set_as_action(const String& p_action, bool p_pressed); bool operator==(const InputEvent &p_event) const; operator String() const; diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index a4201c34ea..e2a992ecb9 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -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..b4ec5da26f 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -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/os.cpp b/core/os/os.cpp index 53ca7c3a49..5e0e5eed77 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -280,6 +280,12 @@ String OS::get_resource_dir() const { return Globals::get_singleton()->get_resource_path(); } + +String OS::get_system_dir(SystemDir p_dir) const { + + return "."; +} + String OS::get_data_dir() const { return "."; @@ -438,7 +444,7 @@ int OS::get_processor_count() const { return 1; } -Error OS::native_video_play(String p_path, float p_volume) { +Error OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { return FAILED; }; @@ -479,6 +485,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; diff --git a/core/os/os.h b/core/os/os.h index ed7e1e4324..d4ac433644 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -34,6 +34,7 @@ #include "vector.h" #include "os/main_loop.h" #include <stdarg.h> + /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -72,7 +73,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 +149,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) { 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; @@ -286,6 +307,20 @@ public: virtual String get_data_dir() const; virtual String get_resource_dir() const; + enum SystemDir { + SYSTEM_DIR_DESKTOP, + SYSTEM_DIR_DCIM, + SYSTEM_DIR_DOCUMENTS, + SYSTEM_DIR_DOWNLOADS, + SYSTEM_DIR_MOVIES, + SYSTEM_DIR_MUSIC, + SYSTEM_DIR_PICTURES, + SYSTEM_DIR_RINGTONES, + }; + + virtual String get_system_dir(SystemDir p_dir) const; + + virtual void set_no_window_mode(bool p_enable); virtual bool is_no_window_mode_enabled() const; @@ -323,7 +358,7 @@ public: virtual String get_unique_ID() const; - virtual Error native_video_play(String p_path, float p_volume); + virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); virtual bool native_video_is_playing() const; virtual void native_video_pause(); virtual void native_video_stop(); @@ -334,6 +369,18 @@ 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; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 492068f604..4935136eeb 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -29,6 +29,7 @@ #include "register_core_types.h" #include "io/tcp_server.h" +#include "io/packet_peer_udp.h" #include "io/config_file.h" #include "os/main_loop.h" #include "io/packet_peer.h" @@ -109,12 +110,14 @@ void register_core_types() { ObjectTypeDB::register_type<Reference>(); + ObjectTypeDB::register_type<WeakRef>(); ObjectTypeDB::register_type<ResourceImportMetadata>(); ObjectTypeDB::register_type<Resource>(); ObjectTypeDB::register_type<FuncRef>(); ObjectTypeDB::register_virtual_type<StreamPeer>(); ObjectTypeDB::register_create_type<StreamPeerTCP>(); ObjectTypeDB::register_create_type<TCP_Server>(); + ObjectTypeDB::register_create_type<PacketPeerUDP>(); ObjectTypeDB::register_create_type<StreamPeerSSL>(); ObjectTypeDB::register_virtual_type<IP>(); ObjectTypeDB::register_virtual_type<PacketPeer>(); diff --git a/core/resource.cpp b/core/resource.cpp index 987bd772b0..560ca9a1f2 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -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); diff --git a/core/script_language.cpp b/core/script_language.cpp index ad93fca4b5..81a9e2b062 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -85,6 +85,13 @@ void ScriptServer::register_language(ScriptLanguage *p_language) { _languages[_language_count++]=p_language; } +void ScriptServer::init_languages() { + + for(int i=0;i<_language_count;i++) { + _languages[i]->init(); + } +} + Variant ScriptInstance::call(const StringName& p_method,VARIANT_ARG_DECLARE) { VARIANT_ARGPTRS; diff --git a/core/script_language.h b/core/script_language.h index 1e0dcc678f..802eff190a 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -54,6 +54,8 @@ public: static int get_language_count(); static ScriptLanguage *get_language(int p_idx); static void register_language(ScriptLanguage *p_language); + + static void init_languages(); }; @@ -142,7 +144,7 @@ public: virtual bool has_named_classes() const=0; virtual int find_function(const String& p_function,const String& p_code) const=0; virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0; - virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_keyword, List<String>* r_options) { return ERR_UNAVAILABLE; } + virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint) { return ERR_UNAVAILABLE; } virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const=0; /* DEBUGGER FUNCTIONS */ diff --git a/core/set.h b/core/set.h index d87f635577..95f38d7108 100644 --- a/core/set.h +++ b/core/set.h @@ -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/translation.cpp b/core/translation.cpp index 81f2c36075..6ad34651b2 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -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/typedefs.h b/core/typedefs.h index 3107ac2ff7..442ed9ae0b 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -41,7 +41,7 @@ #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_REVISION)"-"_MKSTR(VERSION_STATUS) +#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 diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index b78fd89883..2c4d9e16a8 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -243,6 +243,11 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { case Operation::TYPE_PROPERTY: { obj->set(op.name,op.args[0]); +#ifdef TOOLS_ENABLED + Resource* res = obj->cast_to<Resource>(); + if (res) + res->set_edited(true); +#endif } break; case Operation::TYPE_REFERENCE: { //do nothing diff --git a/core/ustring.cpp b/core/ustring.cpp index d75c21d16e..edb5da2bd2 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -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)) @@ -497,6 +498,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()) @@ -626,7 +648,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 +676,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 +1003,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 +1012,7 @@ String String::num_int64(int64_t p_num) { int chars=0; do { - n/=10; + n/=base; chars++; } while(n); @@ -1001,8 +1024,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 +1989,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 +2085,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) { @@ -3437,7 +3470,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 +3547,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..f9f47d69c9 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -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,9 +146,10 @@ 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; @@ -203,7 +208,7 @@ public: String xml_unescape() const; String c_escape() const; String c_unescape() const; - + String percent_encode() const; String percent_decode() const; diff --git a/core/variant.cpp b/core/variant.cpp index fdb14c0c0f..667a7d8648 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -2631,3 +2631,138 @@ 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(ObjectDeConstruct p_obj_deconstruct,void *p_deconstruct_ud) const { + + switch( type ) { + + case NIL: return "null"; + 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)->c_escape()+"\""; + case VECTOR2: return "Vector2("+operator Vector2()+")"; + case RECT2: return "Rect2("+operator Rect2()+")"; + case MATRIX32: return "Matrix32("+operator Matrix32()+")"; + case VECTOR3: return "Vector3("+operator Vector3()+")"; + case PLANE: return "Plane("+operator Plane()+")"; + //case QUAT: + case _AABB: return "AABB("+operator AABB()+")"; + case QUAT: return "Quat("+operator Quat()+")"; + case MATRIX3: return "Matrix3("+operator Matrix3()+")"; + case TRANSFORM: return "Transform("+operator Transform()+")"; + 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: { + + const Dictionary &d =*reinterpret_cast<const Dictionary*>(_data._mem); + //const String *K=NULL; + String str="{"; + List<Variant> keys; + d.get_key_list(&keys); + + Vector<_VariantStrPair> pairs; + + for(List<Variant>::Element *E=keys.front();E;E=E->next()) { + + _VariantStrPair sp; + 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); + } + + pairs.sort(); + + for(int i=0;i<pairs.size();i++) { + if (i>0) + str+=", "; + str+="("+pairs[i].key+":"+pairs[i].value+")"; + } + str+="}"; + + return str; + } break; + case VECTOR3_ARRAY: { + + DVector<Vector3> vec = operator DVector<Vector3>(); + String str="Vector3Array(["; + for(int i=0;i<vec.size();i++) { + + if (i>0) + str+=", "; + str+=Variant( vec[i] ).get_construct_string(); + } + return str+"])"; + } break; + case STRING_ARRAY: { + + DVector<String> vec = operator DVector<String>(); + 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+"])"; + } break; + case INT_ARRAY: { + + DVector<int> vec = operator DVector<int>(); + String str="IntArray(["; + for(int i=0;i<vec.size();i++) { + + if (i>0) + str+=", "; + str=str+itos(vec[i]); + } + return str+"])"; + } break; + case REAL_ARRAY: { + + DVector<real_t> vec = operator DVector<real_t>(); + String str="FloatArray(["; + for(int i=0;i<vec.size();i++) { + + if (i>0) + str+=", "; + str=str+rtos(vec[i]); + } + return str+"])"; + } break; + case ARRAY: { + + Array arr = operator Array(); + String str="["; + for (int i=0; i<arr.size(); i++) { + if (i) + str+=", "; + str += arr[i].get_construct_string(p_obj_deconstruct,p_deconstruct_ud); + }; + return str+"]"; + + } break; + case OBJECT: { + + 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; + default: { + return "["+get_type_name(type)+"]"; + } + } + +} diff --git a/core/variant.h b/core/variant.h index f651e38352..d5d4792422 100644 --- a/core/variant.h +++ b/core/variant.h @@ -167,14 +167,18 @@ public: static String get_type_name(Variant::Type p_type); static bool can_convert(Type p_type_from,Type p_type_to); + + template<class T> static Type get_type_for() { GetSimpleType<T> t; Variant v(t.type); - return v.get_type(); + Type r = v.get_type(); + return r; } + bool is_ref() const; _FORCE_INLINE_ bool is_num() const { return type==INT || type==REAL; }; _FORCE_INLINE_ bool is_array() const { return type>=ARRAY; }; @@ -358,7 +362,7 @@ public: static String get_operator_name(Operator p_op); static void evaluate(const Operator& p_op,const Variant& p_a, const Variant& p_b,Variant &r_ret,bool &r_valid); - static _FORCE_INLINE_ Variant evaluate(Operator& p_op,const Variant& p_a, const Variant& p_b) { + static _FORCE_INLINE_ Variant evaluate(const Operator& p_op,const Variant& p_a, const Variant& p_b) { bool valid=true; Variant res; @@ -415,6 +419,12 @@ 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); + 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); _FORCE_INLINE_ Variant() { type=NIL; } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index bd731abeaf..c6b498ff28 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -511,7 +511,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 +519,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 +531,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]); } @@ -544,6 +544,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_PTR0R(Image,get_used_rect); VCALL_PTR3R(Image,brushed); VCALL_PTR1R(Image,load); + VCALL_PTR1R(Image,save_png); VCALL_PTR3(Image,brush_transfer); VCALL_PTR1R(Image,get_rect); VCALL_PTR1R(Image,compressed); @@ -684,6 +685,7 @@ 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_PTR0R( InputEvent, is_echo ); + VCALL_PTR2( InputEvent, set_as_action ); struct ConstructData { @@ -755,6 +757,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]); @@ -1256,8 +1263,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()); @@ -1325,6 +1332,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC4(IMAGE, NIL, Image, put_pixel, INT, "x", INT, "y", COLOR, "color", INT, "mipmap_level", varray(0)); ADDFUNC3(IMAGE, IMAGE, Image, brushed, IMAGE, "src", IMAGE, "brush", VECTOR2, "pos", varray(0)); ADDFUNC1(IMAGE, INT, Image, load, STRING, "path", varray(0)); + ADDFUNC1(IMAGE, INT, Image, save_png, STRING, "path", varray(0)); ADDFUNC3(IMAGE, NIL, Image, brush_transfer, IMAGE, "src", IMAGE, "brush", VECTOR2, "pos", varray(0)); ADDFUNC0(IMAGE, RECT2, Image, get_used_rect, varray(0)); ADDFUNC1(IMAGE, IMAGE, Image, get_rect, RECT2, "area", varray(0)); @@ -1488,6 +1496,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_pressed,varray()); ADDFUNC1(INPUT_EVENT,BOOL,InputEvent,is_action,STRING,"action",varray()); ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_echo,varray()); + ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray()); /* REGISTER CONSTRUCTORS */ @@ -1505,6 +1514,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); 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..87d9738b06 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -552,6 +552,9 @@ 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; @@ -736,6 +739,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 +943,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 +982,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 +1076,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 +1708,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 +2399,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; + ie.action.pressed; + } + } } break; case DICTIONARY: { diff --git a/core/vector.h b/core/vector.h index 90a9bf715b..d6453a3b83 100644 --- a/core/vector.h +++ b/core/vector.h @@ -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); diff --git a/demos/2d/area_input/box_area.png b/demos/2d/area_input/box_area.png Binary files differnew file mode 100644 index 0000000000..ba7c37f7de --- /dev/null +++ b/demos/2d/area_input/box_area.png diff --git a/demos/2d/area_input/circle_area.png b/demos/2d/area_input/circle_area.png Binary files differnew file mode 100644 index 0000000000..3cc24c8a0c --- /dev/null +++ b/demos/2d/area_input/circle_area.png diff --git a/demos/2d/area_input/engine.cfg b/demos/2d/area_input/engine.cfg new file mode 100644 index 0000000000..3227e9278f --- /dev/null +++ b/demos/2d/area_input/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="Area 2D Input Events" +main_scene="res://input.scn" diff --git a/demos/2d/area_input/input.gd b/demos/2d/area_input/input.gd new file mode 100644 index 0000000000..3f719fc853 --- /dev/null +++ b/demos/2d/area_input/input.gd @@ -0,0 +1,16 @@ + +extends Area2D + +#virtual from CollisionObject2D (also available as signal) +func _input_event(viewport, event, shape_idx): + #convert event to local coordinates + if (event.type==InputEvent.MOUSE_MOTION): + event = make_input_local( event ) + get_node("label").set_text(str(event.pos)) + +#virtual from CollisionObject2D (also available as signal) +func _mouse_exit(): + get_node("label").set_text("") + + + diff --git a/demos/2d/area_input/input.scn b/demos/2d/area_input/input.scn Binary files differnew file mode 100644 index 0000000000..1a2dcbc5f4 --- /dev/null +++ b/demos/2d/area_input/input.scn diff --git a/demos/2d/fog_of_war/.fscache b/demos/2d/fog_of_war/.fscache new file mode 100644 index 0000000000..ba5e3995f3 --- /dev/null +++ b/demos/2d/fog_of_war/.fscache @@ -0,0 +1,11 @@ +::res://::1422910453 +floor.png::ImageTexture::1422910453:: +fog.gd::GDScript::1422910025:: +fog.png::ImageTexture::1422908128:: +fog.scn::PackedScene::1422909435:: +fog.xml::TileSet::1422909324:: +icon.png::ImageTexture::1422811193:: +tile_edit.scn::PackedScene::1422909313:: +troll.gd::GDScript::1422909940:: +troll.png::ImageTexture::1418669358:: +troll.scn::PackedScene::1418669358:: diff --git a/demos/2d/fog_of_war/engine.cfg b/demos/2d/fog_of_war/engine.cfg new file mode 100644 index 0000000000..5c4307b5bc --- /dev/null +++ b/demos/2d/fog_of_war/engine.cfg @@ -0,0 +1,12 @@ +[application] + +name="Fog of War" +main_scene="res://fog.scn" +icon="icon.png" + +[input] + +move_up=[key(Up)] +move_bottom=[key(Down)] +move_left=[key(Left)] +move_right=[key(Right)] diff --git a/demos/2d/fog_of_war/floor.png b/demos/2d/fog_of_war/floor.png Binary files differnew file mode 100644 index 0000000000..07b4f8c98f --- /dev/null +++ b/demos/2d/fog_of_war/floor.png diff --git a/demos/2d/fog_of_war/fog.gd b/demos/2d/fog_of_war/fog.gd new file mode 100644 index 0000000000..9da5680e4d --- /dev/null +++ b/demos/2d/fog_of_war/fog.gd @@ -0,0 +1,86 @@ + +extends TileMap + +# member variables here, example: +# var a=2 +# var b="textvar" + +# boundarys for the fog rectangle +var x_min = -20 # left start tile +var x_max = 20 # right end tile +var y_min = -20 # top start tile +var y_max = 20 # bottom end tile + +var position # players position + +# iteration variables +var x +var y + +# variable to check if player moved +var x_old +var y_old + +# array to build up the visible area like a square +# first value determines the width/height of the tip +# here it would be 2*2 + 1 = 5 tiles wide/high +# second value determines the total squares size +# here it would be 5*2 + 1 = 10 tiles wide/high +var l = range(2,5) + +# process that runs in realtime +func _fixed_process(delta): + position = get_node("../troll").get_pos() + + # calculate the corresponding tile + # from the players position + x = int(position.x/get_cell_size().x) + # switching from positive to negative tile positions + # causes problems because of rounding problems + if position.x < 0: + x -= 1 # correct negative values + + y = int(position.y/get_cell_size().y) + if position.y < 0: + y -= 1 + + # check if the player moved one tile further + if (x_old != x) or (y_old != y): + + # create the transparent part (visited area) + var end = l.size()-1 + var start = 0 + for steps in range(l.size()): + for m in range(x-l[end]-1,x+l[end]+2): + for n in range(y-l[start]-1,y+l[start]+2): + if get_cell(m,n) != 0: + set_cell(m,n,1,0,0) + end -= 1 + start += 1 + + # create the actual and active visible part + var end = l.size()-1 + var start = 0 + for steps in range(l.size()): + for m in range(x-l[end],x+l[end]+1): + for n in range(y-l[start],y+l[start]+1): + set_cell(m,n,-1) + end -= 1 + start += 1 + + x_old = x + y_old = y + + pass + +func _ready(): + # Initalization here + + # create a square filled with the 100% opaque fog + for x in range(x_min,x_max): + for y in range(y_min,y_max): + set_cell(x,y,0,0,0) + set_fixed_process(true) + pass + + diff --git a/demos/2d/fog_of_war/fog.png b/demos/2d/fog_of_war/fog.png Binary files differnew file mode 100644 index 0000000000..56980c298d --- /dev/null +++ b/demos/2d/fog_of_war/fog.png diff --git a/demos/2d/fog_of_war/fog.scn b/demos/2d/fog_of_war/fog.scn Binary files differnew file mode 100644 index 0000000000..4987f1ead5 --- /dev/null +++ b/demos/2d/fog_of_war/fog.scn diff --git a/demos/2d/fog_of_war/fog.xml b/demos/2d/fog_of_war/fog.xml new file mode 100644 index 0000000000..ed08d84a1f --- /dev/null +++ b/demos/2d/fog_of_war/fog.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<resource_file type="TileSet" subresource_count="3" version="1.0" version_name="Godot Engine v1.0.stable.custom_build"> + <ext_resource path="res://floor.png" type="Texture"></ext_resource> + <ext_resource path="res://fog.png" type="Texture"></ext_resource> + <main_resource> + <string name="0/name"> "fog opaque" </string> + <resource name="0/texture" resource_type="Texture" path="res://fog.png"> </resource> + <vector2 name="0/tex_offset"> -48, -48 </vector2> + <vector2 name="0/shape_offset"> 0, 0 </vector2> + <rect2 name="0/region"> 0, 0, 144, 144 </rect2> + <array name="0/shapes" len="0" shared="false"> + </array> + <string name="1/name"> "fog transparent" </string> + <resource name="1/texture" resource_type="Texture" path="res://fog.png"> </resource> + <vector2 name="1/tex_offset"> -48, -48 </vector2> + <vector2 name="1/shape_offset"> 0, 0 </vector2> + <rect2 name="1/region"> 144, 0, 144, 144 </rect2> + <array name="1/shapes" len="0" shared="false"> + </array> + <string name="2/name"> "floor" </string> + <resource name="2/texture" resource_type="Texture" path="res://floor.png"> </resource> + <vector2 name="2/tex_offset"> 0, 0 </vector2> + <vector2 name="2/shape_offset"> 0, 0 </vector2> + <rect2 name="2/region"> 0, 0, 0, 0 </rect2> + <array name="2/shapes" len="0" shared="false"> + </array> + + </main_resource> +</resource_file>
\ No newline at end of file diff --git a/demos/2d/fog_of_war/icon.png b/demos/2d/fog_of_war/icon.png Binary files differnew file mode 100644 index 0000000000..a483390048 --- /dev/null +++ b/demos/2d/fog_of_war/icon.png diff --git a/demos/2d/fog_of_war/icon.png.flags b/demos/2d/fog_of_war/icon.png.flags new file mode 100644 index 0000000000..dbef2209e8 --- /dev/null +++ b/demos/2d/fog_of_war/icon.png.flags @@ -0,0 +1 @@ +gen_mipmaps=true diff --git a/demos/2d/fog_of_war/tile_edit.scn b/demos/2d/fog_of_war/tile_edit.scn Binary files differnew file mode 100644 index 0000000000..aaca19d370 --- /dev/null +++ b/demos/2d/fog_of_war/tile_edit.scn diff --git a/demos/2d/fog_of_war/troll.gd b/demos/2d/fog_of_war/troll.gd new file mode 100644 index 0000000000..d118d3a2ba --- /dev/null +++ b/demos/2d/fog_of_war/troll.gd @@ -0,0 +1,43 @@ + +extends KinematicBody2D + +# This is a simple collision demo showing how +# the kinematic cotroller works. +# move() will allow to move the node, and will +# always move it to a non-colliding spot, +# as long as it starts from a non-colliding spot too. + + +#pixels / second +const MOTION_SPEED=160 + +func _fixed_process(delta): + + var motion = Vector2() + + if (Input.is_action_pressed("move_up")): + motion+=Vector2(0,-1) + if (Input.is_action_pressed("move_bottom")): + motion+=Vector2(0,1) + if (Input.is_action_pressed("move_left")): + motion+=Vector2(-1,0) + if (Input.is_action_pressed("move_right")): + motion+=Vector2(1,0) + + motion = motion.normalized() * MOTION_SPEED * delta + motion = move(motion) + + #make character slide nicely through the world + var slide_attempts = 4 + while(is_colliding() and slide_attempts>0): + motion = get_collision_normal().slide(motion) + motion=move(motion) + slide_attempts-=1 + + +func _ready(): + # Initalization here + set_fixed_process(true) + pass + + diff --git a/demos/2d/fog_of_war/troll.png b/demos/2d/fog_of_war/troll.png Binary files differnew file mode 100644 index 0000000000..69f195d034 --- /dev/null +++ b/demos/2d/fog_of_war/troll.png diff --git a/demos/2d/fog_of_war/troll.scn b/demos/2d/fog_of_war/troll.scn Binary files differnew file mode 100644 index 0000000000..f5d87c3631 --- /dev/null +++ b/demos/2d/fog_of_war/troll.scn diff --git a/demos/2d/hdr/beach_cave.gd b/demos/2d/hdr/beach_cave.gd new file mode 100644 index 0000000000..9dffbc4662 --- /dev/null +++ b/demos/2d/hdr/beach_cave.gd @@ -0,0 +1,26 @@ + +extends Node2D + +# member variables here, example: +# var a=2 +# var b="textvar" +const CAVE_LIMIT=1000 + +func _input(ev): + if (ev.type==InputEvent.MOUSE_MOTION and ev.button_mask&1): + var rel_x = ev.relative_x + var cavepos = get_node("cave").get_pos() + cavepos.x+=rel_x + if (cavepos.x<-CAVE_LIMIT): + cavepos.x=-CAVE_LIMIT + elif (cavepos.x>0): + cavepos.x=0 + get_node("cave").set_pos(cavepos) + + +func _ready(): + set_process_input(true) + # Initialization here + pass + + diff --git a/demos/2d/hdr/beach_cave.scn b/demos/2d/hdr/beach_cave.scn Binary files differnew file mode 100644 index 0000000000..4147a130ad --- /dev/null +++ b/demos/2d/hdr/beach_cave.scn diff --git a/demos/2d/hdr/engine.cfg b/demos/2d/hdr/engine.cfg new file mode 100644 index 0000000000..3d8b4222d5 --- /dev/null +++ b/demos/2d/hdr/engine.cfg @@ -0,0 +1,13 @@ +[application] + +name="HDR for 2D" +main_scene="res://beach_cave.scn" + +[display] + +width=1080 +height=720 + +[rasterizer] + +blur_buffer_size=128 diff --git a/demos/2d/hdr/ocean_beach.png b/demos/2d/hdr/ocean_beach.png Binary files differnew file mode 100644 index 0000000000..a873d4f61d --- /dev/null +++ b/demos/2d/hdr/ocean_beach.png diff --git a/demos/2d/hdr/ocean_beach.png.flags b/demos/2d/hdr/ocean_beach.png.flags new file mode 100644 index 0000000000..82127bd7d5 --- /dev/null +++ b/demos/2d/hdr/ocean_beach.png.flags @@ -0,0 +1 @@ +tolinear=true diff --git a/demos/2d/hdr/ocean_cave.png b/demos/2d/hdr/ocean_cave.png Binary files differnew file mode 100644 index 0000000000..8875499df3 --- /dev/null +++ b/demos/2d/hdr/ocean_cave.png diff --git a/demos/2d/hdr/ocean_cave.png.flags b/demos/2d/hdr/ocean_cave.png.flags new file mode 100644 index 0000000000..82127bd7d5 --- /dev/null +++ b/demos/2d/hdr/ocean_cave.png.flags @@ -0,0 +1 @@ +tolinear=true diff --git a/demos/2d/hexamap/.fscache b/demos/2d/hexamap/.fscache deleted file mode 100644 index 60aa69b645..0000000000 --- a/demos/2d/hexamap/.fscache +++ /dev/null @@ -1,33 +0,0 @@ -::res://::1412302385 -WWT-01.png::ImageTexture::1412126473:: -WWT-02.png::ImageTexture::1412126474:: -WWT-03.png::ImageTexture::1412126474:: -WWT-04.png::ImageTexture::1412126474:: -WWT-05.png::ImageTexture::1412126474:: -WWT-06.png::ImageTexture::1412126474:: -WWT-07.png::ImageTexture::1412126474:: -WWT-08.png::ImageTexture::1412126474:: -WWT-09.png::ImageTexture::1412126474:: -WWT-10.png::ImageTexture::1412126474:: -WWT-11.png::ImageTexture::1412126475:: -WWT-12.png::ImageTexture::1412126475:: -WWT-13.png::ImageTexture::1412126475:: -WWT-14.png::ImageTexture::1412126475:: -WWT-15.png::ImageTexture::1412126475:: -WWT-16.png::ImageTexture::1412126475:: -WWT-17.png::ImageTexture::1412126475:: -WWT-18.png::ImageTexture::1412126475:: -WWT-19.png::ImageTexture::1412126476:: -WWT-20.png::ImageTexture::1412126476:: -WWT-21.png::ImageTexture::1412126476:: -WWT-22.png::ImageTexture::1412126476:: -WWT-23.png::ImageTexture::1412126476:: -WWT-24.png::ImageTexture::1412126476:: -WWT-25.png::ImageTexture::1412126476:: -WWT-26.png::ImageTexture::1412126476:: -map.scn::PackedScene::1412127344:: -tiles.scn::PackedScene::1412126994:: -tileset.res::TileSet::1412127001:: -troll.gd::GDScript::1412302377:: -troll.png::ImageTexture::1412302385:: -troll.scn::PackedScene::1412302380:: diff --git a/demos/2d/isometric/dungeon.scn b/demos/2d/isometric/dungeon.scn Binary files differindex 76532a44aa..58c530d5c5 100644 --- a/demos/2d/isometric/dungeon.scn +++ b/demos/2d/isometric/dungeon.scn diff --git a/demos/2d/isometric_light/character_shder.res b/demos/2d/isometric_light/character_shder.res Binary files differnew file mode 100644 index 0000000000..ca221f766c --- /dev/null +++ b/demos/2d/isometric_light/character_shder.res diff --git a/demos/2d/isometric_light/column.scn b/demos/2d/isometric_light/column.scn Binary files differnew file mode 100644 index 0000000000..f0b7683885 --- /dev/null +++ b/demos/2d/isometric_light/column.scn diff --git a/demos/2d/isometric_light/cubio.gd b/demos/2d/isometric_light/cubio.gd new file mode 100644 index 0000000000..30c766936c --- /dev/null +++ b/demos/2d/isometric_light/cubio.gd @@ -0,0 +1,96 @@ + +extends KinematicBody2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const MAX_SPEED = 300.0 +const IDLE_SPEED = 10.0 +const ACCEL=5.0 +const VSCALE=0.5 +const SHOOT_INTERVAL=0.3 + +var speed=Vector2() +var current_anim="" +var current_mirror=false + +var shoot_countdown=0 + +func _input(ev): + if (ev.type==InputEvent.MOUSE_BUTTON and ev.button_index==1 and ev.pressed and shoot_countdown<=0): + var pos = get_canvas_transform().affine_inverse() * ev.pos + var dir = (pos-get_global_pos()).normalized() + var bullet = preload("res://shoot.scn").instance() + bullet.advance_dir=dir + bullet.set_pos( get_global_pos() + dir * 60 ) + get_parent().add_child(bullet) + shoot_countdown=SHOOT_INTERVAL + + + + +func _fixed_process(delta): + + shoot_countdown-=delta + var dir = Vector2() + if (Input.is_action_pressed("up")): + dir+=Vector2(0,-1) + if (Input.is_action_pressed("down")): + dir+=Vector2(0,1) + if (Input.is_action_pressed("left")): + dir+=Vector2(-1,0) + if (Input.is_action_pressed("right")): + dir+=Vector2(1,0) + + if (dir!=Vector2()): + dir=dir.normalized() + speed = speed.linear_interpolate(dir*MAX_SPEED,delta*ACCEL) + var motion = speed * delta + motion.y*=VSCALE + motion=move(motion) + + if (is_colliding()): + var n = get_collision_normal() + motion=n.slide(motion) + move(motion) + + var next_anim="" + var next_mirror=false + + if (dir==Vector2() and speed.length()<IDLE_SPEED): + next_anim="idle" + next_mirror=false + elif (speed.length()>IDLE_SPEED*0.1): + var angle = atan2(abs(speed.x),speed.y) + + next_mirror = speed.x>0 + if (angle<PI/8): + next_anim="bottom" + next_mirror=false + elif (angle<PI/4+PI/8): + next_anim="bottom_left" + elif (angle<PI*2/4+PI/8): + next_anim="left" + elif (angle<PI*3/4+PI/8): + next_anim="top_left" + else: + next_anim="top" + next_mirror=false + + + if (next_anim!=current_anim or next_mirror!=current_mirror): + get_node("frames").set_flip_h(next_mirror) + get_node("anim").play(next_anim) + current_anim=next_anim + current_mirror=next_mirror + + + +func _ready(): + # Initialization here + set_fixed_process(true) + set_process_input(true) + pass + + diff --git a/demos/2d/isometric_light/cubio.scn b/demos/2d/isometric_light/cubio.scn Binary files differnew file mode 100644 index 0000000000..c8ab7ddd4e --- /dev/null +++ b/demos/2d/isometric_light/cubio.scn diff --git a/demos/2d/isometric_light/cubio/idle0001.png b/demos/2d/isometric_light/cubio/idle0001.png Binary files differnew file mode 100644 index 0000000000..837dd38f9c --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0001.png diff --git a/demos/2d/isometric_light/cubio/idle0002.png b/demos/2d/isometric_light/cubio/idle0002.png Binary files differnew file mode 100644 index 0000000000..6137a37a9d --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0002.png diff --git a/demos/2d/isometric_light/cubio/idle0003.png b/demos/2d/isometric_light/cubio/idle0003.png Binary files differnew file mode 100644 index 0000000000..7f3e3e0e31 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0003.png diff --git a/demos/2d/isometric_light/cubio/idle0004.png b/demos/2d/isometric_light/cubio/idle0004.png Binary files differnew file mode 100644 index 0000000000..0a697dadf9 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0004.png diff --git a/demos/2d/isometric_light/cubio/idle0005.png b/demos/2d/isometric_light/cubio/idle0005.png Binary files differnew file mode 100644 index 0000000000..9c47197247 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0005.png diff --git a/demos/2d/isometric_light/cubio/idle0006.png b/demos/2d/isometric_light/cubio/idle0006.png Binary files differnew file mode 100644 index 0000000000..717a7be5b1 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0006.png diff --git a/demos/2d/isometric_light/cubio/idle0007.png b/demos/2d/isometric_light/cubio/idle0007.png Binary files differnew file mode 100644 index 0000000000..dde18399f3 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0007.png diff --git a/demos/2d/isometric_light/cubio/idle0008.png b/demos/2d/isometric_light/cubio/idle0008.png Binary files differnew file mode 100644 index 0000000000..0f716a5d84 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0008.png diff --git a/demos/2d/isometric_light/cubio/idle0009.png b/demos/2d/isometric_light/cubio/idle0009.png Binary files differnew file mode 100644 index 0000000000..d271373f9d --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0009.png diff --git a/demos/2d/isometric_light/cubio/idle0010.png b/demos/2d/isometric_light/cubio/idle0010.png Binary files differnew file mode 100644 index 0000000000..61311be0eb --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0010.png diff --git a/demos/2d/isometric_light/cubio/idle0011.png b/demos/2d/isometric_light/cubio/idle0011.png Binary files differnew file mode 100644 index 0000000000..0b7d32d138 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0011.png diff --git a/demos/2d/isometric_light/cubio/idle0012.png b/demos/2d/isometric_light/cubio/idle0012.png Binary files differnew file mode 100644 index 0000000000..c176034cfa --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0012.png diff --git a/demos/2d/isometric_light/cubio/idle0013.png b/demos/2d/isometric_light/cubio/idle0013.png Binary files differnew file mode 100644 index 0000000000..c37018154b --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0013.png diff --git a/demos/2d/isometric_light/cubio/idle0014.png b/demos/2d/isometric_light/cubio/idle0014.png Binary files differnew file mode 100644 index 0000000000..a4613e4269 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0014.png diff --git a/demos/2d/isometric_light/cubio/idle0015.png b/demos/2d/isometric_light/cubio/idle0015.png Binary files differnew file mode 100644 index 0000000000..8354588b72 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0015.png diff --git a/demos/2d/isometric_light/cubio/idle0016.png b/demos/2d/isometric_light/cubio/idle0016.png Binary files differnew file mode 100644 index 0000000000..4e5796fb89 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0016.png diff --git a/demos/2d/isometric_light/cubio/idle0017.png b/demos/2d/isometric_light/cubio/idle0017.png Binary files differnew file mode 100644 index 0000000000..a4ac7e8c43 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0017.png diff --git a/demos/2d/isometric_light/cubio/idle0018.png b/demos/2d/isometric_light/cubio/idle0018.png Binary files differnew file mode 100644 index 0000000000..aa7cc8fe6c --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0018.png diff --git a/demos/2d/isometric_light/cubio/idle0019.png b/demos/2d/isometric_light/cubio/idle0019.png Binary files differnew file mode 100644 index 0000000000..3ab603ceda --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0019.png diff --git a/demos/2d/isometric_light/cubio/idle0020.png b/demos/2d/isometric_light/cubio/idle0020.png Binary files differnew file mode 100644 index 0000000000..9f02648f1a --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0020.png diff --git a/demos/2d/isometric_light/cubio/idle0021.png b/demos/2d/isometric_light/cubio/idle0021.png Binary files differnew file mode 100644 index 0000000000..ec37fc331f --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0021.png diff --git a/demos/2d/isometric_light/cubio/idle0022.png b/demos/2d/isometric_light/cubio/idle0022.png Binary files differnew file mode 100644 index 0000000000..34bf331af0 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0022.png diff --git a/demos/2d/isometric_light/cubio/idle0023.png b/demos/2d/isometric_light/cubio/idle0023.png Binary files differnew file mode 100644 index 0000000000..80a458146e --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0023.png diff --git a/demos/2d/isometric_light/cubio/idle0024.png b/demos/2d/isometric_light/cubio/idle0024.png Binary files differnew file mode 100644 index 0000000000..cd08c6d14a --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0024.png diff --git a/demos/2d/isometric_light/cubio/idle0025.png b/demos/2d/isometric_light/cubio/idle0025.png Binary files differnew file mode 100644 index 0000000000..de500512d4 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0025.png diff --git a/demos/2d/isometric_light/cubio/idle0026.png b/demos/2d/isometric_light/cubio/idle0026.png Binary files differnew file mode 100644 index 0000000000..4a8335a248 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0026.png diff --git a/demos/2d/isometric_light/cubio/idle0027.png b/demos/2d/isometric_light/cubio/idle0027.png Binary files differnew file mode 100644 index 0000000000..c3d1609a03 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0027.png diff --git a/demos/2d/isometric_light/cubio/idle0028.png b/demos/2d/isometric_light/cubio/idle0028.png Binary files differnew file mode 100644 index 0000000000..96c1f32223 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0028.png diff --git a/demos/2d/isometric_light/cubio/idle0029.png b/demos/2d/isometric_light/cubio/idle0029.png Binary files differnew file mode 100644 index 0000000000..5b72d02300 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0029.png diff --git a/demos/2d/isometric_light/cubio/idle0030.png b/demos/2d/isometric_light/cubio/idle0030.png Binary files differnew file mode 100644 index 0000000000..a84787bf0a --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0030.png diff --git a/demos/2d/isometric_light/cubio/idle0031.png b/demos/2d/isometric_light/cubio/idle0031.png Binary files differnew file mode 100644 index 0000000000..dc9cd7ddc5 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0031.png diff --git a/demos/2d/isometric_light/cubio/idle0032.png b/demos/2d/isometric_light/cubio/idle0032.png Binary files differnew file mode 100644 index 0000000000..c99f2e52bc --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0032.png diff --git a/demos/2d/isometric_light/cubio/idle0033.png b/demos/2d/isometric_light/cubio/idle0033.png Binary files differnew file mode 100644 index 0000000000..cf5c648f9e --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0033.png diff --git a/demos/2d/isometric_light/cubio/idle0034.png b/demos/2d/isometric_light/cubio/idle0034.png Binary files differnew file mode 100644 index 0000000000..8e18e12d8d --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0034.png diff --git a/demos/2d/isometric_light/cubio/idle0035.png b/demos/2d/isometric_light/cubio/idle0035.png Binary files differnew file mode 100644 index 0000000000..ee2c25ee96 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0035.png diff --git a/demos/2d/isometric_light/cubio/idle0036.png b/demos/2d/isometric_light/cubio/idle0036.png Binary files differnew file mode 100644 index 0000000000..f452b5db33 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0036.png diff --git a/demos/2d/isometric_light/cubio/idle0037.png b/demos/2d/isometric_light/cubio/idle0037.png Binary files differnew file mode 100644 index 0000000000..7768c712e3 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0037.png diff --git a/demos/2d/isometric_light/cubio/idle0038.png b/demos/2d/isometric_light/cubio/idle0038.png Binary files differnew file mode 100644 index 0000000000..1200127116 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0038.png diff --git a/demos/2d/isometric_light/cubio/idle0039.png b/demos/2d/isometric_light/cubio/idle0039.png Binary files differnew file mode 100644 index 0000000000..25219f0582 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0039.png diff --git a/demos/2d/isometric_light/cubio/idle0040.png b/demos/2d/isometric_light/cubio/idle0040.png Binary files differnew file mode 100644 index 0000000000..8da0a81050 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0040.png diff --git a/demos/2d/isometric_light/cubio/idle0041.png b/demos/2d/isometric_light/cubio/idle0041.png Binary files differnew file mode 100644 index 0000000000..fa102aec8a --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0041.png diff --git a/demos/2d/isometric_light/cubio/idle0042.png b/demos/2d/isometric_light/cubio/idle0042.png Binary files differnew file mode 100644 index 0000000000..0d19c32572 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0042.png diff --git a/demos/2d/isometric_light/cubio/idle0043.png b/demos/2d/isometric_light/cubio/idle0043.png Binary files differnew file mode 100644 index 0000000000..bf284c62d0 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0043.png diff --git a/demos/2d/isometric_light/cubio/idle0044.png b/demos/2d/isometric_light/cubio/idle0044.png Binary files differnew file mode 100644 index 0000000000..3daa1be0b8 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0044.png diff --git a/demos/2d/isometric_light/cubio/idle0045.png b/demos/2d/isometric_light/cubio/idle0045.png Binary files differnew file mode 100644 index 0000000000..92abe74295 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0045.png diff --git a/demos/2d/isometric_light/cubio/idle0046.png b/demos/2d/isometric_light/cubio/idle0046.png Binary files differnew file mode 100644 index 0000000000..2a1ab0f036 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0046.png diff --git a/demos/2d/isometric_light/cubio/idle0047.png b/demos/2d/isometric_light/cubio/idle0047.png Binary files differnew file mode 100644 index 0000000000..da38b835ef --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0047.png diff --git a/demos/2d/isometric_light/cubio/idle0048.png b/demos/2d/isometric_light/cubio/idle0048.png Binary files differnew file mode 100644 index 0000000000..35fac1b602 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0048.png diff --git a/demos/2d/isometric_light/cubio/idle0049.png b/demos/2d/isometric_light/cubio/idle0049.png Binary files differnew file mode 100644 index 0000000000..7ebd79b8d7 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0049.png diff --git a/demos/2d/isometric_light/cubio/idle0050.png b/demos/2d/isometric_light/cubio/idle0050.png Binary files differnew file mode 100644 index 0000000000..ba0678ba87 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0050.png diff --git a/demos/2d/isometric_light/cubio/idle0051.png b/demos/2d/isometric_light/cubio/idle0051.png Binary files differnew file mode 100644 index 0000000000..03c54f1232 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0051.png diff --git a/demos/2d/isometric_light/cubio/idle0052.png b/demos/2d/isometric_light/cubio/idle0052.png Binary files differnew file mode 100644 index 0000000000..0e2c8b5d9f --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0052.png diff --git a/demos/2d/isometric_light/cubio/idle0053.png b/demos/2d/isometric_light/cubio/idle0053.png Binary files differnew file mode 100644 index 0000000000..d95095937f --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0053.png diff --git a/demos/2d/isometric_light/cubio/idle0054.png b/demos/2d/isometric_light/cubio/idle0054.png Binary files differnew file mode 100644 index 0000000000..5a09fce69e --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0054.png diff --git a/demos/2d/isometric_light/cubio/idle0055.png b/demos/2d/isometric_light/cubio/idle0055.png Binary files differnew file mode 100644 index 0000000000..6e2aad9d70 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0055.png diff --git a/demos/2d/isometric_light/cubio/idle0056.png b/demos/2d/isometric_light/cubio/idle0056.png Binary files differnew file mode 100644 index 0000000000..45813e953f --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0056.png diff --git a/demos/2d/isometric_light/cubio/idle0057.png b/demos/2d/isometric_light/cubio/idle0057.png Binary files differnew file mode 100644 index 0000000000..579b4e1647 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0057.png diff --git a/demos/2d/isometric_light/cubio/idle0058.png b/demos/2d/isometric_light/cubio/idle0058.png Binary files differnew file mode 100644 index 0000000000..236f290651 --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0058.png diff --git a/demos/2d/isometric_light/cubio/idle0059.png b/demos/2d/isometric_light/cubio/idle0059.png Binary files differnew file mode 100644 index 0000000000..837dd38f9c --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0059.png diff --git a/demos/2d/isometric_light/cubio/idle0060.png b/demos/2d/isometric_light/cubio/idle0060.png Binary files differnew file mode 100644 index 0000000000..837dd38f9c --- /dev/null +++ b/demos/2d/isometric_light/cubio/idle0060.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0001.png b/demos/2d/isometric_light/cubio/norm-b-0001.png Binary files differnew file mode 100644 index 0000000000..cda17e21cc --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0001.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0002.png b/demos/2d/isometric_light/cubio/norm-b-0002.png Binary files differnew file mode 100644 index 0000000000..fb36728cdf --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0002.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0003.png b/demos/2d/isometric_light/cubio/norm-b-0003.png Binary files differnew file mode 100644 index 0000000000..c8bfecb100 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0003.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0004.png b/demos/2d/isometric_light/cubio/norm-b-0004.png Binary files differnew file mode 100644 index 0000000000..e91213434f --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0004.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0005.png b/demos/2d/isometric_light/cubio/norm-b-0005.png Binary files differnew file mode 100644 index 0000000000..a823fe9a92 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0005.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0006.png b/demos/2d/isometric_light/cubio/norm-b-0006.png Binary files differnew file mode 100644 index 0000000000..d9de12baad --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0006.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0007.png b/demos/2d/isometric_light/cubio/norm-b-0007.png Binary files differnew file mode 100644 index 0000000000..f042eed408 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0007.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0008.png b/demos/2d/isometric_light/cubio/norm-b-0008.png Binary files differnew file mode 100644 index 0000000000..e18ca607dd --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0008.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0009.png b/demos/2d/isometric_light/cubio/norm-b-0009.png Binary files differnew file mode 100644 index 0000000000..7e7ddd4c63 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0009.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0010.png b/demos/2d/isometric_light/cubio/norm-b-0010.png Binary files differnew file mode 100644 index 0000000000..fddb956099 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0010.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0011.png b/demos/2d/isometric_light/cubio/norm-b-0011.png Binary files differnew file mode 100644 index 0000000000..240a50a9ec --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0011.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0012.png b/demos/2d/isometric_light/cubio/norm-b-0012.png Binary files differnew file mode 100644 index 0000000000..3e38628e98 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0012.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0013.png b/demos/2d/isometric_light/cubio/norm-b-0013.png Binary files differnew file mode 100644 index 0000000000..2380e76909 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0013.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0014.png b/demos/2d/isometric_light/cubio/norm-b-0014.png Binary files differnew file mode 100644 index 0000000000..db374927c6 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0014.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0015.png b/demos/2d/isometric_light/cubio/norm-b-0015.png Binary files differnew file mode 100644 index 0000000000..1cd0e762c5 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0015.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0016.png b/demos/2d/isometric_light/cubio/norm-b-0016.png Binary files differnew file mode 100644 index 0000000000..0d894db3f4 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0016.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0017.png b/demos/2d/isometric_light/cubio/norm-b-0017.png Binary files differnew file mode 100644 index 0000000000..c184af8e85 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0017.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0018.png b/demos/2d/isometric_light/cubio/norm-b-0018.png Binary files differnew file mode 100644 index 0000000000..1db06014b7 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0018.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0019.png b/demos/2d/isometric_light/cubio/norm-b-0019.png Binary files differnew file mode 100644 index 0000000000..e74c9c7954 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0019.png diff --git a/demos/2d/isometric_light/cubio/norm-b-0020.png b/demos/2d/isometric_light/cubio/norm-b-0020.png Binary files differnew file mode 100644 index 0000000000..326e60c64a --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-b-0020.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0001.png b/demos/2d/isometric_light/cubio/norm-bl-0001.png Binary files differnew file mode 100644 index 0000000000..0b36e8caa3 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0001.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0002.png b/demos/2d/isometric_light/cubio/norm-bl-0002.png Binary files differnew file mode 100644 index 0000000000..f00166d140 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0002.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0003.png b/demos/2d/isometric_light/cubio/norm-bl-0003.png Binary files differnew file mode 100644 index 0000000000..d84993e097 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0003.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0004.png b/demos/2d/isometric_light/cubio/norm-bl-0004.png Binary files differnew file mode 100644 index 0000000000..8e4c7f278b --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0004.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0005.png b/demos/2d/isometric_light/cubio/norm-bl-0005.png Binary files differnew file mode 100644 index 0000000000..5009f2a514 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0005.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0006.png b/demos/2d/isometric_light/cubio/norm-bl-0006.png Binary files differnew file mode 100644 index 0000000000..d0d654de6e --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0006.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0007.png b/demos/2d/isometric_light/cubio/norm-bl-0007.png Binary files differnew file mode 100644 index 0000000000..2df2437a0d --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0007.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0008.png b/demos/2d/isometric_light/cubio/norm-bl-0008.png Binary files differnew file mode 100644 index 0000000000..4bb8e91ecc --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0008.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0009.png b/demos/2d/isometric_light/cubio/norm-bl-0009.png Binary files differnew file mode 100644 index 0000000000..e4ab80ab72 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0009.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0010.png b/demos/2d/isometric_light/cubio/norm-bl-0010.png Binary files differnew file mode 100644 index 0000000000..7ead89343f --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0010.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0011.png b/demos/2d/isometric_light/cubio/norm-bl-0011.png Binary files differnew file mode 100644 index 0000000000..9714999645 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0011.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0012.png b/demos/2d/isometric_light/cubio/norm-bl-0012.png Binary files differnew file mode 100644 index 0000000000..95e0117df8 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0012.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0013.png b/demos/2d/isometric_light/cubio/norm-bl-0013.png Binary files differnew file mode 100644 index 0000000000..85d4f25e7e --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0013.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0014.png b/demos/2d/isometric_light/cubio/norm-bl-0014.png Binary files differnew file mode 100644 index 0000000000..3c9cc526d0 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0014.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0015.png b/demos/2d/isometric_light/cubio/norm-bl-0015.png Binary files differnew file mode 100644 index 0000000000..3e30649ce1 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0015.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0016.png b/demos/2d/isometric_light/cubio/norm-bl-0016.png Binary files differnew file mode 100644 index 0000000000..f39399c369 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0016.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0017.png b/demos/2d/isometric_light/cubio/norm-bl-0017.png Binary files differnew file mode 100644 index 0000000000..47f79741a1 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0017.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0018.png b/demos/2d/isometric_light/cubio/norm-bl-0018.png Binary files differnew file mode 100644 index 0000000000..8f4ccdcf33 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0018.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0019.png b/demos/2d/isometric_light/cubio/norm-bl-0019.png Binary files differnew file mode 100644 index 0000000000..a278ec0f05 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0019.png diff --git a/demos/2d/isometric_light/cubio/norm-bl-0020.png b/demos/2d/isometric_light/cubio/norm-bl-0020.png Binary files differnew file mode 100644 index 0000000000..db5fd0b73c --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-bl-0020.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0001.png b/demos/2d/isometric_light/cubio/norm-l-0001.png Binary files differnew file mode 100644 index 0000000000..7a989e79dd --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0001.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0002.png b/demos/2d/isometric_light/cubio/norm-l-0002.png Binary files differnew file mode 100644 index 0000000000..2257923ee6 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0002.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0003.png b/demos/2d/isometric_light/cubio/norm-l-0003.png Binary files differnew file mode 100644 index 0000000000..2e264e49a4 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0003.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0004.png b/demos/2d/isometric_light/cubio/norm-l-0004.png Binary files differnew file mode 100644 index 0000000000..e0061451d6 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0004.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0005.png b/demos/2d/isometric_light/cubio/norm-l-0005.png Binary files differnew file mode 100644 index 0000000000..e16cca081c --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0005.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0006.png b/demos/2d/isometric_light/cubio/norm-l-0006.png Binary files differnew file mode 100644 index 0000000000..694c2163eb --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0006.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0007.png b/demos/2d/isometric_light/cubio/norm-l-0007.png Binary files differnew file mode 100644 index 0000000000..ed2ae64cad --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0007.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0008.png b/demos/2d/isometric_light/cubio/norm-l-0008.png Binary files differnew file mode 100644 index 0000000000..4bbaeb8006 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0008.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0009.png b/demos/2d/isometric_light/cubio/norm-l-0009.png Binary files differnew file mode 100644 index 0000000000..1f53a1067b --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0009.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0010.png b/demos/2d/isometric_light/cubio/norm-l-0010.png Binary files differnew file mode 100644 index 0000000000..2007942a2a --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0010.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0011.png b/demos/2d/isometric_light/cubio/norm-l-0011.png Binary files differnew file mode 100644 index 0000000000..0c27288646 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0011.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0012.png b/demos/2d/isometric_light/cubio/norm-l-0012.png Binary files differnew file mode 100644 index 0000000000..8b885bcee8 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0012.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0013.png b/demos/2d/isometric_light/cubio/norm-l-0013.png Binary files differnew file mode 100644 index 0000000000..ed08c9a470 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0013.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0014.png b/demos/2d/isometric_light/cubio/norm-l-0014.png Binary files differnew file mode 100644 index 0000000000..3b6088c9a0 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0014.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0015.png b/demos/2d/isometric_light/cubio/norm-l-0015.png Binary files differnew file mode 100644 index 0000000000..1ffa2b8cda --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0015.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0016.png b/demos/2d/isometric_light/cubio/norm-l-0016.png Binary files differnew file mode 100644 index 0000000000..00279dc052 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0016.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0017.png b/demos/2d/isometric_light/cubio/norm-l-0017.png Binary files differnew file mode 100644 index 0000000000..1805000a78 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0017.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0018.png b/demos/2d/isometric_light/cubio/norm-l-0018.png Binary files differnew file mode 100644 index 0000000000..1ff123533f --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0018.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0019.png b/demos/2d/isometric_light/cubio/norm-l-0019.png Binary files differnew file mode 100644 index 0000000000..2faf043a2b --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0019.png diff --git a/demos/2d/isometric_light/cubio/norm-l-0020.png b/demos/2d/isometric_light/cubio/norm-l-0020.png Binary files differnew file mode 100644 index 0000000000..7948d2d79d --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-l-0020.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0001.png b/demos/2d/isometric_light/cubio/norm-u-0001.png Binary files differnew file mode 100644 index 0000000000..6c702ba7c3 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0001.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0002.png b/demos/2d/isometric_light/cubio/norm-u-0002.png Binary files differnew file mode 100644 index 0000000000..9a151e049b --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0002.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0003.png b/demos/2d/isometric_light/cubio/norm-u-0003.png Binary files differnew file mode 100644 index 0000000000..0b7464260a --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0003.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0004.png b/demos/2d/isometric_light/cubio/norm-u-0004.png Binary files differnew file mode 100644 index 0000000000..89061fdbcf --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0004.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0005.png b/demos/2d/isometric_light/cubio/norm-u-0005.png Binary files differnew file mode 100644 index 0000000000..efc8ab0157 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0005.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0006.png b/demos/2d/isometric_light/cubio/norm-u-0006.png Binary files differnew file mode 100644 index 0000000000..a89ef58f46 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0006.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0007.png b/demos/2d/isometric_light/cubio/norm-u-0007.png Binary files differnew file mode 100644 index 0000000000..b069591200 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0007.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0008.png b/demos/2d/isometric_light/cubio/norm-u-0008.png Binary files differnew file mode 100644 index 0000000000..8f0dbe8016 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0008.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0009.png b/demos/2d/isometric_light/cubio/norm-u-0009.png Binary files differnew file mode 100644 index 0000000000..d4698f2584 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0009.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0010.png b/demos/2d/isometric_light/cubio/norm-u-0010.png Binary files differnew file mode 100644 index 0000000000..cc3d442d4a --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0010.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0011.png b/demos/2d/isometric_light/cubio/norm-u-0011.png Binary files differnew file mode 100644 index 0000000000..43c505d7e4 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0011.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0012.png b/demos/2d/isometric_light/cubio/norm-u-0012.png Binary files differnew file mode 100644 index 0000000000..d4f955fd0c --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0012.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0013.png b/demos/2d/isometric_light/cubio/norm-u-0013.png Binary files differnew file mode 100644 index 0000000000..08dd875a54 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0013.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0014.png b/demos/2d/isometric_light/cubio/norm-u-0014.png Binary files differnew file mode 100644 index 0000000000..4bea108a46 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0014.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0015.png b/demos/2d/isometric_light/cubio/norm-u-0015.png Binary files differnew file mode 100644 index 0000000000..943c556706 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0015.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0016.png b/demos/2d/isometric_light/cubio/norm-u-0016.png Binary files differnew file mode 100644 index 0000000000..d71a69c5a6 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0016.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0017.png b/demos/2d/isometric_light/cubio/norm-u-0017.png Binary files differnew file mode 100644 index 0000000000..2d74e4472c --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0017.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0018.png b/demos/2d/isometric_light/cubio/norm-u-0018.png Binary files differnew file mode 100644 index 0000000000..17a5b10acb --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0018.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0019.png b/demos/2d/isometric_light/cubio/norm-u-0019.png Binary files differnew file mode 100644 index 0000000000..e376c843e1 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0019.png diff --git a/demos/2d/isometric_light/cubio/norm-u-0020.png b/demos/2d/isometric_light/cubio/norm-u-0020.png Binary files differnew file mode 100644 index 0000000000..fa1d3521ca --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-u-0020.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0001.png b/demos/2d/isometric_light/cubio/norm-ul-0001.png Binary files differnew file mode 100644 index 0000000000..3e75621260 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0001.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0002.png b/demos/2d/isometric_light/cubio/norm-ul-0002.png Binary files differnew file mode 100644 index 0000000000..d48d902936 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0002.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0003.png b/demos/2d/isometric_light/cubio/norm-ul-0003.png Binary files differnew file mode 100644 index 0000000000..703cef6715 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0003.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0004.png b/demos/2d/isometric_light/cubio/norm-ul-0004.png Binary files differnew file mode 100644 index 0000000000..7dd3e2884e --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0004.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0005.png b/demos/2d/isometric_light/cubio/norm-ul-0005.png Binary files differnew file mode 100644 index 0000000000..1281b9ceb8 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0005.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0006.png b/demos/2d/isometric_light/cubio/norm-ul-0006.png Binary files differnew file mode 100644 index 0000000000..e3c58752e9 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0006.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0007.png b/demos/2d/isometric_light/cubio/norm-ul-0007.png Binary files differnew file mode 100644 index 0000000000..ccec10c83c --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0007.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0008.png b/demos/2d/isometric_light/cubio/norm-ul-0008.png Binary files differnew file mode 100644 index 0000000000..1243c7dfe8 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0008.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0009.png b/demos/2d/isometric_light/cubio/norm-ul-0009.png Binary files differnew file mode 100644 index 0000000000..77ea3ca8e9 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0009.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0010.png b/demos/2d/isometric_light/cubio/norm-ul-0010.png Binary files differnew file mode 100644 index 0000000000..cf1cb7d0e3 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0010.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0011.png b/demos/2d/isometric_light/cubio/norm-ul-0011.png Binary files differnew file mode 100644 index 0000000000..1063ee29a8 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0011.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0012.png b/demos/2d/isometric_light/cubio/norm-ul-0012.png Binary files differnew file mode 100644 index 0000000000..a896237161 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0012.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0013.png b/demos/2d/isometric_light/cubio/norm-ul-0013.png Binary files differnew file mode 100644 index 0000000000..cc289b18a0 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0013.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0014.png b/demos/2d/isometric_light/cubio/norm-ul-0014.png Binary files differnew file mode 100644 index 0000000000..faf36e82b6 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0014.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0015.png b/demos/2d/isometric_light/cubio/norm-ul-0015.png Binary files differnew file mode 100644 index 0000000000..925be82a2e --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0015.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0016.png b/demos/2d/isometric_light/cubio/norm-ul-0016.png Binary files differnew file mode 100644 index 0000000000..1cb2300b9d --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0016.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0017.png b/demos/2d/isometric_light/cubio/norm-ul-0017.png Binary files differnew file mode 100644 index 0000000000..5a841b57af --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0017.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0018.png b/demos/2d/isometric_light/cubio/norm-ul-0018.png Binary files differnew file mode 100644 index 0000000000..2b30df8988 --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0018.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0019.png b/demos/2d/isometric_light/cubio/norm-ul-0019.png Binary files differnew file mode 100644 index 0000000000..12c0a72d6d --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0019.png diff --git a/demos/2d/isometric_light/cubio/norm-ul-0020.png b/demos/2d/isometric_light/cubio/norm-ul-0020.png Binary files differnew file mode 100644 index 0000000000..3cffda17ca --- /dev/null +++ b/demos/2d/isometric_light/cubio/norm-ul-0020.png diff --git a/demos/2d/isometric_light/energy.png b/demos/2d/isometric_light/energy.png Binary files differnew file mode 100644 index 0000000000..237e3ea4f0 --- /dev/null +++ b/demos/2d/isometric_light/energy.png diff --git a/demos/2d/isometric_light/engine.cfg b/demos/2d/isometric_light/engine.cfg new file mode 100644 index 0000000000..0d9e432d5d --- /dev/null +++ b/demos/2d/isometric_light/engine.cfg @@ -0,0 +1,18 @@ +[application] + +main_scene="res://map.scn" + +[input] + +up=[key(Up), key(W)] +down=[key(S), key(Down)] +left=[key(Left), key(A)] +right=[key(Right), key(D)] + +[rasterizer] + +shadow_filter=0 + +[render] + +default_clear_color=#ff000000 diff --git a/demos/2d/isometric_light/faceColor.png b/demos/2d/isometric_light/faceColor.png Binary files differnew file mode 100644 index 0000000000..c6daf73cb7 --- /dev/null +++ b/demos/2d/isometric_light/faceColor.png diff --git a/demos/2d/isometric_light/faceMask.png b/demos/2d/isometric_light/faceMask.png Binary files differnew file mode 100644 index 0000000000..d91e968c8e --- /dev/null +++ b/demos/2d/isometric_light/faceMask.png diff --git a/demos/2d/isometric_light/faceNormal.png b/demos/2d/isometric_light/faceNormal.png Binary files differnew file mode 100644 index 0000000000..651f075fa1 --- /dev/null +++ b/demos/2d/isometric_light/faceNormal.png diff --git a/demos/2d/isometric_light/fire.png b/demos/2d/isometric_light/fire.png Binary files differnew file mode 100644 index 0000000000..746e4f9f4b --- /dev/null +++ b/demos/2d/isometric_light/fire.png diff --git a/demos/2d/isometric_light/floor_shader.res b/demos/2d/isometric_light/floor_shader.res Binary files differnew file mode 100644 index 0000000000..446c71d227 --- /dev/null +++ b/demos/2d/isometric_light/floor_shader.res diff --git a/demos/2d/isometric_light/light2.png b/demos/2d/isometric_light/light2.png Binary files differnew file mode 100644 index 0000000000..cd473251aa --- /dev/null +++ b/demos/2d/isometric_light/light2.png diff --git a/demos/2d/isometric_light/map.gd b/demos/2d/isometric_light/map.gd new file mode 100644 index 0000000000..f712aeeaec --- /dev/null +++ b/demos/2d/isometric_light/map.gd @@ -0,0 +1,18 @@ + +extends Node2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +func _ready(): + # Initialization here + pass + + + + +func _on_prince_area_body_enter( body ): + if (body.get_name()=="cubio"): + get_node("message").show() + pass # replace with function body diff --git a/demos/2d/isometric_light/map.scn b/demos/2d/isometric_light/map.scn Binary files differnew file mode 100644 index 0000000000..c939a4b392 --- /dev/null +++ b/demos/2d/isometric_light/map.scn diff --git a/demos/2d/isometric_light/shadow_blob.png b/demos/2d/isometric_light/shadow_blob.png Binary files differnew file mode 100644 index 0000000000..e97fd2a826 --- /dev/null +++ b/demos/2d/isometric_light/shadow_blob.png diff --git a/demos/2d/isometric_light/shoot.gd b/demos/2d/isometric_light/shoot.gd new file mode 100644 index 0000000000..0486bbb658 --- /dev/null +++ b/demos/2d/isometric_light/shoot.gd @@ -0,0 +1,27 @@ + +extends KinematicBody2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +var advance_dir=Vector2(1,0) +const ADVANCE_SPEED = 500.0 + +var hit=false + +func _fixed_process(delta): + + if (hit): + return + move(advance_dir*delta*ADVANCE_SPEED) + if (is_colliding()): + get_node("anim").play("explode") + hit=true + +func _ready(): + # Initialization here + set_fixed_process(true) + pass + + diff --git a/demos/2d/isometric_light/shoot.scn b/demos/2d/isometric_light/shoot.scn Binary files differnew file mode 100644 index 0000000000..672608810f --- /dev/null +++ b/demos/2d/isometric_light/shoot.scn diff --git a/demos/2d/isometric_light/shoot_halo.png b/demos/2d/isometric_light/shoot_halo.png Binary files differnew file mode 100644 index 0000000000..5ba954b32b --- /dev/null +++ b/demos/2d/isometric_light/shoot_halo.png diff --git a/demos/2d/isometric_light/tileset.res b/demos/2d/isometric_light/tileset.res Binary files differnew file mode 100644 index 0000000000..633bdada38 --- /dev/null +++ b/demos/2d/isometric_light/tileset.res diff --git a/demos/2d/isometric_light/tileset_scene.scn b/demos/2d/isometric_light/tileset_scene.scn Binary files differnew file mode 100644 index 0000000000..3d0773c9c5 --- /dev/null +++ b/demos/2d/isometric_light/tileset_scene.scn diff --git a/demos/2d/isometric_light/torch.scn b/demos/2d/isometric_light/torch.scn Binary files differnew file mode 100644 index 0000000000..d1cb7fe7e6 --- /dev/null +++ b/demos/2d/isometric_light/torch.scn diff --git a/demos/2d/isometric_light/torch_light.png b/demos/2d/isometric_light/torch_light.png Binary files differnew file mode 100644 index 0000000000..a98113d36f --- /dev/null +++ b/demos/2d/isometric_light/torch_light.png diff --git a/demos/2d/isometric_light/torch_shader.res b/demos/2d/isometric_light/torch_shader.res Binary files differnew file mode 100644 index 0000000000..ad70d5260d --- /dev/null +++ b/demos/2d/isometric_light/torch_shader.res diff --git a/demos/2d/isometric_light/wall_shader.res b/demos/2d/isometric_light/wall_shader.res Binary files differnew file mode 100644 index 0000000000..78c8fe57e1 --- /dev/null +++ b/demos/2d/isometric_light/wall_shader.res diff --git a/demos/2d/kinematic_char/colworld.scn b/demos/2d/kinematic_char/colworld.scn Binary files differindex b3a0a1f168..7b79a1d887 100644 --- a/demos/2d/kinematic_char/colworld.scn +++ b/demos/2d/kinematic_char/colworld.scn diff --git a/demos/2d/kinematic_char/player.gd b/demos/2d/kinematic_char/player.gd index 9cff0269e8..e8b3cc8d00 100644 --- a/demos/2d/kinematic_char/player.gd +++ b/demos/2d/kinematic_char/player.gd @@ -15,6 +15,7 @@ const GRAVITY = 500.0 #consider "floor". const FLOOR_ANGLE_TOLERANCE = 40 const WALK_FORCE = 600 +const WALK_MIN_SPEED=10 const WALK_MAX_SPEED = 200 const STOP_FORCE = 1300 const JUMP_SPEED = 200 @@ -40,12 +41,12 @@ func _fixed_process(delta): var stop=true if (walk_left): - if (velocity.x<=0 and velocity.x > -WALK_MAX_SPEED): + if (velocity.x<=WALK_MIN_SPEED and velocity.x > -WALK_MAX_SPEED): force.x-=WALK_FORCE stop=false elif (walk_right): - if (velocity.x>=0 and velocity.x < WALK_MAX_SPEED): + if (velocity.x>=-WALK_MIN_SPEED and velocity.x < WALK_MAX_SPEED): force.x+=WALK_FORCE stop=false diff --git a/demos/2d/kinematic_char/player.scn b/demos/2d/kinematic_char/player.scn Binary files differindex 126b332184..5809c0e98a 100644 --- a/demos/2d/kinematic_char/player.scn +++ b/demos/2d/kinematic_char/player.scn diff --git a/demos/2d/light_mask/burano.png b/demos/2d/light_mask/burano.png Binary files differnew file mode 100644 index 0000000000..6eec09d585 --- /dev/null +++ b/demos/2d/light_mask/burano.png diff --git a/demos/2d/light_mask/engine.cfg b/demos/2d/light_mask/engine.cfg new file mode 100644 index 0000000000..8b0ae6f61d --- /dev/null +++ b/demos/2d/light_mask/engine.cfg @@ -0,0 +1,8 @@ +[application] + +name="Using Lights As Mask" +main_scene="res://lightmask.scn" + +[rasterizer] + +shadow_filter=3 diff --git a/demos/2d/light_mask/lightmask.scn b/demos/2d/light_mask/lightmask.scn Binary files differnew file mode 100644 index 0000000000..08805f44c6 --- /dev/null +++ b/demos/2d/light_mask/lightmask.scn diff --git a/demos/2d/light_mask/splat.png b/demos/2d/light_mask/splat.png Binary files differnew file mode 100644 index 0000000000..8c35f068a0 --- /dev/null +++ b/demos/2d/light_mask/splat.png diff --git a/demos/2d/lights_shadows/bg.png b/demos/2d/lights_shadows/bg.png Binary files differnew file mode 100644 index 0000000000..4a3376f484 --- /dev/null +++ b/demos/2d/lights_shadows/bg.png diff --git a/demos/2d/lights_shadows/caster.png b/demos/2d/lights_shadows/caster.png Binary files differnew file mode 100644 index 0000000000..bf53a4565b --- /dev/null +++ b/demos/2d/lights_shadows/caster.png diff --git a/demos/2d/lights_shadows/engine.cfg b/demos/2d/lights_shadows/engine.cfg new file mode 100644 index 0000000000..bb9d1ef256 --- /dev/null +++ b/demos/2d/lights_shadows/engine.cfg @@ -0,0 +1,8 @@ +[application] + +name="2D Lighting" +main_scene="res://light_shadows.scn" + +[rasterizer] + +shadow_filter=2 diff --git a/demos/2d/lights_shadows/light.png b/demos/2d/lights_shadows/light.png Binary files differnew file mode 100644 index 0000000000..936860de52 --- /dev/null +++ b/demos/2d/lights_shadows/light.png diff --git a/demos/2d/lights_shadows/light_shadows.scn b/demos/2d/lights_shadows/light_shadows.scn Binary files differnew file mode 100644 index 0000000000..a13e31376e --- /dev/null +++ b/demos/2d/lights_shadows/light_shadows.scn diff --git a/demos/2d/lights_shadows/spot.png b/demos/2d/lights_shadows/spot.png Binary files differnew file mode 100644 index 0000000000..9ab2d34963 --- /dev/null +++ b/demos/2d/lights_shadows/spot.png diff --git a/demos/2d/navpoly/agent.png b/demos/2d/navpoly/agent.png Binary files differnew file mode 100644 index 0000000000..23e396c478 --- /dev/null +++ b/demos/2d/navpoly/agent.png diff --git a/demos/2d/navpoly/engine.cfg b/demos/2d/navpoly/engine.cfg new file mode 100644 index 0000000000..51eefd7b77 --- /dev/null +++ b/demos/2d/navpoly/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="Navigation Polygon (2D)" +main_scene="res://navigation.scn" diff --git a/demos/2d/navpoly/navigation.gd b/demos/2d/navpoly/navigation.gd new file mode 100644 index 0000000000..9c3dc2921d --- /dev/null +++ b/demos/2d/navpoly/navigation.gd @@ -0,0 +1,63 @@ + +extends Navigation2D + +# member variables here, example: +# var a=2 +# var b="textvar" +var begin=Vector2() +var end=Vector2() +var path=[] + +const SPEED=200.0 + +func _process(delta): + + + if (path.size()>1): + + var to_walk = delta*SPEED + while(to_walk>0 and path.size()>=2): + var pfrom = path[path.size()-1] + var pto = path[path.size()-2] + var d = pfrom.distance_to(pto) + if (d<=to_walk): + path.remove(path.size()-1) + to_walk-=d + else: + path[path.size()-1] = pfrom.linear_interpolate(pto,to_walk/d) + to_walk=0 + + var atpos = path[path.size()-1] + get_node("agent").set_pos(atpos) + + if (path.size()<2): + path=[] + set_process(false) + + else: + set_process(false) + + + +func _update_path(): + + var p = get_simple_path(begin,end,true) + path=Array(p) # Vector2array to complex to use, convert to regular array + path.invert() + + set_process(true) + + +func _input(ev): + if (ev.type==InputEvent.MOUSE_BUTTON and ev.pressed and ev.button_index==1): + begin=get_node("agent").get_pos() + #mouse to local navigatio cooards + end=ev.pos - get_pos() + _update_path() + +func _ready(): + # Initialization here + set_process_input(true) + pass + + diff --git a/demos/2d/navpoly/navigation.scn b/demos/2d/navpoly/navigation.scn Binary files differnew file mode 100644 index 0000000000..1bb7de391b --- /dev/null +++ b/demos/2d/navpoly/navigation.scn diff --git a/demos/2d/navpoly/navigation2.scn b/demos/2d/navpoly/navigation2.scn Binary files differnew file mode 100644 index 0000000000..224aed73f5 --- /dev/null +++ b/demos/2d/navpoly/navigation2.scn diff --git a/demos/2d/navpoly/path.png b/demos/2d/navpoly/path.png Binary files differnew file mode 100644 index 0000000000..52a6d507c3 --- /dev/null +++ b/demos/2d/navpoly/path.png diff --git a/demos/2d/normalmaps/diffuse.jpg b/demos/2d/normalmaps/diffuse.jpg Binary files differnew file mode 100644 index 0000000000..87bc9cf158 --- /dev/null +++ b/demos/2d/normalmaps/diffuse.jpg diff --git a/demos/2d/normalmaps/diffuse.png b/demos/2d/normalmaps/diffuse.png Binary files differnew file mode 100644 index 0000000000..634d955f8d --- /dev/null +++ b/demos/2d/normalmaps/diffuse.png diff --git a/demos/2d/normalmaps/engine.cfg b/demos/2d/normalmaps/engine.cfg new file mode 100644 index 0000000000..3fc2048716 --- /dev/null +++ b/demos/2d/normalmaps/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="2D Normal Mapping" +main_scene="res://normalmap.scn" diff --git a/demos/2d/normalmaps/light.png b/demos/2d/normalmaps/light.png Binary files differnew file mode 100644 index 0000000000..9568298086 --- /dev/null +++ b/demos/2d/normalmaps/light.png diff --git a/demos/2d/normalmaps/normal.png b/demos/2d/normalmaps/normal.png Binary files differnew file mode 100644 index 0000000000..d5b3d53a24 --- /dev/null +++ b/demos/2d/normalmaps/normal.png diff --git a/demos/2d/normalmaps/normal_material.res b/demos/2d/normalmaps/normal_material.res Binary files differnew file mode 100644 index 0000000000..34129cccdc --- /dev/null +++ b/demos/2d/normalmaps/normal_material.res diff --git a/demos/2d/normalmaps/normalmap.scn b/demos/2d/normalmaps/normalmap.scn Binary files differnew file mode 100644 index 0000000000..ab737e83f3 --- /dev/null +++ b/demos/2d/normalmaps/normalmap.scn diff --git a/demos/2d/platformer/player.gd b/demos/2d/platformer/player.gd index 481f340ab8..b08105212c 100644 --- a/demos/2d/platformer/player.gd +++ b/demos/2d/platformer/player.gd @@ -53,12 +53,15 @@ var enemy func _integrate_forces(s): + + var lv = s.get_linear_velocity() var step = s.get_step() var new_anim=anim var new_siding_left=siding_left + # Get the controls var move_left = Input.is_action_pressed("move_left") var move_right = Input.is_action_pressed("move_right") diff --git a/demos/2d/platformer/player.xml b/demos/2d/platformer/player.xml index c129d01f0d..196881dee4 100644 --- a/demos/2d/platformer/player.xml +++ b/demos/2d/platformer/player.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> -<resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.3917-beta1"> +<resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.rc2.custom_build"> <ext_resource path="res://osb_jump.png" type="Texture"></ext_resource> <ext_resource path="res://bullet.png" type="Texture"></ext_resource> <ext_resource path="res://osb_right.png" type="Texture"></ext_resource> <ext_resource path="res://sound_coin.wav" type="Sample"></ext_resource> - <ext_resource path="res://sound_shoot.wav" type="Sample"></ext_resource> <ext_resource path="res://osb_fire.png" type="Texture"></ext_resource> - <ext_resource path="res://robot_demo.png" type="Texture"></ext_resource> + <ext_resource path="res://sound_shoot.wav" type="Sample"></ext_resource> <ext_resource path="res://osb_left.png" type="Texture"></ext_resource> + <ext_resource path="res://robot_demo.png" type="Texture"></ext_resource> <ext_resource path="res://player.gd" type="Script"></ext_resource> <ext_resource path="res://sound_jump.wav" type="Sample"></ext_resource> <resource type="RayShape2D" path="local://1"> @@ -50,8 +50,8 @@ </resource> <resource type="Animation" path="local://4"> - <string name="resource/name"> "run" </string> - <real name="length"> 1.25 </real> + <string name="resource/name"> "jumping" </string> + <real name="length"> 0.5 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> <string name="tracks/0/type"> "value" </string> @@ -61,24 +61,21 @@ <string> "cont" </string> <bool> False </bool> <string> "transitions" </string> - <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array> + <real_array len="3"> 1, 1, 1 </real_array> <string> "values" </string> - <array len="6" shared="false"> - <int> 0 </int> - <int> 1 </int> - <int> 2 </int> - <int> 3 </int> - <int> 4 </int> - <int> 0 </int> + <array len="3" shared="false"> + <int> 23 </int> + <int> 24 </int> + <int> 23 </int> </array> <string> "times" </string> - <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array> + <real_array len="3"> 0, 0.25, 0.5 </real_array> </dictionary> </resource> <resource type="Animation" path="local://5"> - <string name="resource/name"> "run_gun_fire" </string> - <real name="length"> 1.25 </real> + <string name="resource/name"> "idle_weapon" </string> + <real name="length"> 0.5 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> <string name="tracks/0/type"> "value" </string> @@ -88,24 +85,18 @@ <string> "cont" </string> <bool> False </bool> <string> "transitions" </string> - <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array> + <real_array len="1"> 1 </real_array> <string> "values" </string> - <array len="6" shared="false"> - <int> 10 </int> - <int> 11 </int> - <int> 12 </int> - <int> 13 </int> - <int> 14 </int> - <int> 5 </int> + <array len="1" shared="false"> + <int> 25 </int> </array> <string> "times" </string> - <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array> + <real_array len="1"> 0 </real_array> </dictionary> </resource> <resource type="Animation" path="local://6"> - <string name="resource/name"> "jumping_weapon" </string> - <real name="length"> 0.5 </real> + <real name="length"> 1.25 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> <string name="tracks/0/type"> "value" </string> @@ -115,13 +106,18 @@ <string> "cont" </string> <bool> False </bool> <string> "transitions" </string> - <real_array len="1"> 1 </real_array> + <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array> <string> "values" </string> - <array len="1" shared="false"> - <int> 26 </int> + <array len="6" shared="false"> + <int> 0 </int> + <int> 1 </int> + <int> 2 </int> + <int> 3 </int> + <int> 4 </int> + <int> 0 </int> </array> <string> "times" </string> - <real_array len="1"> 0 </real_array> + <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array> </dictionary> </resource> @@ -148,8 +144,8 @@ </resource> <resource type="Animation" path="local://8"> - <string name="resource/name"> "jumping" </string> - <real name="length"> 0.5 </real> + <string name="resource/name"> "falling" </string> + <real name="length"> 0.01 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> <string name="tracks/0/type"> "value" </string> @@ -159,20 +155,17 @@ <string> "cont" </string> <bool> False </bool> <string> "transitions" </string> - <real_array len="3"> 1, 1, 1 </real_array> + <real_array len="1"> 1 </real_array> <string> "values" </string> - <array len="3" shared="false"> - <int> 23 </int> - <int> 24 </int> - <int> 23 </int> + <array len="1" shared="false"> + <int> 21 </int> </array> <string> "times" </string> - <real_array len="3"> 0, 0.25, 0.5 </real_array> + <real_array len="1"> 0 </real_array> </dictionary> </resource> <resource type="Animation" path="local://9"> - <string name="resource/name"> "run_weapon" </string> <real name="length"> 1.25 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> @@ -186,11 +179,11 @@ <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array> <string> "values" </string> <array len="6" shared="false"> - <int> 5 </int> - <int> 6 </int> - <int> 7 </int> - <int> 8 </int> - <int> 9 </int> + <int> 10 </int> + <int> 11 </int> + <int> 12 </int> + <int> 13 </int> + <int> 14 </int> <int> 5 </int> </array> <string> "times" </string> @@ -199,7 +192,7 @@ </resource> <resource type="Animation" path="local://10"> - <string name="resource/name"> "idle_weapon" </string> + <string name="resource/name"> "falling_weapon" </string> <real name="length"> 0.5 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> @@ -213,7 +206,7 @@ <real_array len="1"> 1 </real_array> <string> "values" </string> <array len="1" shared="false"> - <int> 25 </int> + <int> 26 </int> </array> <string> "times" </string> <real_array len="1"> 0 </real_array> @@ -221,8 +214,7 @@ </resource> <resource type="Animation" path="local://11"> - <string name="resource/name"> "falling_weapon" </string> - <real name="length"> 0.5 </real> + <real name="length"> 1.25 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> <string name="tracks/0/type"> "value" </string> @@ -232,19 +224,23 @@ <string> "cont" </string> <bool> False </bool> <string> "transitions" </string> - <real_array len="1"> 1 </real_array> + <real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array> <string> "values" </string> - <array len="1" shared="false"> - <int> 26 </int> + <array len="6" shared="false"> + <int> 5 </int> + <int> 6 </int> + <int> 7 </int> + <int> 8 </int> + <int> 9 </int> + <int> 5 </int> </array> <string> "times" </string> - <real_array len="1"> 0 </real_array> + <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array> </dictionary> </resource> <resource type="Animation" path="local://12"> - <string name="resource/name"> "falling" </string> - <real name="length"> 0.01 </real> + <real name="length"> 0.5 </real> <bool name="loop"> True </bool> <real name="step"> 0.25 </real> <string name="tracks/0/type"> "value" </string> @@ -257,7 +253,7 @@ <real_array len="1"> 1 </real_array> <string> "values" </string> <array len="1" shared="false"> - <int> 21 </int> + <int> 26 </int> </array> <string> "times" </string> <real_array len="1"> 0 </real_array> @@ -294,9 +290,10 @@ <main_resource> <dictionary name="_bundled" shared="false"> <string> "names" </string> - <string_array len="170"> + <string_array len="180"> <string> "player" </string> <string> "RigidBody2D" </string> + <string> "_import_path" </string> <string> "visibility/visible" </string> <string> "visibility/opacity" </string> <string> "visibility/self_opacity" </string> @@ -311,6 +308,7 @@ <string> "shapes/1/shape" </string> <string> "shapes/1/transform" </string> <string> "shapes/1/trigger" </string> + <string> "layers" </string> <string> "mode" </string> <string> "mass" </string> <string> "friction" </string> @@ -319,7 +317,7 @@ <string> "continuous_cd" </string> <string> "contacts_reported" </string> <string> "contact_monitor" </string> - <string> "active" </string> + <string> "sleeping" </string> <string> "can_sleep" </string> <string> "velocity/linear" </string> <string> "velocity/angular" </string> @@ -354,6 +352,8 @@ <string> "config/flip_h" </string> <string> "config/flip_v" </string> <string> "config/texture" </string> + <string> "config/h_frames" </string> + <string> "config/v_frames" </string> <string> "params/direction" </string> <string> "params/spread" </string> <string> "params/linear_velocity" </string> @@ -364,9 +364,12 @@ <string> "params/radial_accel" </string> <string> "params/tangential_accel" </string> <string> "params/damping" </string> + <string> "params/initial_angle" </string> <string> "params/initial_size" </string> <string> "params/final_size" </string> <string> "params/hue_variation" </string> + <string> "params/anim_speed_scale" </string> + <string> "params/anim_initial_pos" </string> <string> "randomness/direction" </string> <string> "randomness/spread" </string> <string> "randomness/linear_velocity" </string> @@ -377,9 +380,12 @@ <string> "randomness/radial_accel" </string> <string> "randomness/tangential_accel" </string> <string> "randomness/damping" </string> + <string> "randomness/initial_angle" </string> <string> "randomness/initial_size" </string> <string> "randomness/final_size" </string> <string> "randomness/hue_variation" </string> + <string> "randomness/anim_speed_scale" </string> + <string> "randomness/anim_initial_pos" </string> <string> "color_phases/count" </string> <string> "phase_0/pos" </string> <string> "phase_0/color" </string> @@ -396,15 +402,15 @@ <string> "playback/default_blend_time" </string> <string> "root/root" </string> <string> "anims/idle" </string> - <string> "anims/run" </string> - <string> "anims/standing_weapon_ready" </string> - <string> "anims/jumping_weapon" </string> - <string> "anims/crouch" </string> <string> "anims/jumping" </string> - <string> "anims/run_weapon" </string> <string> "anims/idle_weapon" </string> - <string> "anims/falling_weapon" </string> + <string> "anims/run" </string> + <string> "anims/crouch" </string> <string> "anims/falling" </string> + <string> "anims/standing_weapon_ready" </string> + <string> "anims/falling_weapon" </string> + <string> "anims/run_weapon" </string> + <string> "anims/jumping_weapon" </string> <string> "playback/active" </string> <string> "playback/speed" </string> <string> "blend_times" </string> @@ -473,7 +479,8 @@ <string> "node_count" </string> <int> 14 </int> <string> "variants" </string> - <array len="71" shared="false"> + <array len="72" shared="false"> + <node_path> "" </node_path> <bool> True </bool> <real> 1 </real> <bool> False </bool> @@ -485,6 +492,7 @@ <matrix32> 1, -0, 0, 1.76469, 0.291992, -12.1587 </matrix32> <resource resource_type="Shape2D" path="local://2"> </resource> <matrix32> 1, -0, 0, 1, 0, 0 </matrix32> + <int> 1 </int> <real> 3 </real> <int> 0 </int> <int> 3 </int> @@ -507,11 +515,17 @@ <bool> False </bool> <string> "zoom" </string> <real> 2.272073 </real> + <string> "use_snap" </string> + <bool> False </bool> <string> "ofs" </string> <vector2> -181.946, -86.2812 </vector2> + <string> "snap" </string> + <int> 10 </int> </dictionary> <string> "3D" </string> <dictionary shared="false"> + <string> "deflight_rot_y" </string> + <real> 0.628319 </real> <string> "zfar" </string> <real> 500 </real> <string> "fov" </string> @@ -525,10 +539,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> + <string> "listener" </string> + <bool> True </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -539,10 +555,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -553,10 +571,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -567,10 +587,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -579,12 +601,18 @@ <int> 1 </int> <string> "default_light" </string> <bool> True </bool> + <string> "ambient_light_color" </string> + <color> 0.15, 0.15, 0.15, 1 </color> <string> "show_grid" </string> <bool> True </bool> <string> "show_origin" </string> <bool> True </bool> <string> "znear" </string> <real> 0.1 </real> + <string> "default_srgb" </string> + <bool> False </bool> + <string> "deflight_rot_x" </string> + <real> 0.942478 </real> </dictionary> </dictionary> <string> "__editor_run_settings__" </string> @@ -595,14 +623,13 @@ <int> 0 </int> </dictionary> <string> "__editor_plugin_screen__" </string> - <string> "3D" </string> + <string> "Script" </string> </dictionary> <resource resource_type="Texture" path="res://robot_demo.png"> </resource> <int> 16 </int> <color> 1, 1, 1, 1 </color> <rect2> 0, 0, 0, 0 </rect2> <real> 0.363636 </real> - <int> 1 </int> <vector2> 20.7312, 3.21187 </vector2> <real> 83.450417 </real> <int> 4 </int> @@ -654,7 +681,7 @@ <string> "shoot" </string> </array> <string> "nodes" </string> - <int_array len="572"> -1, -1, 1, 0, -1, 28, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 2, 13, 9, 14, 10, 15, 2, 16, 6, 17, 11, 18, 4, 19, 4, 20, 0, 21, 12, 22, 13, 23, 2, 24, 0, 25, 0, 26, 3, 27, 4, 28, 14, 29, 15, 0, 0, 0, 31, 30, -1, 18, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 32, 16, 33, 0, 34, 3, 35, 2, 36, 2, 37, 6, 38, 17, 39, 12, 40, 18, 41, 2, 42, 19, 0, 1, 0, 44, 43, -1, 57, 2, 0, 3, 1, 4, 20, 5, 2, 45, 21, 6, 22, 7, 23, 8, 5, 46, 24, 47, 25, 48, 1, 49, 4, 50, 25, 51, 2, 52, 3, 53, 3, 54, 2, 55, 26, 56, 2, 57, 2, 58, 27, 59, 4, 60, 28, 61, 29, 62, 1, 63, 4, 64, 4, 65, 30, 66, 4, 67, 4, 68, 4, 69, 31, 70, 31, 71, 4, 72, 4, 73, 4, 74, 4, 75, 31, 76, 4, 77, 4, 78, 4, 79, 4, 80, 4, 81, 4, 82, 4, 83, 4, 84, 4, 85, 6, 86, 4, 87, 18, 88, 1, 89, 32, 90, 1, 91, 33, 92, 1, 93, 34, 94, 35, 0, 0, 0, 96, 95, -1, 17, 97, 21, 98, 4, 99, 36, 100, 37, 101, 38, 102, 39, 103, 40, 104, 41, 105, 42, 106, 43, 107, 44, 108, 45, 109, 46, 110, 0, 111, 31, 112, 47, 113, 48, 0, 0, 0, 115, 114, -1, 22, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 33, 0, 116, 2, 117, 0, 118, 4, 119, 5, 120, 12, 121, 12, 122, 49, 123, 49, 124, 0, 125, 0, 126, 50, 127, 50, 128, 50, 129, 50, 0, 0, 0, 131, 130, -1, 7, 2, 0, 3, 1, 4, 1, 5, 2, 6, 51, 7, 4, 8, 5, 0, 0, 0, 132, 132, -1, 9, 2, 0, 3, 1, 4, 1, 5, 2, 6, 52, 7, 4, 8, 53, 133, 7, 134, 2, 0, 0, 0, 136, 135, -1, 14, 137, 13, 138, 54, 139, 4, 140, 1, 141, 4, 142, 4, 143, 4, 144, 55, 145, 55, 146, 55, 147, 55, 148, 6, 149, 4, 150, 4, 0, 0, 0, 151, 151, -1, 9, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 152, 12, 153, 56, 0, 0, 0, 155, 154, -1, 4, 156, 12, 34, 3, 157, 4, 158, 5, 0, 9, 0, 160, 159, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 57, 7, 4, 8, 58, 161, 59, 162, 60, 163, 60, 164, 0, 165, 61, 166, 21, 0, 9, 0, 160, 167, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 62, 7, 4, 8, 58, 161, 63, 162, 60, 163, 60, 164, 0, 165, 64, 166, 21, 0, 9, 0, 160, 168, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 65, 7, 4, 8, 58, 161, 66, 162, 60, 163, 60, 164, 2, 165, 67, 166, 21, 0, 9, 0, 160, 169, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 68, 7, 4, 8, 58, 161, 69, 162, 60, 163, 60, 164, 2, 165, 70, 166, 21, 0 </int_array> + <int_array len="618"> -1, -1, 1, 0, -1, 30, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 9, 13, 3, 14, 10, 15, 11, 16, 3, 17, 12, 18, 7, 19, 13, 20, 5, 21, 5, 22, 1, 23, 14, 24, 15, 25, 3, 26, 3, 27, 1, 28, 4, 29, 5, 30, 16, 31, 17, 0, 0, 0, 33, 32, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 34, 18, 35, 1, 36, 4, 37, 3, 38, 3, 39, 7, 40, 19, 41, 14, 42, 20, 43, 3, 44, 21, 0, 1, 0, 46, 45, -1, 66, 2, 0, 3, 1, 4, 2, 5, 22, 6, 3, 47, 12, 7, 23, 8, 24, 9, 6, 48, 25, 49, 26, 50, 2, 51, 5, 52, 26, 53, 3, 54, 4, 55, 4, 56, 3, 57, 27, 58, 3, 59, 3, 60, 28, 61, 12, 62, 12, 63, 5, 64, 29, 65, 30, 66, 2, 67, 5, 68, 5, 69, 31, 70, 5, 71, 5, 72, 5, 73, 5, 74, 32, 75, 32, 76, 5, 77, 2, 78, 5, 79, 5, 80, 5, 81, 5, 82, 32, 83, 5, 84, 5, 85, 5, 86, 5, 87, 5, 88, 5, 89, 5, 90, 5, 91, 5, 92, 5, 93, 5, 94, 5, 95, 7, 96, 5, 97, 20, 98, 2, 99, 33, 100, 2, 101, 34, 102, 2, 103, 35, 104, 36, 0, 0, 0, 106, 105, -1, 18, 2, 0, 107, 12, 108, 5, 109, 37, 110, 38, 111, 39, 112, 40, 113, 41, 114, 42, 115, 43, 116, 44, 117, 45, 118, 46, 119, 47, 120, 1, 121, 32, 122, 48, 123, 49, 0, 0, 0, 125, 124, -1, 23, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 35, 1, 126, 3, 127, 1, 128, 5, 129, 6, 130, 14, 131, 14, 132, 50, 133, 50, 134, 1, 135, 1, 136, 51, 137, 51, 138, 51, 139, 51, 0, 0, 0, 141, 140, -1, 8, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 52, 8, 5, 9, 6, 0, 0, 0, 142, 142, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 53, 8, 5, 9, 54, 143, 8, 144, 3, 0, 0, 0, 146, 145, -1, 15, 2, 0, 147, 15, 148, 55, 149, 5, 150, 2, 151, 5, 152, 5, 153, 5, 154, 56, 155, 56, 156, 56, 157, 56, 158, 7, 159, 5, 160, 5, 0, 0, 0, 161, 161, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 162, 14, 163, 57, 0, 0, 0, 165, 164, -1, 5, 2, 0, 166, 14, 36, 4, 167, 5, 168, 6, 0, 9, 0, 170, 169, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 58, 8, 5, 9, 59, 171, 60, 172, 61, 173, 61, 174, 1, 175, 62, 176, 12, 0, 9, 0, 170, 177, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 63, 8, 5, 9, 59, 171, 64, 172, 61, 173, 61, 174, 1, 175, 65, 176, 12, 0, 9, 0, 170, 178, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 66, 8, 5, 9, 59, 171, 67, 172, 61, 173, 61, 174, 3, 175, 68, 176, 12, 0, 9, 0, 170, 179, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 69, 8, 5, 9, 59, 171, 70, 172, 61, 173, 61, 174, 3, 175, 71, 176, 12, 0 </int_array> <string> "conns" </string> <int_array len="0"> </int_array> </dictionary> diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml index 78d0f9ae2c..610057183b 100644 --- a/demos/2d/platformer/stage.xml +++ b/demos/2d/platformer/stage.xml @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<resource_file type="PackedScene" subresource_count="9" version="1.0" version_name="Godot Engine v1.0.3917-beta1"> - <ext_resource path="res://tileset.xml" type="TileSet"></ext_resource> +<resource_file type="PackedScene" subresource_count="9" version="1.0" version_name="Godot Engine v1.0.stable.custom_build"> <ext_resource path="res://music.ogg" type="AudioStream"></ext_resource> - <ext_resource path="res://coin.xml" type="PackedScene"></ext_resource> + <ext_resource path="res://tileset.xml" type="TileSet"></ext_resource> + <ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource> <ext_resource path="res://player.xml" type="PackedScene"></ext_resource> - <ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource> <ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource> + <ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource> + <ext_resource path="res://coin.xml" type="PackedScene"></ext_resource> <ext_resource path="res://enemy.xml" type="PackedScene"></ext_resource> - <ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource> <main_resource> <dictionary name="_bundled" shared="false"> <string> "names" </string> - <string_array len="122"> + <string_array len="130"> <string> "stage" </string> <string> "Node" </string> <string> "_import_path" </string> @@ -21,17 +21,25 @@ <string> "visibility/visible" </string> <string> "visibility/opacity" </string> <string> "visibility/self_opacity" </string> - <string> "visibility/behind_parent" </string> + <string> "visibility/light_mask" </string> <string> "transform/pos" </string> <string> "transform/rot" </string> <string> "transform/scale" </string> - <string> "cell_size" </string> - <string> "quadrant_size" </string> + <string> "z/z" </string> + <string> "z/relative" </string> + <string> "mode" </string> <string> "tile_set" </string> - <string> "tile_data" </string> + <string> "cell/size" </string> + <string> "cell/quadrant_size" </string> + <string> "cell/custom_transform" </string> + <string> "cell/half_offset" </string> + <string> "cell/tile_origin" </string> + <string> "cell/y_sort" </string> + <string> "collision/use_kinematic" </string> <string> "collision/friction" </string> <string> "collision/bounce" </string> <string> "collision/layers" </string> + <string> "tile_data" </string> <string> "coins" </string> <string> "coin" </string> <string> "Area2D" </string> @@ -142,7 +150,7 @@ <string> "node_count" </string> <int> 66 </int> <string> "variants" </string> - <array len="96" shared="false"> + <array len="103" shared="false"> <node_path> "" </node_path> <dictionary shared="false"> <string> "__editor_plugin_states__" </string> @@ -164,16 +172,18 @@ <string> "pixel_snap" </string> <bool> False </bool> <string> "zoom" </string> - <real> 0.54036 </real> + <real> 0.814506 </real> <string> "use_snap" </string> <bool> False </bool> + <string> "snap_vec" </string> + <vector2> 10, 10 </vector2> <string> "ofs" </string> - <vector2> -177.089, 415.221 </vector2> - <string> "snap" </string> - <int> 10 </int> + <vector2> 177.488, 709.633 </vector2> </dictionary> <string> "3D" </string> <dictionary shared="false"> + <string> "deflight_rot_y" </string> + <real> 0.628319 </real> <string> "zfar" </string> <real> 500 </real> <string> "fov" </string> @@ -187,10 +197,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> + <string> "listener" </string> + <bool> True </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -201,10 +213,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -215,10 +229,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -229,10 +245,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -241,12 +259,18 @@ <int> 1 </int> <string> "default_light" </string> <bool> True </bool> + <string> "ambient_light_color" </string> + <color> 0.15, 0.15, 0.15, 1 </color> <string> "show_grid" </string> <bool> True </bool> <string> "show_origin" </string> <bool> True </bool> <string> "znear" </string> <real> 0.1 </real> + <string> "default_srgb" </string> + <bool> False </bool> + <string> "deflight_rot_x" </string> + <real> 0.942478 </real> </dictionary> </dictionary> <string> "__editor_run_settings__" </string> @@ -257,19 +281,22 @@ <int> 0 </int> </dictionary> <string> "__editor_plugin_screen__" </string> - <string> "2D" </string> + <string> "3D" </string> </dictionary> <bool> True </bool> <real> 1 </real> - <bool> False </bool> + <int> 1 </int> <vector2> 0, 0 </vector2> <real> 0 </real> <vector2> 1, 1 </vector2> - <int> 64 </int> - <int> 16 </int> + <int> 0 </int> <resource resource_type="TileSet" path="res://tileset.xml"> </resource> - <int_array len="1998"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870925, 1048587, 13, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179663, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 536870918, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array> - <int> 1 </int> + <vector2> 64, 64 </vector2> + <int> 8 </int> + <matrix32> 1, 0, 0, 1, 0, 0 </matrix32> + <int> 2 </int> + <bool> False </bool> + <int_array len="1998"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870925, 1048587, 13, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179663, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 0, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array> <dictionary shared="false"> <string> "_edit_lock_" </string> <bool> True </bool> @@ -280,6 +307,116 @@ </dictionary> <resource resource_type="PackedScene" path="res://coin.xml"> </resource> <vector2> 672, 1120 </vector2> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 2 </int> + <string> "sources" </string> + <array len="3" shared="false"> + <string> "res://enemy.gd" </string> + <string> "res://player.gd" </string> + <string> "res://coin.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "pixel_snap" </string> + <bool> False </bool> + <string> "zoom" </string> + <real> 3.794776 </real> + <string> "ofs" </string> + <vector2> -34.3697, -21.6562 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 45 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "2D" </string> + </dictionary> <vector2> 704, 1120 </vector2> <vector2> 736, 1120 </vector2> <vector2> 1120, 992 </vector2> @@ -323,8 +460,247 @@ <vector2> 4172.75, 541.058 </vector2> <resource resource_type="PackedScene" path="res://player.xml"> </resource> <vector2> 251.684, 1045.6 </vector2> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 0 </int> + <string> "sources" </string> + <array len="1" shared="false"> + <string> "res://player.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "pixel_snap" </string> + <bool> False </bool> + <string> "zoom" </string> + <real> 2.272073 </real> + <string> "use_snap" </string> + <bool> False </bool> + <string> "ofs" </string> + <vector2> -181.946, -86.2812 </vector2> + <string> "snap" </string> + <int> 10 </int> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 45 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "listener" </string> + <bool> True </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "listener" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "listener" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "listener" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "deflight_rot_y" </string> + <real> 0.628319 </real> + <string> "default_light" </string> + <bool> True </bool> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "ambient_light_color" </string> + <color> 0.15, 0.15, 0.15, 1 </color> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + <string> "deflight_rot_x" </string> + <real> 0.942478 </real> + <string> "default_srgb" </string> + <bool> False </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "Script" </string> + </dictionary> <resource resource_type="PackedScene" path="res://moving_platform.xml"> </resource> <vector2> 1451.86, 742.969 </vector2> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 0 </int> + <string> "sources" </string> + <array len="4" shared="false"> + <string> "res://moving_platform.gd" </string> + <string> "res://enemy.gd" </string> + <string> "res://player.gd" </string> + <string> "res://coin.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "pixel_snap" </string> + <bool> False </bool> + <string> "zoom" </string> + <real> 1.360373 </real> + <string> "ofs" </string> + <vector2> -210.652, -172.81 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 400 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "2D" </string> + </dictionary> <vector2> 0, 140 </vector2> <real> 5 </real> <vector2> 624.824, 545.544 </vector2> @@ -334,10 +710,217 @@ <vector2> 450, 0 </vector2> <resource resource_type="PackedScene" path="res://seesaw.xml"> </resource> <vector2> 2402.79, 849.52 </vector2> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "2D" </string> + <dictionary shared="false"> + <string> "pixel_snap" </string> + <bool> False </bool> + <string> "zoom" </string> + <real> 2.050547 </real> + <string> "ofs" </string> + <vector2> -116.979, -109.897 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 400 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "2D" </string> + </dictionary> <resource resource_type="AudioStream" path="res://music.ogg"> </resource> <real> 2 </real> <resource resource_type="PackedScene" path="res://enemy.xml"> </resource> <vector2> 834.664, 1309.6 </vector2> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 0 </int> + <string> "sources" </string> + <array len="1" shared="false"> + <string> "res://enemy.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "pixel_snap" </string> + <bool> False </bool> + <string> "zoom" </string> + <real> 1.108033 </real> + <string> "ofs" </string> + <vector2> -227.625, -197.9 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 45 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "2D" </string> + </dictionary> <vector2> 707.665, 1225.05 </vector2> <vector2> 1125.21, 1053.06 </vector2> <vector2> 1292.11, 1059.24 </vector2> @@ -349,19 +932,78 @@ <vector2> 3546.2, 1356.19 </vector2> <vector2> 2406.63, 815.115 </vector2> <resource resource_type="PackedScene" path="res://parallax_bg.xml"> </resource> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 0 </int> + <string> "sources" </string> + <array len="4" shared="false"> + <string> "res://moving_platform.gd" </string> + <string> "res://enemy.gd" </string> + <string> "res://player.gd" </string> + <string> "res://coin.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "zoom" </string> + <real> 1 </real> + <string> "ofs" </string> + <vector2> -5, -25 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "zfar" </string> + <real> 500 </real> + <string> "fov" </string> + <real> 45 </real> + <string> "window_mode" </string> + <int> 0 </int> + <string> "window_0" </string> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0.337 </real> + <string> "default_light" </string> + <bool> True </bool> + <string> "y_rot" </string> + <real> -0.575 </real> + <string> "show_grid" </string> + <bool> True </bool> + <string> "show_origin" </string> + <bool> True </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <string> "znear" </string> + <real> 0.1 </real> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "2D" </string> + </dictionary> <real> 12 </real> <real> -202 </real> <real> 358 </real> <real> -10 </real> - <int> 2 </int> <real> 7 </real> <real> 14.769231 </real> - <string> "This is a simple demo on how to make a platformer game with Godot.This version uses physics and the 2D physics engine for motion and collision.The demo also shows the benefits of using the scene system, where coins,enemies and the player are edited separatedly and instanced in the stage.To edit the base tiles for the tileset, open the tileset_edit.xml file and follow instructions." </string> - <int> 0 </int> + <string> "This is a simple demo on how to make a platformer game with Godot."This version uses physics and the 2D physics engine for motion and collision.""The demo also shows the benefits of using the scene system, where coins,"enemies and the player are edited separatedly and instanced in the stage.""To edit the base tiles for the tileset, open the tileset_edit.xml file and follow "instructions."" </string> <real> -1 </real> </array> <string> "nodes" </string> - <int_array len="708"> -1, -1, 1, 0, -1, 2, 2, 0, 3, 1, 0, 0, 0, 5, 4, -1, 16, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 9, 15, 10, 16, 11, 17, 3, 18, 6, 19, 12, 3, 13, 0, 0, 0, 1, 20, -1, 2, 2, 0, 3, 14, 0, 2, 0, 22, 21, 15, 1, 10, 16, 0, 2, 0, 22, 23, 15, 1, 10, 17, 0, 2, 0, 22, 24, 15, 1, 10, 18, 0, 2, 0, 22, 25, 15, 1, 10, 19, 0, 2, 0, 22, 26, 15, 1, 10, 20, 0, 2, 0, 22, 27, 15, 1, 10, 21, 0, 2, 0, 22, 28, 15, 1, 10, 22, 0, 2, 0, 22, 29, 15, 1, 10, 23, 0, 2, 0, 22, 30, 15, 1, 10, 24, 0, 2, 0, 22, 31, 15, 1, 10, 25, 0, 2, 0, 22, 32, 15, 1, 10, 26, 0, 2, 0, 22, 33, 15, 1, 10, 27, 0, 2, 0, 22, 34, 15, 1, 10, 28, 0, 2, 0, 22, 35, 15, 1, 10, 29, 0, 2, 0, 22, 36, 15, 1, 10, 30, 0, 2, 0, 22, 37, 15, 1, 10, 31, 0, 2, 0, 22, 38, 15, 1, 10, 32, 0, 2, 0, 22, 39, 15, 1, 10, 33, 0, 2, 0, 22, 40, 15, 1, 10, 34, 0, 2, 0, 22, 41, 15, 1, 10, 35, 0, 2, 0, 22, 42, 15, 1, 10, 36, 0, 2, 0, 22, 43, 15, 1, 10, 37, 0, 2, 0, 22, 44, 15, 1, 10, 38, 0, 2, 0, 22, 45, 15, 1, 10, 39, 0, 2, 0, 22, 46, 15, 1, 10, 40, 0, 2, 0, 22, 47, 15, 1, 10, 41, 0, 2, 0, 22, 48, 15, 1, 10, 42, 0, 2, 0, 22, 49, 15, 1, 10, 43, 0, 2, 0, 22, 50, 15, 1, 10, 44, 0, 2, 0, 22, 51, 15, 1, 10, 45, 0, 2, 0, 22, 52, 15, 1, 10, 46, 0, 2, 0, 22, 53, 15, 1, 10, 47, 0, 2, 0, 22, 54, 15, 1, 10, 48, 0, 2, 0, 22, 55, 15, 1, 10, 49, 0, 2, 0, 22, 56, 15, 1, 10, 50, 0, 2, 0, 22, 57, 15, 1, 10, 51, 0, 2, 0, 22, 58, 15, 1, 10, 52, 0, 2, 0, 22, 59, 15, 1, 10, 53, 0, 2, 0, 22, 60, 15, 1, 10, 54, 0, 2, 0, 22, 61, 15, 1, 10, 55, 0, 2, 0, 22, 62, 15, 1, 10, 56, 0, 2, 0, 22, 63, 15, 1, 10, 57, 0, 0, 0, 65, 64, 58, 1, 10, 59, 0, 0, 0, 1, 66, -1, 1, 2, 0, 0, 46, 0, 68, 67, 60, 3, 10, 61, 69, 62, 70, 63, 0, 46, 0, 68, 71, 60, 3, 10, 64, 69, 65, 70, 66, 0, 46, 0, 68, 72, 60, 3, 10, 67, 69, 68, 70, 66, 0, 46, 0, 68, 73, 69, 1, 10, 70, 0, 0, 0, 75, 74, -1, 7, 2, 0, 76, 71, 77, 4, 78, 2, 79, 72, 80, 2, 81, 4, 0, 0, 0, 1, 82, -1, 1, 2, 0, 0, 52, 0, 65, 83, 73, 1, 10, 74, 0, 52, 0, 65, 84, 73, 1, 10, 75, 0, 52, 0, 65, 85, 73, 1, 10, 76, 0, 52, 0, 65, 86, 73, 1, 10, 77, 0, 52, 0, 65, 87, 73, 1, 10, 78, 0, 52, 0, 65, 88, 73, 1, 10, 79, 0, 52, 0, 65, 89, 73, 1, 10, 80, 0, 52, 0, 65, 90, 73, 1, 10, 81, 0, 52, 0, 65, 91, 73, 1, 10, 82, 0, 52, 0, 65, 92, 73, 1, 10, 83, 0, 52, 0, 65, 93, 73, 1, 10, 84, 0, 0, 0, 95, 94, 85, 0, 0, 0, 0, 96, 96, -1, 30, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 97, 86, 98, 87, 99, 88, 100, 89, 101, 0, 102, 0, 103, 0, 104, 0, 105, 2, 106, 2, 107, 90, 108, 3, 109, 6, 110, 91, 111, 3, 112, 92, 113, 6, 114, 4, 115, 4, 116, 93, 117, 94, 118, 94, 119, 2, 120, 4, 121, 95, 0 </int_array> + <int_array len="960"> -1, -1, 1, 0, -1, 2, 2, 0, 3, 1, 0, 0, 0, 5, 4, -1, 24, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 10, 5, 11, 6, 12, 7, 13, 8, 14, 2, 15, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 8, 22, 14, 23, 14, 24, 3, 25, 6, 26, 4, 27, 15, 3, 16, 0, 0, 0, 1, 28, -1, 2, 2, 0, 3, 17, 0, 2, 0, 30, 29, 18, 3, 2, 0, 10, 19, 3, 20, 0, 2, 0, 30, 31, 18, 3, 2, 0, 10, 21, 3, 20, 0, 2, 0, 30, 32, 18, 3, 2, 0, 10, 22, 3, 20, 0, 2, 0, 30, 33, 18, 3, 2, 0, 10, 23, 3, 20, 0, 2, 0, 30, 34, 18, 3, 2, 0, 10, 24, 3, 20, 0, 2, 0, 30, 35, 18, 3, 2, 0, 10, 25, 3, 20, 0, 2, 0, 30, 36, 18, 3, 2, 0, 10, 26, 3, 20, 0, 2, 0, 30, 37, 18, 3, 2, 0, 10, 27, 3, 20, 0, 2, 0, 30, 38, 18, 3, 2, 0, 10, 28, 3, 20, 0, 2, 0, 30, 39, 18, 3, 2, 0, 10, 29, 3, 20, 0, 2, 0, 30, 40, 18, 3, 2, 0, 10, 30, 3, 20, 0, 2, 0, 30, 41, 18, 3, 2, 0, 10, 31, 3, 20, 0, 2, 0, 30, 42, 18, 3, 2, 0, 10, 32, 3, 20, 0, 2, 0, 30, 43, 18, 3, 2, 0, 10, 33, 3, 20, 0, 2, 0, 30, 44, 18, 3, 2, 0, 10, 34, 3, 20, 0, 2, 0, 30, 45, 18, 3, 2, 0, 10, 35, 3, 20, 0, 2, 0, 30, 46, 18, 3, 2, 0, 10, 36, 3, 20, 0, 2, 0, 30, 47, 18, 3, 2, 0, 10, 37, 3, 20, 0, 2, 0, 30, 48, 18, 3, 2, 0, 10, 38, 3, 20, 0, 2, 0, 30, 49, 18, 3, 2, 0, 10, 39, 3, 20, 0, 2, 0, 30, 50, 18, 3, 2, 0, 10, 40, 3, 20, 0, 2, 0, 30, 51, 18, 3, 2, 0, 10, 41, 3, 20, 0, 2, 0, 30, 52, 18, 3, 2, 0, 10, 42, 3, 20, 0, 2, 0, 30, 53, 18, 3, 2, 0, 10, 43, 3, 20, 0, 2, 0, 30, 54, 18, 3, 2, 0, 10, 44, 3, 20, 0, 2, 0, 30, 55, 18, 3, 2, 0, 10, 45, 3, 20, 0, 2, 0, 30, 56, 18, 3, 2, 0, 10, 46, 3, 20, 0, 2, 0, 30, 57, 18, 3, 2, 0, 10, 47, 3, 20, 0, 2, 0, 30, 58, 18, 3, 2, 0, 10, 48, 3, 20, 0, 2, 0, 30, 59, 18, 3, 2, 0, 10, 49, 3, 20, 0, 2, 0, 30, 60, 18, 3, 2, 0, 10, 50, 3, 20, 0, 2, 0, 30, 61, 18, 3, 2, 0, 10, 51, 3, 20, 0, 2, 0, 30, 62, 18, 3, 2, 0, 10, 52, 3, 20, 0, 2, 0, 30, 63, 18, 3, 2, 0, 10, 53, 3, 20, 0, 2, 0, 30, 64, 18, 3, 2, 0, 10, 54, 3, 20, 0, 2, 0, 30, 65, 18, 3, 2, 0, 10, 55, 3, 20, 0, 2, 0, 30, 66, 18, 3, 2, 0, 10, 56, 3, 20, 0, 2, 0, 30, 67, 18, 3, 2, 0, 10, 57, 3, 20, 0, 2, 0, 30, 68, 18, 3, 2, 0, 10, 58, 3, 20, 0, 2, 0, 30, 69, 18, 3, 2, 0, 10, 59, 3, 20, 0, 2, 0, 30, 70, 18, 3, 2, 0, 10, 60, 3, 20, 0, 2, 0, 30, 71, 18, 3, 2, 0, 10, 61, 3, 20, 0, 0, 0, 73, 72, 62, 3, 2, 0, 10, 63, 3, 64, 0, 0, 0, 1, 74, -1, 1, 2, 0, 0, 46, 0, 76, 75, 65, 5, 2, 0, 10, 66, 3, 67, 77, 68, 78, 69, 0, 46, 0, 76, 79, 65, 5, 2, 0, 10, 70, 3, 67, 77, 71, 78, 72, 0, 46, 0, 76, 80, 65, 5, 2, 0, 10, 73, 3, 67, 77, 74, 78, 72, 0, 46, 0, 76, 81, 75, 3, 2, 0, 10, 76, 3, 77, 0, 0, 0, 83, 82, -1, 7, 2, 0, 84, 78, 85, 14, 86, 2, 87, 79, 88, 2, 89, 14, 0, 0, 0, 1, 90, -1, 1, 2, 0, 0, 52, 0, 73, 91, 80, 3, 2, 0, 10, 81, 3, 82, 0, 52, 0, 73, 92, 80, 3, 2, 0, 10, 83, 3, 82, 0, 52, 0, 73, 93, 80, 3, 2, 0, 10, 84, 3, 82, 0, 52, 0, 73, 94, 80, 3, 2, 0, 10, 85, 3, 82, 0, 52, 0, 73, 95, 80, 3, 2, 0, 10, 86, 3, 82, 0, 52, 0, 73, 96, 80, 3, 2, 0, 10, 87, 3, 82, 0, 52, 0, 73, 97, 80, 3, 2, 0, 10, 88, 3, 82, 0, 52, 0, 73, 98, 80, 3, 2, 0, 10, 89, 3, 82, 0, 52, 0, 73, 99, 80, 3, 2, 0, 10, 90, 3, 82, 0, 52, 0, 73, 100, 80, 3, 2, 0, 10, 91, 3, 82, 0, 52, 0, 73, 101, 80, 3, 2, 0, 10, 92, 3, 82, 0, 0, 0, 103, 102, 93, 2, 2, 0, 3, 94, 0, 0, 0, 104, 104, -1, 30, 2, 0, 6, 2, 7, 3, 8, 3, 9, 4, 105, 95, 106, 96, 107, 97, 108, 98, 109, 0, 110, 0, 111, 0, 112, 0, 113, 2, 114, 2, 115, 13, 116, 3, 117, 6, 118, 99, 119, 3, 120, 100, 121, 6, 122, 14, 123, 14, 124, 101, 125, 8, 126, 8, 127, 2, 128, 14, 129, 102, 0 </int_array> <string> "conns" </string> <int_array len="0"> </int_array> </dictionary> diff --git a/demos/2d/platformer/tiles_demo.png b/demos/2d/platformer/tiles_demo.png Binary files differindex a7a5000906..bc738e6d38 100644 --- a/demos/2d/platformer/tiles_demo.png +++ b/demos/2d/platformer/tiles_demo.png diff --git a/demos/2d/platformer/tileset.xml b/demos/2d/platformer/tileset.xml index 2e4ecc8c04..d8f9a651ee 100644 --- a/demos/2d/platformer/tileset.xml +++ b/demos/2d/platformer/tileset.xml @@ -1,134 +1,191 @@ <?xml version="1.0" encoding="UTF-8" ?> -<resource_file type="TileSet" subresource_count="12" version="0.99" version_name="Godot Engine v0.99.3037-pre-beta"> +<resource_file type="TileSet" subresource_count="14" version="1.0" version_name="Godot Engine v1.0.stable.custom_build"> <ext_resource path="res://tiles_demo.png" type="Texture"></ext_resource> - <resource type="ConvexPolygonShape2D" path="local://0"> - <string name="resource/name"> "" </string> - <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 8, 64, 8, 64, 64, 0, 64 </vector2_array> - <resource name="script/script"></resource> - </resource> <resource type="ConvexPolygonShape2D" path="local://1"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 8, 56, 8, 56, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, -24, 32, -24, 32, 32, -32, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://2"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 0, 56, 0, 56, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, 32, -32, -24, 24, -24, 24, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://3"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 0, 56, 0, 56, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, 32, -32, -32, 24, -32, 24, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://4"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="5"> 0, 64, 0, 0, 56, 0, 64, 8, 64, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -64, 32, -64, -32, -8, -32, -8, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://5"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 8, 64, 8, 64, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="5"> -32, 32, -32, -32, 24, -32, 32, -24, 32, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://6"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 8, 64, 8, 64, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, 32, -32, -24, 32, -24, 32, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://7"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 0, 64, 0, 64, 64, 0, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, 32, -32, -24, 32, -24, 32, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://8"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 8, 64, 72, 64, 128, 0, 128 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, -32, 32, -32, 32, 32, -32, 32 </vector2_array> + </resource> <resource type="ConvexPolygonShape2D" path="local://9"> - <string name="resource/name"> "" </string> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 0, 56, 0, 56, 64 </vector2_array> - <resource name="script/script"></resource> + <vector2_array name="points" len="4"> -32, -56, 32, 8, 32, 64, -32, 64 </vector2_array> + + </resource> + <resource type="ConvexPolygonShape2D" path="local://10"> + <real name="custom_solver_bias"> 0 </real> + <vector2_array name="points" len="4"> -32, 32, -32, -32, 24, -32, 24, 32 </vector2_array> + + </resource> + <resource type="ConvexPolygonShape2D" path="local://11"> + <real name="custom_solver_bias"> 0 </real> + <vector2_array name="points" len="4"> -32, -24, 32, -24, 32, 24, -32, 24 </vector2_array> + + </resource> + <resource type="ConvexPolygonShape2D" path="local://12"> + <real name="custom_solver_bias"> 0 </real> + <vector2_array name="points" len="4"> -32, -24, 24, -24, 24, 24, -32, 24 </vector2_array> + </resource> <main_resource> - <string name="resource/name"> "" </string> <string name="0/name"> "floor" </string> <resource name="0/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="0/offset"> 0, 0 </vector2> + <vector2 name="0/tex_offset"> 0, 0 </vector2> + <vector2 name="0/shape_offset"> 32, 32 </vector2> <rect2 name="0/region"> 0, 0, 64, 64 </rect2> - <resource name="0/shape" resource_type="ConvexPolygonShape2D" path="local://0"> </resource> + <array name="0/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://1"> </resource> + </array> <string name="1/name"> "edge" </string> <resource name="1/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="1/offset"> 0, 0 </vector2> + <vector2 name="1/tex_offset"> 0, 0 </vector2> + <vector2 name="1/shape_offset"> 32, 32 </vector2> <rect2 name="1/region"> 64, 0, 64, 64 </rect2> - <resource name="1/shape" resource_type="ConvexPolygonShape2D" path="local://1"> </resource> + <array name="1/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://2"> </resource> + </array> <string name="2/name"> "wall" </string> <resource name="2/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="2/offset"> 0, 0 </vector2> + <vector2 name="2/tex_offset"> 0, 0 </vector2> + <vector2 name="2/shape_offset"> 32, 32 </vector2> <rect2 name="2/region"> 64, 64, 64, 64 </rect2> - <resource name="2/shape" resource_type="ConvexPolygonShape2D" path="local://2"> </resource> + <array name="2/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://3"> </resource> + </array> <string name="3/name"> "wall_deco" </string> <resource name="3/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="3/offset"> 0, 0 </vector2> + <vector2 name="3/tex_offset"> 0, 0 </vector2> + <vector2 name="3/shape_offset"> 64, 32 </vector2> <rect2 name="3/region"> 320, 128, 128, 64 </rect2> - <resource name="3/shape" resource_type="ConvexPolygonShape2D" path="local://3"> </resource> + <array name="3/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://4"> </resource> + </array> <string name="4/name"> "corner" </string> <resource name="4/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="4/offset"> 0, 0 </vector2> + <vector2 name="4/tex_offset"> 0, 0 </vector2> + <vector2 name="4/shape_offset"> 32, 32 </vector2> <rect2 name="4/region"> 64, 128, 64, 64 </rect2> - <resource name="4/shape" resource_type="ConvexPolygonShape2D" path="local://4"> </resource> + <array name="4/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://5"> </resource> + </array> <string name="5/name"> "flowers" </string> <resource name="5/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="5/offset"> 0, 0 </vector2> + <vector2 name="5/tex_offset"> 0, 0 </vector2> + <vector2 name="5/shape_offset"> 32, 32 </vector2> <rect2 name="5/region"> 192, 192, 64, 64 </rect2> - <resource name="5/shape" resource_type="ConvexPolygonShape2D" path="local://5"> </resource> + <array name="5/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://6"> </resource> + </array> <string name="6/name"> "tree_base" </string> <resource name="6/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="6/offset"> 0, 0 </vector2> + <vector2 name="6/tex_offset"> 0, 0 </vector2> + <vector2 name="6/shape_offset"> 32, 32 </vector2> <rect2 name="6/region"> 256, 192, 64, 64 </rect2> - <resource name="6/shape" resource_type="ConvexPolygonShape2D" path="local://6"> </resource> + <array name="6/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://7"> </resource> + </array> <string name="7/name"> "tree_mid" </string> <resource name="7/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="7/offset"> 0, 0 </vector2> + <vector2 name="7/tex_offset"> 0, 0 </vector2> + <vector2 name="7/shape_offset"> 0, 0 </vector2> <rect2 name="7/region"> 256, 128, 64, 64 </rect2> - <resource name="7/shape"></resource> <string name="8/name"> "tree_mid 2" </string> + <array name="7/shapes" len="0" shared="false"> + </array> + <string name="8/name"> "tree_mid 2" </string> <resource name="8/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="8/offset"> 0, 0 </vector2> + <vector2 name="8/tex_offset"> 0, 0 </vector2> + <vector2 name="8/shape_offset"> 0, 0 </vector2> <rect2 name="8/region"> 256, 64, 64, 64 </rect2> - <resource name="8/shape"></resource> <string name="9/name"> "tree_top" </string> + <array name="8/shapes" len="0" shared="false"> + </array> + <string name="9/name"> "tree_top" </string> <resource name="9/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="9/offset"> 0, 0 </vector2> + <vector2 name="9/tex_offset"> 0, 0 </vector2> + <vector2 name="9/shape_offset"> 0, 0 </vector2> <rect2 name="9/region"> 256, 0, 64, 64 </rect2> - <resource name="9/shape"></resource> <string name="10/name"> "solid" </string> + <array name="9/shapes" len="0" shared="false"> + </array> + <string name="10/name"> "solid" </string> <resource name="10/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="10/offset"> 0, 0 </vector2> + <vector2 name="10/tex_offset"> 0, 0 </vector2> + <vector2 name="10/shape_offset"> 0, 0 </vector2> <rect2 name="10/region"> 0, 64, 64, 64 </rect2> - <resource name="10/shape"></resource> <string name="11/name"> "ceiling" </string> + <array name="10/shapes" len="0" shared="false"> + </array> + <string name="11/name"> "ceiling" </string> <resource name="11/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="11/offset"> 0, 0 </vector2> + <vector2 name="11/tex_offset"> 0, 0 </vector2> + <vector2 name="11/shape_offset"> 32, 32 </vector2> <rect2 name="11/region"> 384, 64, 64, 64 </rect2> - <resource name="11/shape" resource_type="ConvexPolygonShape2D" path="local://7"> </resource> + <array name="11/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://8"> </resource> + </array> <string name="12/name"> "ramp" </string> <resource name="12/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="12/offset"> 0, 0 </vector2> + <vector2 name="12/tex_offset"> 0, 0 </vector2> + <vector2 name="12/shape_offset"> 32, 64 </vector2> <rect2 name="12/region"> 128, 128, 64, 128 </rect2> - <resource name="12/shape" resource_type="ConvexPolygonShape2D" path="local://8"> </resource> + <array name="12/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://9"> </resource> + </array> <string name="13/name"> "ceiling2wall" </string> <resource name="13/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> - <vector2 name="13/offset"> 0, 0 </vector2> + <vector2 name="13/tex_offset"> 0, 0 </vector2> + <vector2 name="13/shape_offset"> 32, 32 </vector2> <rect2 name="13/region"> 448, 64, 64, 64 </rect2> - <resource name="13/shape" resource_type="ConvexPolygonShape2D" path="local://9"> </resource> - <resource name="script/script"></resource> + <array name="13/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://10"> </resource> + </array> + <string name="14/name"> "platform_floor" </string> + <resource name="14/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> + <vector2 name="14/tex_offset"> 0, 0 </vector2> + <vector2 name="14/shape_offset"> 32, 32 </vector2> + <rect2 name="14/region"> 128, 0, 64, 64 </rect2> + <array name="14/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://11"> </resource> + </array> + <string name="15/name"> "platform_edge" </string> + <resource name="15/texture" resource_type="Texture" path="res://tiles_demo.png"> </resource> + <vector2 name="15/tex_offset"> 0, 0 </vector2> + <vector2 name="15/shape_offset"> 32, 32 </vector2> + <rect2 name="15/region"> 192, 0, 64, 64 </rect2> + <array name="15/shapes" len="1" shared="false"> + <resource resource_type="Shape2D" path="local://12"> </resource> + </array> + </main_resource> </resource_file>
\ No newline at end of file diff --git a/demos/2d/platformer/tileset_edit.xml b/demos/2d/platformer/tileset_edit.xml index 2473656a6a..db289433ab 100644 --- a/demos/2d/platformer/tileset_edit.xml +++ b/demos/2d/platformer/tileset_edit.xml @@ -1,71 +1,83 @@ <?xml version="1.0" encoding="UTF-8" ?> -<resource_file type="PackedScene" subresource_count="12" version="1.0" version_name="Godot Engine v1.0.3917-beta1"> +<resource_file type="PackedScene" subresource_count="14" version="1.0" version_name="Godot Engine v1.0.stable.custom_build"> <ext_resource path="res://tiles_demo.png" type="Texture"></ext_resource> <resource type="ConvexPolygonShape2D" path="local://1"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 8, 64, 8, 64, 64, 0, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, -24, 32, -24, 32, 32, -32, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://2"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 8, 56, 8, 56, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, 32, -32, -24, 24, -24, 24, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://3"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 0, 56, 0, 56, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, 32, -32, -32, 24, -32, 24, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://4"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 0, 56, 0, 56, 64 </vector2_array> + <vector2_array name="points" len="4"> -64, 32, -64, -32, -8, -32, -8, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://5"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="5"> 0, 64, 0, 0, 56, 0, 64, 8, 64, 64 </vector2_array> + <vector2_array name="points" len="5"> -32, 32, -32, -32, 24, -32, 32, -24, 32, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://6"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 8, 64, 72, 64, 128, 0, 128 </vector2_array> + <vector2_array name="points" len="4"> -32, 32, -32, -24, 32, -24, 32, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://7"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 8, 64, 8, 64, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, 32, -32, -24, 32, -24, 32, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://8"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 8, 64, 8, 64, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, -32, 32, -32, 32, 32, -32, 32 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://9"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 0, 64, 0, 64, 64, 0, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, -56, 32, 8, 32, 64, -32, 64 </vector2_array> </resource> <resource type="ConvexPolygonShape2D" path="local://10"> <real name="custom_solver_bias"> 0 </real> - <vector2_array name="points" len="4"> 0, 64, 0, 0, 56, 0, 56, 64 </vector2_array> + <vector2_array name="points" len="4"> -32, 32, -32, -32, 24, -32, 24, 32 </vector2_array> + + </resource> + <resource type="ConvexPolygonShape2D" path="local://11"> + <real name="custom_solver_bias"> 0 </real> + <vector2_array name="points" len="4"> -32, -24, 32, -24, 32, 24, -32, 24 </vector2_array> + + </resource> + <resource type="ConvexPolygonShape2D" path="local://12"> + <real name="custom_solver_bias"> 0 </real> + <vector2_array name="points" len="4"> -32, -24, 24, -24, 24, 24, -32, 24 </vector2_array> </resource> <main_resource> <dictionary name="_bundled" shared="false"> <string> "names" </string> - <string_array len="75"> + <string_array len="77"> <string> "Node" </string> + <string> "_import_path" </string> <string> "__meta__" </string> <string> "floor" </string> <string> "Sprite" </string> <string> "visibility/visible" </string> <string> "visibility/opacity" </string> <string> "visibility/self_opacity" </string> - <string> "visibility/behind_parent" </string> <string> "transform/pos" </string> <string> "transform/rot" </string> <string> "transform/scale" </string> + <string> "z/z" </string> + <string> "z/relative" </string> <string> "texture" </string> <string> "centered" </string> <string> "offset" </string> @@ -83,6 +95,7 @@ <string> "shapes/0/shape" </string> <string> "shapes/0/transform" </string> <string> "shapes/0/trigger" </string> + <string> "layers" </string> <string> "constant_linear_velocity" </string> <string> "constant_angular_velocity" </string> <string> "friction" </string> @@ -90,11 +103,11 @@ <string> "CollisionPolygon2D" </string> <string> "build_mode" </string> <string> "polygon" </string> + <string> "trigger" </string> <string> "edge" </string> <string> "wall" </string> <string> "wall_deco" </string> <string> "corner" </string> - <string> "ramp" </string> <string> "flowers" </string> <string> "tree_base" </string> <string> "tree_mid" </string> @@ -102,13 +115,10 @@ <string> "tree_top" </string> <string> "solid" </string> <string> "ceiling" </string> + <string> "ramp" </string> <string> "ceiling2wall" </string> <string> "help" </string> <string> "Label" </string> - <string> "margin/left" </string> - <string> "margin/top" </string> - <string> "margin/right" </string> - <string> "margin/bottom" </string> <string> "focus_neighbour/left" </string> <string> "focus_neighbour/top" </string> <string> "focus_neighbour/right" </string> @@ -130,29 +140,38 @@ <string> "autowrap" </string> <string> "uppercase" </string> <string> "percent_visible" </string> + <string> "platform_floor" </string> + <string> "platform_edge" </string> </string_array> <string> "version" </string> <int> 1 </int> <string> "conn_count" </string> <int> 0 </int> <string> "node_count" </string> - <int> 36 </int> + <int> 42 </int> <string> "variants" </string> - <array len="65" shared="false"> + <array len="69" shared="false"> + <node_path> "" </node_path> <dictionary shared="false"> <string> "__editor_plugin_states__" </string> <dictionary shared="false"> <string> "2D" </string> <dictionary shared="false"> <string> "pixel_snap" </string> - <bool> False </bool> + <bool> True </bool> <string> "zoom" </string> - <real> 1.670182 </real> + <real> 1.670183 </real> + <string> "use_snap" </string> + <bool> True </bool> <string> "ofs" </string> - <vector2> -58.9115, 60.1605 </vector2> + <vector2> -446.534, -87.6905 </vector2> + <string> "snap" </string> + <int> 8 </int> </dictionary> <string> "3D" </string> <dictionary shared="false"> + <string> "deflight_rot_y" </string> + <real> 0.628319 </real> <string> "zfar" </string> <real> 500 </real> <string> "fov" </string> @@ -166,10 +185,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> + <string> "listener" </string> + <bool> True </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -180,10 +201,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -194,10 +217,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -208,10 +233,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -220,12 +247,18 @@ <int> 1 </int> <string> "default_light" </string> <bool> True </bool> + <string> "ambient_light_color" </string> + <color> 0.15, 0.15, 0.15, 1 </color> <string> "show_grid" </string> <bool> True </bool> <string> "show_origin" </string> <bool> True </bool> <string> "znear" </string> <real> 0.1 </real> + <string> "default_srgb" </string> + <bool> False </bool> + <string> "deflight_rot_x" </string> + <real> 0.942478 </real> </dictionary> </dictionary> <string> "__editor_run_settings__" </string> @@ -239,45 +272,42 @@ <string> "2D" </string> </dictionary> <bool> True </bool> - <nil> </nil> - <nil> </nil> + <real> 1 </real> <vector2> 0, 0 </vector2> - <nil> </nil> + <real> 0 </real> <vector2> 1, 1 </vector2> + <int> 0 </int> <resource resource_type="Texture" path="res://tiles_demo.png"> </resource> + <bool> False </bool> <int> 1 </int> - <nil> </nil> <color> 1, 1, 1, 1 </color> <rect2> 0, 0, 64, 64 </rect2> <resource resource_type="Shape2D" path="local://1"> </resource> <matrix32> 1, -0, 0, 1, 0, 0 </matrix32> - <vector2_array len="4"> 64, 8, 64, 64, 0, 64, 0, 8 </vector2_array> + <vector2_array len="4"> 32, -24, 32, 32, -32, 32, -32, -24 </vector2_array> <vector2> 64, 0 </vector2> <rect2> 64, 0, 64, 64 </rect2> <resource resource_type="Shape2D" path="local://2"> </resource> - <vector2_array len="4"> 0, 8, 56, 8, 56, 64, 0, 64 </vector2_array> + <vector2_array len="4"> -32, -24, 24, -24, 24, 32, -32, 32 </vector2_array> <vector2> 64, 64 </vector2> <rect2> 64, 64, 64, 64 </rect2> <resource resource_type="Shape2D" path="local://3"> </resource> - <vector2_array len="4"> 0, 0, 56, 0, 56, 64, 0, 64 </vector2_array> - <vector2> 64, 128 </vector2> + <vector2_array len="4"> -32, -32, 24, -32, 24, 32, -32, 32 </vector2_array> + <vector2> 96, 128 </vector2> <rect2> 320, 128, 128, 64 </rect2> <resource resource_type="Shape2D" path="local://4"> </resource> + <vector2_array len="4"> -64, -32, -8, -32, -8, 32, -64, 32 </vector2_array> <vector2> 64, 192 </vector2> <rect2> 64, 128, 64, 64 </rect2> <resource resource_type="Shape2D" path="local://5"> </resource> - <vector2_array len="5"> 0, 0, 56, 0, 64, 8, 64, 64, 0, 64 </vector2_array> - <vector2> 256, 192 </vector2> - <rect2> 128, 128, 64, 128 </rect2> - <resource resource_type="Shape2D" path="local://6"> </resource> - <vector2_array len="4"> 0, 8, 64, 72, 64, 128, 0, 128 </vector2_array> + <vector2_array len="5"> -32, -32, 24, -32, 32, -24, 32, 32, -32, 32 </vector2_array> <vector2> 128, 192 </vector2> <rect2> 192, 192, 64, 64 </rect2> - <resource resource_type="Shape2D" path="local://7"> </resource> - <vector2_array len="4"> 0, 64, 64, 64, 64, 8, 0, 8 </vector2_array> + <resource resource_type="Shape2D" path="local://6"> </resource> + <vector2_array len="4"> -32, 32, 32, 32, 32, -24, -32, -24 </vector2_array> <vector2> 192, 192 </vector2> <rect2> 256, 192, 64, 64 </rect2> - <resource resource_type="Shape2D" path="local://8"> </resource> + <resource resource_type="Shape2D" path="local://7"> </resource> <vector2> 192, 128 </vector2> <rect2> 256, 128, 64, 64 </rect2> <vector2> 192, 64 </vector2> @@ -288,23 +318,29 @@ <rect2> 0, 64, 64, 64 </rect2> <vector2> 0, 128 </vector2> <rect2> 384, 64, 64, 64 </rect2> + <resource resource_type="Shape2D" path="local://8"> </resource> + <vector2_array len="4"> 32, -32, 32, 32, -32, 32, -32, -32 </vector2_array> + <vector2> 256, 224 </vector2> + <rect2> 128, 128, 64, 128 </rect2> <resource resource_type="Shape2D" path="local://9"> </resource> - <vector2_array len="4"> 64, 0, 64, 64, 0, 64, 0, 0 </vector2_array> + <vector2_array len="4"> -32, -56, 32, 8, 32, 64, -32, 64 </vector2_array> <vector2> 0, 192 </vector2> <rect2> 448, 64, 64, 64 </rect2> <resource resource_type="Shape2D" path="local://10"> </resource> - <nil> </nil> - <nil> </nil> - <nil> </nil> - <nil> </nil> - <nil> </nil> <int> 2 </int> - <nil> </nil> - <string> "This scene serves as a tool for editing the tileset. Nodes (sprites) and their respective collisions are edited here. To create a tileset from this, a "TileSet" resoucre must be created. Use the helper in: Scene -< Convert To -< TileSet This will save a tileset. Saving over it will merge your changes. Finally, the saved tileset resource (tileset.xml in this case), can be opened to be used into a TileMap node for editing a tile map. " </string> + <string> "This scene serves as a tool for editing the tileset.
Nodes (sprites) and their respective collisions
are edited here. 

To create a tileset from this, a "TileSet" resoucre 
must be created. Use the helper in:

 Scene -< Convert To -< TileSet

This will save a tileset. Saving over it will merge your changes.

Finally, the saved tileset resource (tileset.xml in this
 case), can be opened to be used into a TileMap node
 for editing a tile map.
" </string> <real> -1 </real> + <vector2> 0, 256 </vector2> + <rect2> 128, 0, 64, 64 </rect2> + <resource resource_type="Shape2D" path="local://11"> </resource> + <vector2_array len="4"> 32, -24, 32, 24, -32, 24, -32, -24 </vector2_array> + <vector2> 64, 256 </vector2> + <rect2> 192, 0, 64, 64 </rect2> + <resource resource_type="Shape2D" path="local://12"> </resource> + <vector2_array len="4"> 24, -24, 24, 24, -32, 24, -32, -24 </vector2_array> </array> <string> "nodes" </string> - <int_array len="1296"> -1, -1, 0, 0, -1, 1, 1, 0, 0, 0, 0, 3, 2, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 11, 0, 1, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 12, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 2, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 14, 0, 0, 0, 3, 35, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 15, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 16, 0, 4, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 17, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 5, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 18, 0, 0, 0, 3, 36, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 19, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 20, 0, 7, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 21, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 8, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 22, 0, 0, 0, 3, 37, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 23, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 24, 0, 10, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 25, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 11, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 22, 0, 0, 0, 3, 38, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 26, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 27, 0, 13, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 28, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 14, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 29, 0, 0, 0, 3, 39, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 30, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 31, 0, 16, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 32, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 17, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 33, 0, 0, 0, 3, 40, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 34, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 35, 0, 19, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 36, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 20, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 37, 0, 0, 0, 3, 41, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 38, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 39, 0, 22, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 40, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 23, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 37, 0, 0, 0, 3, 42, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 41, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 42, 0, 0, 0, 3, 43, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 43, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 44, 0, 0, 0, 3, 44, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 45, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 46, 0, 0, 0, 3, 45, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 47, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 48, 0, 0, 0, 3, 46, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 49, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 50, 0, 29, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 51, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 30, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 52, 0, 0, 0, 3, 47, -1, 18, 4, 1, 5, 2, 6, 2, 7, 3, 8, 53, 9, 5, 10, 6, 11, 7, 12, 3, 13, 4, 14, 3, 15, 3, 16, 8, 17, 8, 18, 9, 19, 10, 20, 1, 21, 54, 0, 32, 0, 23, 22, -1, 15, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 24, 8, 25, 55, 26, 13, 27, 3, 28, 4, 29, 5, 30, 2, 31, 5, 0, 33, 0, 32, 32, -1, 9, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 33, 9, 34, 22, 0, 0, 0, 49, 48, -1, 29, 4, 1, 5, 2, 6, 2, 7, 3, 50, 56, 51, 57, 52, 58, 53, 59, 54, 60, 55, 60, 56, 60, 57, 60, 58, 1, 59, 1, 60, 61, 61, 2, 62, 5, 63, 62, 64, 2, 65, 62, 66, 5, 67, 3, 68, 3, 69, 63, 70, 9, 71, 9, 72, 3, 73, 3, 74, 64, 0 </int_array> + <int_array len="1708"> -1, -1, 0, 0, -1, 2, 1, 0, 2, 1, 0, 0, 0, 4, 3, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 12, 0, 1, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 13, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 2, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 15, 38, 9, 0, 0, 0, 4, 39, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 16, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 17, 0, 4, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 18, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 5, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 19, 38, 9, 0, 0, 0, 4, 40, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 20, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 21, 0, 7, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 22, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 8, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 23, 38, 9, 0, 0, 0, 4, 41, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 24, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 25, 0, 10, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 26, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 11, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 27, 38, 9, 0, 0, 0, 4, 42, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 28, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 29, 0, 13, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 30, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 14, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 31, 38, 9, 0, 0, 0, 4, 43, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 32, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 33, 0, 16, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 34, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 17, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 35, 38, 9, 0, 0, 0, 4, 44, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 36, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 37, 0, 19, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 38, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 20, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 35, 38, 9, 0, 0, 0, 4, 45, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 39, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 40, 0, 0, 0, 4, 46, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 41, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 42, 0, 0, 0, 4, 47, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 43, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 44, 0, 0, 0, 4, 48, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 45, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 46, 0, 0, 0, 4, 49, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 47, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 48, 0, 26, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 49, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 27, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 50, 38, 9, 0, 0, 0, 4, 50, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 51, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 52, 0, 29, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 53, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 30, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 54, 38, 9, 0, 0, 0, 4, 51, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 55, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 56, 0, 32, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 57, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 33, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 23, 38, 9, 0, 0, 0, 53, 52, -1, 25, 1, 0, 5, 2, 6, 3, 7, 3, 54, 0, 55, 0, 56, 0, 57, 0, 58, 2, 59, 2, 60, 58, 61, 3, 62, 5, 63, 3, 64, 3, 65, 3, 66, 5, 67, 9, 68, 9, 69, 59, 70, 7, 71, 7, 72, 9, 73, 9, 74, 60, 0, 0, 0, 4, 75, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 61, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 62, 0, 36, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 63, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 37, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 64, 38, 9, 0, 0, 0, 4, 76, -1, 20, 1, 0, 5, 2, 6, 3, 7, 3, 8, 65, 9, 5, 10, 6, 11, 7, 12, 2, 13, 8, 14, 2, 15, 4, 16, 9, 17, 9, 18, 10, 19, 10, 20, 7, 21, 11, 22, 2, 23, 66, 0, 39, 0, 25, 24, -1, 18, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 26, 10, 27, 67, 28, 14, 29, 9, 30, 10, 31, 4, 32, 5, 33, 3, 34, 5, 0, 40, 0, 35, 35, -1, 12, 1, 0, 5, 2, 6, 3, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 2, 36, 7, 37, 68, 38, 9, 0 </int_array> <string> "conns" </string> <int_array len="0"> </int_array> </dictionary> diff --git a/demos/2d/polygon_path_finder_demo/engine.cfg b/demos/2d/polygon_path_finder_demo/engine.cfg new file mode 100644 index 0000000000..41c4adf701 --- /dev/null +++ b/demos/2d/polygon_path_finder_demo/engine.cfg @@ -0,0 +1,5 @@ +[application] + +name="polygon_path_finder_demo" +main_scene="res://new_scene_poly_with_holes.scn" +icon="icon.png" diff --git a/demos/2d/polygon_path_finder_demo/icon.png b/demos/2d/polygon_path_finder_demo/icon.png Binary files differnew file mode 100644 index 0000000000..0c422e37b0 --- /dev/null +++ b/demos/2d/polygon_path_finder_demo/icon.png diff --git a/demos/2d/polygon_path_finder_demo/icon.png.flags b/demos/2d/polygon_path_finder_demo/icon.png.flags new file mode 100644 index 0000000000..dbef2209e8 --- /dev/null +++ b/demos/2d/polygon_path_finder_demo/icon.png.flags @@ -0,0 +1 @@ +gen_mipmaps=true diff --git a/demos/2d/polygon_path_finder_demo/new_scene_poly_with_holes.scn b/demos/2d/polygon_path_finder_demo/new_scene_poly_with_holes.scn Binary files differnew file mode 100644 index 0000000000..07838be41e --- /dev/null +++ b/demos/2d/polygon_path_finder_demo/new_scene_poly_with_holes.scn diff --git a/demos/2d/polygon_path_finder_demo/polygonpathfinder.gd b/demos/2d/polygon_path_finder_demo/polygonpathfinder.gd new file mode 100644 index 0000000000..a0e71dd127 --- /dev/null +++ b/demos/2d/polygon_path_finder_demo/polygonpathfinder.gd @@ -0,0 +1,80 @@ + +extends Spatial + +func _ready(): + var pf = PolygonPathFinder.new() + + var points = Vector2Array() + var connections = IntArray() + + # poly 1 + points.push_back(Vector2(0, 0)) #0 + points.push_back(Vector2(10, 0)) #1 + points.push_back(Vector2(10, 10)) #2 + points.push_back(Vector2(0, 10)) #3 + + connections.push_back(0) # connect vertex 0 ... + connections.push_back(1) # ... to 1 + drawLine(points[0], points[1], get_node("/root/Spatial/Polys")) + connections.push_back(1) # connect vertex 1 ... + connections.push_back(2) # ... to 2 + drawLine(points[1], points[2], get_node("/root/Spatial/Polys")) + connections.push_back(2) # etc. + connections.push_back(3) + drawLine(points[2], points[3], get_node("/root/Spatial/Polys")) + connections.push_back(3) # connect vertex 3 ... + connections.push_back(0) # back to vertex 0, to close the polygon + drawLine(points[3], points[0], get_node("/root/Spatial/Polys")) + + # poly 2, as obstacle inside poly 1 + points.push_back(Vector2(2, 0.5)) #4 + points.push_back(Vector2(4, 0.5)) #5 + points.push_back(Vector2(4, 9.5)) #6 + points.push_back(Vector2(2, 9.5)) #7 + + connections.push_back(4) + connections.push_back(5) + drawLine(points[4], points[5], get_node("/root/Spatial/Polys")) + connections.push_back(5) + connections.push_back(6) + drawLine(points[5], points[6], get_node("/root/Spatial/Polys")) + connections.push_back(6) + connections.push_back(7) + drawLine(points[6], points[7], get_node("/root/Spatial/Polys")) + connections.push_back(7) + connections.push_back(4) + drawLine(points[7], points[4], get_node("/root/Spatial/Polys")) + + + print("points: ",points) + print("connections: ",connections) + + pf.setup(points, connections) + + var path = pf.find_path(Vector2(1, 5), Vector2(8, 5)) + + var lastStep = null + print("path: ",path) + for step in path: + print("step: ",step) + if (lastStep != null): + var currPathSegment = Vector2Array() + drawLine(lastStep, step, get_node("/root/Spatial/Path")) + lastStep = step + + + +func drawLine(pointA, pointB, immediateGeo): + var drawPosY = 0.1 + var im = immediateGeo + + im.begin(Mesh.PRIMITIVE_POINTS, null) + im.add_vertex(Vector3(pointA.x, drawPosY, pointA.y)) + im.add_vertex(Vector3(pointB.x, drawPosY, pointB.y)) + im.end() + im.begin(Mesh.PRIMITIVE_LINE_STRIP, null) + im.add_vertex(Vector3(pointA.x, drawPosY, pointA.y)) + im.add_vertex(Vector3(pointB.x, drawPosY, pointB.y)) + im.end() + + diff --git a/demos/2d/screen_space_shaders/art/burano.jpg b/demos/2d/screen_space_shaders/art/burano.jpg Binary files differnew file mode 100644 index 0000000000..cdab993ec1 --- /dev/null +++ b/demos/2d/screen_space_shaders/art/burano.jpg diff --git a/demos/2d/screen_space_shaders/art/burano.png b/demos/2d/screen_space_shaders/art/burano.png Binary files differnew file mode 100644 index 0000000000..6eec09d585 --- /dev/null +++ b/demos/2d/screen_space_shaders/art/burano.png diff --git a/demos/2d/screen_space_shaders/art/filmgrain.png b/demos/2d/screen_space_shaders/art/filmgrain.png Binary files differnew file mode 100644 index 0000000000..b8ea89902c --- /dev/null +++ b/demos/2d/screen_space_shaders/art/filmgrain.png diff --git a/demos/2d/screen_space_shaders/art/filmgrain.png.flags b/demos/2d/screen_space_shaders/art/filmgrain.png.flags new file mode 100644 index 0000000000..d5476d5499 --- /dev/null +++ b/demos/2d/screen_space_shaders/art/filmgrain.png.flags @@ -0,0 +1 @@ +repeat=true diff --git a/demos/2d/screen_space_shaders/art/forest.png b/demos/2d/screen_space_shaders/art/forest.png Binary files differnew file mode 100644 index 0000000000..f5a2fb9bfb --- /dev/null +++ b/demos/2d/screen_space_shaders/art/forest.png diff --git a/demos/2d/screen_space_shaders/art/mountains.png b/demos/2d/screen_space_shaders/art/mountains.png Binary files differnew file mode 100644 index 0000000000..b8435bb1a8 --- /dev/null +++ b/demos/2d/screen_space_shaders/art/mountains.png diff --git a/demos/2d/screen_space_shaders/art/platformer.png b/demos/2d/screen_space_shaders/art/platformer.png Binary files differnew file mode 100644 index 0000000000..21c1cb4c4b --- /dev/null +++ b/demos/2d/screen_space_shaders/art/platformer.png diff --git a/demos/2d/screen_space_shaders/art/vignette.png b/demos/2d/screen_space_shaders/art/vignette.png Binary files differnew file mode 100644 index 0000000000..8afeb7f9e1 --- /dev/null +++ b/demos/2d/screen_space_shaders/art/vignette.png diff --git a/demos/2d/screen_space_shaders/art/white.png b/demos/2d/screen_space_shaders/art/white.png Binary files differnew file mode 100644 index 0000000000..573faa33f2 --- /dev/null +++ b/demos/2d/screen_space_shaders/art/white.png diff --git a/demos/2d/screen_space_shaders/engine.cfg b/demos/2d/screen_space_shaders/engine.cfg new file mode 100644 index 0000000000..2a41110886 --- /dev/null +++ b/demos/2d/screen_space_shaders/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="Screen-Space Shaders" +main_scene="res://screen_shaders.scn" diff --git a/demos/2d/screen_space_shaders/screen_shaders.gd b/demos/2d/screen_space_shaders/screen_shaders.gd new file mode 100644 index 0000000000..4e8a548539 --- /dev/null +++ b/demos/2d/screen_space_shaders/screen_shaders.gd @@ -0,0 +1,32 @@ + +extends Control + +# member variables here, example: +# var a=2 +# var b="textvar" + +func _ready(): + # Initialization here + for c in get_node("pictures").get_children(): + get_node("picture").add_item("PIC: "+c.get_name()) + for c in get_node("effects").get_children(): + get_node("effect").add_item("FX: "+c.get_name()) + pass + + + + +func _on_picture_item_selected( ID ): + for c in range(get_node("pictures").get_child_count()): + if (ID==c): + get_node("pictures").get_child(c).show() + else: + get_node("pictures").get_child(c).hide() + + +func _on_effect_item_selected( ID ): + for c in range(get_node("effects").get_child_count()): + if (ID==c): + get_node("effects").get_child(c).show() + else: + get_node("effects").get_child(c).hide() diff --git a/demos/2d/screen_space_shaders/screen_shaders.scn b/demos/2d/screen_space_shaders/screen_shaders.scn Binary files differnew file mode 100644 index 0000000000..aa359616de --- /dev/null +++ b/demos/2d/screen_space_shaders/screen_shaders.scn diff --git a/demos/2d/sdf_font/KaushanScript-Regular.otf b/demos/2d/sdf_font/KaushanScript-Regular.otf Binary files differnew file mode 100644 index 0000000000..bd29502100 --- /dev/null +++ b/demos/2d/sdf_font/KaushanScript-Regular.otf diff --git a/demos/2d/sdf_font/engine.cfg b/demos/2d/sdf_font/engine.cfg new file mode 100644 index 0000000000..bdf26ce741 --- /dev/null +++ b/demos/2d/sdf_font/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="Signed Distance Field Font" +main_scene="res://sdf.scn" diff --git a/demos/2d/sdf_font/font.fnt b/demos/2d/sdf_font/font.fnt Binary files differnew file mode 100644 index 0000000000..c2b6b0177d --- /dev/null +++ b/demos/2d/sdf_font/font.fnt diff --git a/demos/2d/sdf_font/sdf.scn b/demos/2d/sdf_font/sdf.scn Binary files differnew file mode 100644 index 0000000000..89d6245bf0 --- /dev/null +++ b/demos/2d/sdf_font/sdf.scn diff --git a/demos/2d/shower_of_bullets/bullet.png b/demos/2d/shower_of_bullets/bullet.png Binary files differnew file mode 100644 index 0000000000..7466374129 --- /dev/null +++ b/demos/2d/shower_of_bullets/bullet.png diff --git a/demos/2d/shower_of_bullets/bullets.gd b/demos/2d/shower_of_bullets/bullets.gd new file mode 100644 index 0000000000..79f4faaae6 --- /dev/null +++ b/demos/2d/shower_of_bullets/bullets.gd @@ -0,0 +1,76 @@ + +extends Node2D + +# This demo is an example of controling a high number of 2D objects with logic and collision without using scene nodes. +# This technique is a lot more efficient than using instancing and nodes, but requires more programming and is less visual + +const BULLET_COUNT = 500 +const SPEED_MIN = 20 +const SPEED_MAX = 50 + +var bullets=[] +var shape + +class Bullet: + var pos = Vector2() + var speed = 1.0 + var body = RID() + + +func _draw(): + + var t = preload("res://bullet.png") + var tofs = -t.get_size()*0.5 + for b in bullets: + draw_texture(t,b.pos+tofs) + + +func _process(delta): + var width = get_viewport_rect().size.x*2.0 + var mat = Matrix32() + for b in bullets: + b.pos.x-=b.speed*delta + if (b.pos.x < -30): + b.pos.x+=width + mat.o=b.pos + + Physics2DServer.body_set_state(b.body,Physics2DServer.BODY_STATE_TRANSFORM,mat) + + update() + + +func _ready(): + + shape = Physics2DServer.shape_create(Physics2DServer.SHAPE_CIRCLE) + Physics2DServer.shape_set_data(shape,8) #radius + + for i in range(BULLET_COUNT): + var b = Bullet.new() + b.speed=rand_range(SPEED_MIN,SPEED_MAX) + b.body = Physics2DServer.body_create(Physics2DServer.BODY_MODE_KINEMATIC) + Physics2DServer.body_set_space(b.body,get_world_2d().get_space()) + Physics2DServer.body_add_shape(b.body,shape) + + b.pos = Vector2( get_viewport_rect().size * Vector2(randf()*2.0,randf()) ) #twice as long + b.pos.x += get_viewport_rect().size.x # start outside + var mat = Matrix32() + mat.o=b.pos + Physics2DServer.body_set_state(b.body,Physics2DServer.BODY_STATE_TRANSFORM,mat) + + bullets.append(b) + + + set_process(true) + + +func _exit_tree(): + for b in bullets: + Physics2DServer.free_rid(b.body) + + Physics2DServer.free_rid(shape) + # Initalization here + bullets.clear() + + pass + + diff --git a/demos/2d/shower_of_bullets/engine.cfg b/demos/2d/shower_of_bullets/engine.cfg new file mode 100644 index 0000000000..cad5751985 --- /dev/null +++ b/demos/2d/shower_of_bullets/engine.cfg @@ -0,0 +1,16 @@ +[application] + +name="Bullet Shower" +main_scene="res://shower.scn" +icon="res://icon.png" + +[display] + +width=1024 +height=600 +resizable=true +stretch_aspect="keep" + +[physics_2d] + +cell_size=64 diff --git a/demos/2d/shower_of_bullets/face_happy.png b/demos/2d/shower_of_bullets/face_happy.png Binary files differnew file mode 100644 index 0000000000..6ed643b62d --- /dev/null +++ b/demos/2d/shower_of_bullets/face_happy.png diff --git a/demos/2d/shower_of_bullets/face_sad.png b/demos/2d/shower_of_bullets/face_sad.png Binary files differnew file mode 100644 index 0000000000..d6318b20a3 --- /dev/null +++ b/demos/2d/shower_of_bullets/face_sad.png diff --git a/demos/2d/shower_of_bullets/icon.png b/demos/2d/shower_of_bullets/icon.png Binary files differnew file mode 100644 index 0000000000..432c74a5a3 --- /dev/null +++ b/demos/2d/shower_of_bullets/icon.png diff --git a/demos/2d/shower_of_bullets/shower.gd b/demos/2d/shower_of_bullets/shower.gd new file mode 100644 index 0000000000..bba8431764 --- /dev/null +++ b/demos/2d/shower_of_bullets/shower.gd @@ -0,0 +1,32 @@ + +extends Node2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +var touching=0 + +func _input(ev): + + if (ev.type==InputEvent.MOUSE_MOTION): + get_node("player").set_pos(ev.pos-Vector2(0,16)) + + +func _on_player_body_enter_shape( body_id, body, body_shape, area_shape ): + + touching+=1 + if (touching==1): + get_node("player/sprite").set_frame(1) + + +func _on_player_body_exit_shape( body_id, body, body_shape, area_shape ): + + touching-=1 + if (touching==0): + get_node("player/sprite").set_frame(0) + + +func _ready(): + set_process_input(true) + pass diff --git a/demos/2d/shower_of_bullets/shower.scn b/demos/2d/shower_of_bullets/shower.scn Binary files differnew file mode 100644 index 0000000000..648888d099 --- /dev/null +++ b/demos/2d/shower_of_bullets/shower.scn diff --git a/demos/2d/sprite_shaders/cubio.png b/demos/2d/sprite_shaders/cubio.png Binary files differnew file mode 100644 index 0000000000..6f76220225 --- /dev/null +++ b/demos/2d/sprite_shaders/cubio.png diff --git a/demos/2d/sprite_shaders/engine.cfg b/demos/2d/sprite_shaders/engine.cfg new file mode 100644 index 0000000000..09f9a59566 --- /dev/null +++ b/demos/2d/sprite_shaders/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="2D Shaders for Sprites" +main_scene="res://sprite_shaders.scn" diff --git a/demos/2d/sprite_shaders/sprite_shaders.scn b/demos/2d/sprite_shaders/sprite_shaders.scn Binary files differnew file mode 100644 index 0000000000..7c36f2137c --- /dev/null +++ b/demos/2d/sprite_shaders/sprite_shaders.scn diff --git a/demos/2d/texscreen/OpenCV_Chessboard.png b/demos/2d/texscreen/OpenCV_Chessboard.png Binary files differnew file mode 100644 index 0000000000..31b7f8ccd8 --- /dev/null +++ b/demos/2d/texscreen/OpenCV_Chessboard.png diff --git a/demos/2d/texscreen/bubble.png b/demos/2d/texscreen/bubble.png Binary files differnew file mode 100644 index 0000000000..021abba601 --- /dev/null +++ b/demos/2d/texscreen/bubble.png diff --git a/demos/2d/texscreen/bubbles.gd b/demos/2d/texscreen/bubbles.gd new file mode 100644 index 0000000000..2ee227a928 --- /dev/null +++ b/demos/2d/texscreen/bubbles.gd @@ -0,0 +1,17 @@ + +extends Control + +# member variables here, example: +# var a=2 +# var b="textvar" + +const MAX_BUBBLES=10 + +func _ready(): + # Initialization here + for i in range(MAX_BUBBLES): + var bubble = preload("res://lens.scn").instance() + add_child(bubble) + pass + + diff --git a/demos/2d/texscreen/bubbles.scn b/demos/2d/texscreen/bubbles.scn Binary files differnew file mode 100644 index 0000000000..779cba6930 --- /dev/null +++ b/demos/2d/texscreen/bubbles.scn diff --git a/demos/2d/texscreen/burano.png b/demos/2d/texscreen/burano.png Binary files differnew file mode 100644 index 0000000000..6eec09d585 --- /dev/null +++ b/demos/2d/texscreen/burano.png diff --git a/demos/2d/texscreen/engine.cfg b/demos/2d/texscreen/engine.cfg new file mode 100644 index 0000000000..58193c8c4a --- /dev/null +++ b/demos/2d/texscreen/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="Glass Bubbles (Texscreen)" +main_scene="res://bubbles.scn" diff --git a/demos/2d/texscreen/lens.gd b/demos/2d/texscreen/lens.gd new file mode 100644 index 0000000000..2ccbfba497 --- /dev/null +++ b/demos/2d/texscreen/lens.gd @@ -0,0 +1,37 @@ + +extends BackBufferCopy + +# member variables here, example: +# var a=2 +# var b="textvar" +const MOTION_SPEED=150 + +var vsize; +var dir; + +func _process(delta): + var pos = get_pos() + dir * delta * MOTION_SPEED + + if (pos.x<0): + dir.x=abs(dir.x) + elif (pos.x>vsize.x): + dir.x=-abs(dir.x) + + if (pos.y<0): + dir.y=abs(dir.y) + elif (pos.y>vsize.y): + dir.y=-abs(dir.y) + + set_pos(pos) + +func _ready(): + vsize = get_viewport_rect().size + var pos = vsize * Vector2(randf(),randf()); + set_pos(pos); + dir = Vector2(randf()*2.0-1,randf()*2.0-1).normalized() + set_process(true) + + # Initialization here + pass + + diff --git a/demos/2d/texscreen/lens.scn b/demos/2d/texscreen/lens.scn Binary files differnew file mode 100644 index 0000000000..5c6f8b7af8 --- /dev/null +++ b/demos/2d/texscreen/lens.scn diff --git a/demos/3d/kinematic_char/cubelib.res b/demos/3d/kinematic_char/cubelib.res Binary files differindex 66b999d78d..27f2b9b3bd 100644 --- a/demos/3d/kinematic_char/cubelib.res +++ b/demos/3d/kinematic_char/cubelib.res diff --git a/demos/3d/kinematic_char/cubio.gd b/demos/3d/kinematic_char/cubio.gd index 6f12e39db7..a1baa78a0c 100644 --- a/demos/3d/kinematic_char/cubio.gd +++ b/demos/3d/kinematic_char/cubio.gd @@ -54,7 +54,7 @@ func _fixed_process(delta): var original_vel = vel - var floor_velocity=Vector2() + var floor_velocity=Vector3() var attempts=4 diff --git a/demos/3d/kinematic_char/level.scn b/demos/3d/kinematic_char/level.scn Binary files differindex a276fe22e1..7ccb2430c1 100644 --- a/demos/3d/kinematic_char/level.scn +++ b/demos/3d/kinematic_char/level.scn diff --git a/demos/3d/mousepick_test/mousepick.gd b/demos/3d/mousepick_test/mousepick.gd index cf3d9f1e4e..c96091b650 100644 --- a/demos/3d/mousepick_test/mousepick.gd +++ b/demos/3d/mousepick_test/mousepick.gd @@ -9,7 +9,7 @@ var gray_mat = FixedMaterial.new() var selected=false -func _input_event(event,pos,normal,shape): +func _input_event(camera,event,pos,normal,shape): if (event.type==InputEvent.MOUSE_BUTTON and event.pressed): if (not selected): get_node("mesh").set_material_override(gray_mat) diff --git a/demos/3d/navmesh/engine.cfg b/demos/3d/navmesh/engine.cfg new file mode 100644 index 0000000000..30af6ce5a5 --- /dev/null +++ b/demos/3d/navmesh/engine.cfg @@ -0,0 +1,9 @@ +[application] + +name="Navmesh Demo" +main_scene="res://navmesh.scn" +icon="res://icon.png" + +[rasterizer] + +shadow_filter=3 diff --git a/demos/3d/navmesh/navmesh.gd b/demos/3d/navmesh/navmesh.gd new file mode 100644 index 0000000000..b5dc488ec3 --- /dev/null +++ b/demos/3d/navmesh/navmesh.gd @@ -0,0 +1,110 @@ + +extends Navigation + +# member variables here, example: +# var a=2 +# var b="textvar" + +const SPEED=4.0 + +var camrot=0.0 + +var begin=Vector3() +var end=Vector3() +var m = FixedMaterial.new() + +var path=[] + +func _process(delta): + + + if (path.size()>1): + + var to_walk = delta*SPEED + var to_watch = Vector3(0,1,0) + while(to_walk>0 and path.size()>=2): + var pfrom = path[path.size()-1] + var pto = path[path.size()-2] + to_watch = (pto - pfrom).normalized() + var d = pfrom.distance_to(pto) + if (d<=to_walk): + path.remove(path.size()-1) + to_walk-=d + else: + path[path.size()-1] = pfrom.linear_interpolate(pto,to_walk/d) + to_walk=0 + + var atpos = path[path.size()-1] + var atdir = to_watch + atdir.y=0 + + var t = Transform() + t.origin=atpos + t=t.looking_at(atpos+atdir,Vector3(0,1,0)) + get_node("robot_base").set_transform(t) + + if (path.size()<2): + path=[] + set_process(false) + + else: + set_process(false) + +var draw_path=false + +func _update_path(): + + var p = get_simple_path(begin,end,true) + path=Array(p) # Vector3array to complex to use, convert to regular array + path.invert() + set_process(true) + + if (draw_path): + var im = get_node("draw") + im.set_material_override(m) + im.clear() + im.begin(Mesh.PRIMITIVE_POINTS,null) + im.add_vertex(begin) + im.add_vertex(end) + im.end() + im.begin(Mesh.PRIMITIVE_LINE_STRIP,null) + for x in p: + im.add_vertex(x) + im.end() + +func _input(ev): + + if (ev.type==InputEvent.MOUSE_BUTTON and ev.button_index==BUTTON_LEFT and ev.pressed): + + var from = get_node("cambase/Camera").project_ray_origin(ev.pos) + var to = from+get_node("cambase/Camera").project_ray_normal(ev.pos)*100 + var p = get_closest_point_to_segment(from,to) + + begin=get_closest_point(get_node("robot_base").get_translation()) + end=p + + _update_path() + + if (ev.type==InputEvent.MOUSE_MOTION): + if (ev.button_mask&BUTTON_MASK_MIDDLE): + + camrot+=ev.relative_x*0.005 + get_node("cambase").set_rotation(Vector3(0,camrot,0)) + print("camrot ", camrot) + + + +func _ready(): + # Initalization here + set_process_input(true) + m.set_line_width(3) + m.set_point_size(3) + m.set_fixed_flag(FixedMaterial.FLAG_USE_POINT_SIZE,true) + m.set_flag(Material.FLAG_UNSHADED,true) + #begin = get_closest_point(get_node("start").get_translation()) + #end = get_closest_point(get_node("end").get_translation()) + #call_deferred("_update_path") + + pass + + diff --git a/demos/3d/navmesh/navmesh.scn b/demos/3d/navmesh/navmesh.scn Binary files differnew file mode 100644 index 0000000000..73df340b1e --- /dev/null +++ b/demos/3d/navmesh/navmesh.scn diff --git a/demos/3d/navmesh/particle.png b/demos/3d/navmesh/particle.png Binary files differnew file mode 100644 index 0000000000..18851c8c9d --- /dev/null +++ b/demos/3d/navmesh/particle.png diff --git a/demos/3d/platformer/stage.xml b/demos/3d/platformer/stage.xml index f3a5caffa9..37a11068c9 100644 --- a/demos/3d/platformer/stage.xml +++ b/demos/3d/platformer/stage.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<resource_file type="PackedScene" subresource_count="7" version="1.0" version_name="Godot Engine v1.0.3917-beta1"> +<resource_file type="PackedScene" subresource_count="7" version="1.0" version_name="Godot Engine v1.0.stable.custom_build"> <ext_resource path="res://sb.cube" type="CubeMap"></ext_resource> <ext_resource path="res://tiles.res" type="MeshLibrary"></ext_resource> <ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource> - <ext_resource path="res://coin.scn" type="PackedScene"></ext_resource> <ext_resource path="res://player.xml" type="PackedScene"></ext_resource> + <ext_resource path="res://coin.scn" type="PackedScene"></ext_resource> <resource type="Environment" path="local://1"> <bool name="ambient_light/enabled"> True </bool> <color name="ambient_light/color"> 0, 0.409429, 0.596681, 1 </color> @@ -29,8 +29,9 @@ <real name="dof_blur/begin"> 100 </real> <real name="dof_blur/range"> 10 </real> <bool name="hdr/enabled"> True </bool> + <int name="hdr/tonemapper"> 0 </int> <real name="hdr/exposure"> 0.4 </real> - <real name="hdr/scalar"> 1 </real> + <real name="hdr/white"> 1 </real> <real name="hdr/glow_treshold"> 0.9 </real> <real name="hdr/glow_scale"> 0.5 </real> <real name="hdr/min_luminance"> 0.4 </real> @@ -52,11 +53,12 @@ <main_resource> <dictionary name="_bundled" shared="false"> <string> "names" </string> - <string_array len="92"> + <string_array len="94"> <string> "world" </string> <string> "Spatial" </string> <string> "_import_path" </string> <string> "_import_transform" </string> + <string> "visibility/visible" </string> <string> "__meta__" </string> <string> "GridMap" </string> <string> "theme/theme" </string> @@ -73,6 +75,7 @@ <string> "transform/local" </string> <string> "layers" </string> <string> "params/enabled" </string> + <string> "params/editor_only" </string> <string> "params/bake_mode" </string> <string> "params/energy" </string> <string> "colors/diffuse" </string> @@ -153,9 +156,10 @@ <string> "node_count" </string> <int> 55 </int> <string> "variants" </string> - <array len="79" shared="false"> + <array len="82" shared="false"> <node_path> "" </node_path> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 </transform> + <bool> True </bool> <dictionary shared="false"> <string> "__editor_plugin_states__" </string> <dictionary shared="false"> @@ -174,23 +178,27 @@ </dictionary> <string> "3D" </string> <dictionary shared="false"> + <string> "deflight_rot_y" </string> + <real> 0.628319 </real> <string> "zfar" </string> <real> 500 </real> <string> "fov" </string> - <real> 400 </real> + <real> 179 </real> <string> "viewports" </string> <array len="4" shared="false"> <dictionary shared="false"> <string> "distance" </string> - <real> 0.261354 </real> + <real> 9.009935 </real> <string> "x_rot" </string> <real> 0.458294 </real> <string> "y_rot" </string> <real> -1.2 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> + <string> "listener" </string> + <bool> True </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 13.4535, 5.75047, 13.8175 </vector3> </dictionary> @@ -201,10 +209,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -215,10 +225,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -229,10 +241,12 @@ <real> 0 </real> <string> "y_rot" </string> <real> 0 </real> - <string> "use_orthogonal" </string> + <string> "listener" </string> <bool> False </bool> <string> "use_environment" </string> <bool> False </bool> + <string> "use_orthogonal" </string> + <bool> False </bool> <string> "pos" </string> <vector3> 0, 0, 0 </vector3> </dictionary> @@ -241,12 +255,18 @@ <int> 1 </int> <string> "default_light" </string> <bool> False </bool> + <string> "ambient_light_color" </string> + <color> 0.15, 0.15, 0.15, 1 </color> <string> "show_grid" </string> <bool> True </bool> <string> "show_origin" </string> <bool> True </bool> <string> "znear" </string> <real> 0.1 </real> + <string> "default_srgb" </string> + <bool> False </bool> + <string> "deflight_rot_x" </string> + <real> 0.942478 </real> </dictionary> </dictionary> <string> "__editor_run_settings__" </string> @@ -263,7 +283,6 @@ <bool> False </bool> <real> 2 </real> <int> 4 </int> - <bool> True </bool> <real> 1.001 </real> <dictionary shared="false"> <string> "cells" </string> @@ -295,6 +314,112 @@ </dictionary> <resource resource_type="PackedScene" path="res://coin.scn"> </resource> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 5.24675 </transform> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 0 </int> + <string> "sources" </string> + <array len="1" shared="false"> + <string> "res://coin.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "zoom" </string> + <real> 1 </real> + <string> "ofs" </string> + <vector2> 1, 1 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 400 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 1.361845 </real> + <string> "x_rot" </string> + <real> 0.0125 </real> + <string> "y_rot" </string> + <real> 12.050008 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> -0.00892573, 0.51052, -0.216081 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "3D" </string> + </dictionary> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 7.24675 </transform> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5311, 2.85075, 5.24675 </transform> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5311, 2.85075, 7.24675 </transform> @@ -340,14 +465,230 @@ <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 4.60515, 25.1836 </transform> <resource resource_type="PackedScene" path="res://enemy.scn"> </resource> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.3062, 5.40827, 5.96938 </transform> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 0 </int> + <string> "sources" </string> + <array len="2" shared="false"> + <string> "res://enemy.gd" </string> + <string> "res://player.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "zoom" </string> + <real> 1 </real> + <string> "ofs" </string> + <vector2> 1, 1 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 400 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 7.403724 </real> + <string> "x_rot" </string> + <real> 0.25 </real> + <string> "y_rot" </string> + <real> 3.312502 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0.898236, 0.953557, 0.742913 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "Script" </string> + </dictionary> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.1292, 5.40827, 17.1396 </transform> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.1292, 5.40827, 32.6128 </transform> <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 55.5702, 5.40827, 32.6128 </transform> <resource resource_type="PackedScene" path="res://player.xml"> </resource> <transform> 0.0160676, 0, -0.999871, 0, 1, 0, 0.999871, 0, 0.0160676, 8.50167, 4.15811, 15.9334 </transform> + <dictionary shared="false"> + <string> "__editor_plugin_states__" </string> + <dictionary shared="false"> + <string> "Script" </string> + <dictionary shared="false"> + <string> "current" </string> + <int> 1 </int> + <string> "sources" </string> + <array len="2" shared="false"> + <string> "res://follow_camera.gd" </string> + <string> "res://player.gd" </string> + </array> + </dictionary> + <string> "2D" </string> + <dictionary shared="false"> + <string> "pixel_snap" </string> + <bool> False </bool> + <string> "zoom" </string> + <real> 1 </real> + <string> "ofs" </string> + <vector2> -241, -19 </vector2> + </dictionary> + <string> "3D" </string> + <dictionary shared="false"> + <string> "fov" </string> + <real> 400 </real> + <string> "zfar" </string> + <real> 500 </real> + <string> "viewports" </string> + <array len="4" shared="false"> + <dictionary shared="false"> + <string> "distance" </string> + <real> 2.161076 </real> + <string> "x_rot" </string> + <real> 0.520797 </real> + <string> "y_rot" </string> + <real> 26.741669 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> -0.415811, 0.486899, 0.089334 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + <dictionary shared="false"> + <string> "distance" </string> + <real> 4 </real> + <string> "x_rot" </string> + <real> 0 </real> + <string> "y_rot" </string> + <real> 0 </real> + <string> "use_orthogonal" </string> + <bool> False </bool> + <string> "use_environment" </string> + <bool> False </bool> + <string> "pos" </string> + <vector3> 0, 0, 0 </vector3> + </dictionary> + </array> + <string> "viewport_mode" </string> + <int> 1 </int> + <string> "default_light" </string> + <bool> True </bool> + <string> "show_grid" </string> + <bool> True </bool> + <string> "znear" </string> + <real> 0.1 </real> + <string> "show_origin" </string> + <bool> True </bool> + </dictionary> + </dictionary> + <string> "__editor_run_settings__" </string> + <dictionary shared="false"> + <string> "custom_args" </string> + <string> "-l $scene" </string> + <string> "run_mode" </string> + <int> 0 </int> + </dictionary> + <string> "__editor_plugin_screen__" </string> + <string> "3D" </string> + </dictionary> </array> <string> "nodes" </string> - <int_array len="569"> -1, -1, 1, 0, -1, 3, 2, 0, 3, 1, 4, 2, 0, 0, 0, 5, 5, -1, 13, 2, 0, 3, 1, 6, 3, 7, 4, 8, 4, 9, 5, 10, 6, 11, 7, 12, 7, 13, 7, 14, 8, 15, 9, 4, 10, 0, 0, 0, 16, 16, -1, 21, 2, 0, 3, 1, 17, 11, 18, 12, 19, 7, 20, 13, 21, 14, 22, 15, 23, 15, 24, 7, 25, 16, 26, 17, 27, 18, 28, 19, 29, 20, 30, 21, 31, 13, 32, 22, 33, 23, 34, 24, 35, 5, 0, 0, 0, 37, 36, -1, 3, 2, 0, 3, 1, 36, 25, 0, 0, 0, 39, 38, -1, 2, 2, 0, 4, 26, 0, 4, 0, 41, 40, 27, 1, 17, 28, 0, 4, 0, 41, 42, 27, 1, 17, 29, 0, 4, 0, 41, 43, 27, 1, 17, 30, 0, 4, 0, 41, 44, 27, 1, 17, 31, 0, 4, 0, 41, 45, 27, 1, 17, 32, 0, 4, 0, 41, 46, 27, 1, 17, 33, 0, 4, 0, 41, 47, 27, 1, 17, 34, 0, 4, 0, 41, 48, 27, 1, 17, 35, 0, 4, 0, 41, 49, 27, 1, 17, 36, 0, 4, 0, 41, 50, 27, 1, 17, 37, 0, 4, 0, 41, 51, 27, 1, 17, 38, 0, 4, 0, 41, 52, 27, 1, 17, 39, 0, 4, 0, 41, 53, 27, 1, 17, 40, 0, 4, 0, 41, 54, 27, 1, 17, 41, 0, 4, 0, 41, 55, 27, 1, 17, 42, 0, 4, 0, 41, 56, 27, 1, 17, 43, 0, 4, 0, 41, 57, 27, 1, 17, 44, 0, 4, 0, 41, 58, 27, 1, 17, 45, 0, 4, 0, 41, 59, 27, 1, 17, 46, 0, 4, 0, 41, 60, 27, 1, 17, 47, 0, 4, 0, 41, 61, 27, 1, 17, 48, 0, 4, 0, 41, 62, 27, 1, 17, 49, 0, 4, 0, 41, 63, 27, 1, 17, 50, 0, 4, 0, 41, 64, 27, 1, 17, 51, 0, 4, 0, 41, 65, 27, 1, 17, 52, 0, 4, 0, 41, 66, 27, 1, 17, 53, 0, 4, 0, 41, 67, 27, 1, 17, 54, 0, 4, 0, 41, 68, 27, 1, 17, 55, 0, 4, 0, 41, 69, 27, 1, 17, 56, 0, 4, 0, 41, 70, 27, 1, 17, 57, 0, 4, 0, 41, 71, 27, 1, 17, 58, 0, 4, 0, 41, 72, 27, 1, 17, 59, 0, 4, 0, 41, 73, 27, 1, 17, 60, 0, 4, 0, 41, 74, 27, 1, 17, 61, 0, 4, 0, 41, 75, 27, 1, 17, 62, 0, 4, 0, 41, 76, 27, 1, 17, 63, 0, 4, 0, 41, 77, 27, 1, 17, 64, 0, 4, 0, 41, 78, 27, 1, 17, 65, 0, 4, 0, 41, 79, 27, 1, 17, 66, 0, 4, 0, 41, 80, 27, 1, 17, 67, 0, 4, 0, 41, 81, 27, 1, 17, 68, 0, 4, 0, 41, 82, 27, 1, 17, 69, 0, 4, 0, 41, 83, 27, 1, 17, 70, 0, 4, 0, 41, 84, 27, 1, 17, 71, 0, 0, 0, 39, 85, -1, 1, 2, 0, 0, 49, 0, 87, 86, 72, 1, 17, 73, 0, 49, 0, 87, 88, 72, 1, 17, 74, 0, 49, 0, 87, 89, 72, 1, 17, 75, 0, 49, 0, 87, 90, 72, 1, 17, 76, 0, 0, 0, 87, 91, 77, 1, 17, 78, 0 </int_array> + <int_array len="873"> -1, -1, 1, 0, -1, 4, 2, 0, 3, 1, 4, 2, 5, 3, 0, 0, 0, 6, 6, -1, 14, 2, 0, 3, 1, 4, 2, 7, 4, 8, 5, 9, 5, 10, 6, 11, 7, 12, 2, 13, 2, 14, 2, 15, 8, 16, 9, 5, 10, 0, 0, 0, 17, 17, -1, 23, 2, 0, 3, 1, 18, 11, 4, 2, 19, 12, 20, 2, 21, 5, 22, 13, 23, 14, 24, 15, 25, 15, 26, 2, 27, 16, 28, 17, 29, 18, 30, 19, 31, 20, 32, 21, 33, 13, 34, 22, 35, 23, 36, 24, 37, 6, 0, 0, 0, 39, 38, -1, 4, 2, 0, 3, 1, 4, 2, 38, 25, 0, 0, 0, 41, 40, -1, 2, 2, 0, 5, 26, 0, 4, 0, 43, 42, 27, 4, 2, 0, 3, 1, 18, 28, 5, 29, 0, 4, 0, 43, 44, 27, 4, 2, 0, 3, 1, 18, 30, 5, 29, 0, 4, 0, 43, 45, 27, 4, 2, 0, 3, 1, 18, 31, 5, 29, 0, 4, 0, 43, 46, 27, 4, 2, 0, 3, 1, 18, 32, 5, 29, 0, 4, 0, 43, 47, 27, 4, 2, 0, 3, 1, 18, 33, 5, 29, 0, 4, 0, 43, 48, 27, 4, 2, 0, 3, 1, 18, 34, 5, 29, 0, 4, 0, 43, 49, 27, 4, 2, 0, 3, 1, 18, 35, 5, 29, 0, 4, 0, 43, 50, 27, 4, 2, 0, 3, 1, 18, 36, 5, 29, 0, 4, 0, 43, 51, 27, 4, 2, 0, 3, 1, 18, 37, 5, 29, 0, 4, 0, 43, 52, 27, 4, 2, 0, 3, 1, 18, 38, 5, 29, 0, 4, 0, 43, 53, 27, 4, 2, 0, 3, 1, 18, 39, 5, 29, 0, 4, 0, 43, 54, 27, 4, 2, 0, 3, 1, 18, 40, 5, 29, 0, 4, 0, 43, 55, 27, 4, 2, 0, 3, 1, 18, 41, 5, 29, 0, 4, 0, 43, 56, 27, 4, 2, 0, 3, 1, 18, 42, 5, 29, 0, 4, 0, 43, 57, 27, 4, 2, 0, 3, 1, 18, 43, 5, 29, 0, 4, 0, 43, 58, 27, 4, 2, 0, 3, 1, 18, 44, 5, 29, 0, 4, 0, 43, 59, 27, 4, 2, 0, 3, 1, 18, 45, 5, 29, 0, 4, 0, 43, 60, 27, 4, 2, 0, 3, 1, 18, 46, 5, 29, 0, 4, 0, 43, 61, 27, 4, 2, 0, 3, 1, 18, 47, 5, 29, 0, 4, 0, 43, 62, 27, 4, 2, 0, 3, 1, 18, 48, 5, 29, 0, 4, 0, 43, 63, 27, 4, 2, 0, 3, 1, 18, 49, 5, 29, 0, 4, 0, 43, 64, 27, 4, 2, 0, 3, 1, 18, 50, 5, 29, 0, 4, 0, 43, 65, 27, 4, 2, 0, 3, 1, 18, 51, 5, 29, 0, 4, 0, 43, 66, 27, 4, 2, 0, 3, 1, 18, 52, 5, 29, 0, 4, 0, 43, 67, 27, 4, 2, 0, 3, 1, 18, 53, 5, 29, 0, 4, 0, 43, 68, 27, 4, 2, 0, 3, 1, 18, 54, 5, 29, 0, 4, 0, 43, 69, 27, 4, 2, 0, 3, 1, 18, 55, 5, 29, 0, 4, 0, 43, 70, 27, 4, 2, 0, 3, 1, 18, 56, 5, 29, 0, 4, 0, 43, 71, 27, 4, 2, 0, 3, 1, 18, 57, 5, 29, 0, 4, 0, 43, 72, 27, 4, 2, 0, 3, 1, 18, 58, 5, 29, 0, 4, 0, 43, 73, 27, 4, 2, 0, 3, 1, 18, 59, 5, 29, 0, 4, 0, 43, 74, 27, 4, 2, 0, 3, 1, 18, 60, 5, 29, 0, 4, 0, 43, 75, 27, 4, 2, 0, 3, 1, 18, 61, 5, 29, 0, 4, 0, 43, 76, 27, 4, 2, 0, 3, 1, 18, 62, 5, 29, 0, 4, 0, 43, 77, 27, 4, 2, 0, 3, 1, 18, 63, 5, 29, 0, 4, 0, 43, 78, 27, 4, 2, 0, 3, 1, 18, 64, 5, 29, 0, 4, 0, 43, 79, 27, 4, 2, 0, 3, 1, 18, 65, 5, 29, 0, 4, 0, 43, 80, 27, 4, 2, 0, 3, 1, 18, 66, 5, 29, 0, 4, 0, 43, 81, 27, 4, 2, 0, 3, 1, 18, 67, 5, 29, 0, 4, 0, 43, 82, 27, 4, 2, 0, 3, 1, 18, 68, 5, 29, 0, 4, 0, 43, 83, 27, 4, 2, 0, 3, 1, 18, 69, 5, 29, 0, 4, 0, 43, 84, 27, 4, 2, 0, 3, 1, 18, 70, 5, 29, 0, 4, 0, 43, 85, 27, 4, 2, 0, 3, 1, 18, 71, 5, 29, 0, 4, 0, 43, 86, 27, 4, 2, 0, 3, 1, 18, 72, 5, 29, 0, 0, 0, 41, 87, -1, 1, 2, 0, 0, 49, 0, 89, 88, 73, 4, 2, 0, 3, 1, 18, 74, 5, 75, 0, 49, 0, 89, 90, 73, 4, 2, 0, 3, 1, 18, 76, 5, 75, 0, 49, 0, 89, 91, 73, 4, 2, 0, 3, 1, 18, 77, 5, 75, 0, 49, 0, 89, 92, 73, 4, 2, 0, 3, 1, 18, 78, 5, 75, 0, 0, 0, 89, 93, 79, 4, 2, 0, 3, 1, 18, 80, 5, 81, 0 </int_array> <string> "conns" </string> <int_array len="0"> </int_array> </dictionary> diff --git a/demos/3d/platformer/tiles.res b/demos/3d/platformer/tiles.res Binary files differindex 53534788a1..d4fb779ff1 100644 --- a/demos/3d/platformer/tiles.res +++ b/demos/3d/platformer/tiles.res diff --git a/demos/3d/truck_town/crane.scn b/demos/3d/truck_town/crane.scn Binary files differindex 080bd8ea17..2c4645af69 100644 --- a/demos/3d/truck_town/crane.scn +++ b/demos/3d/truck_town/crane.scn diff --git a/demos/gui/drag_and_drop/drag_and_drop.scn b/demos/gui/drag_and_drop/drag_and_drop.scn Binary files differnew file mode 100644 index 0000000000..94a25cc53e --- /dev/null +++ b/demos/gui/drag_and_drop/drag_and_drop.scn diff --git a/demos/gui/drag_and_drop/drag_drop_script.gd b/demos/gui/drag_and_drop/drag_drop_script.gd new file mode 100644 index 0000000000..21a737ce1a --- /dev/null +++ b/demos/gui/drag_and_drop/drag_drop_script.gd @@ -0,0 +1,24 @@ + +extends ColorPickerButton + + +#virtual function +func get_drag_data(pos): + + #use another colorpicker as drag preview + var cpb = ColorPickerButton.new() + cpb.set_color( get_color() ) + cpb.set_size(Vector2(50,50)) + set_drag_preview(cpb) + #return color as drag data + return get_color() + +#virtual function +func can_drop_data(pos, data): + return typeof(data)==TYPE_COLOR + +#virtual function +func drop_data(pos, data): + set_color(data) + + diff --git a/demos/gui/drag_and_drop/engine.cfg b/demos/gui/drag_and_drop/engine.cfg new file mode 100644 index 0000000000..448939c61d --- /dev/null +++ b/demos/gui/drag_and_drop/engine.cfg @@ -0,0 +1,4 @@ +[application] + +name="Drag & Drop (GUI)" +main_scene="res://drag_and_drop.scn" diff --git a/demos/misc/autoload/global.gd b/demos/misc/autoload/global.gd index d9fa308a2f..a0415c6ee0 100644 --- a/demos/misc/autoload/global.gd +++ b/demos/misc/autoload/global.gd @@ -12,12 +12,12 @@ func goto_scene(scene): #instance the new scene current_scene = s.instance() #add it to the active scene, as child of root - get_scene().get_root().add_child(current_scene) + get_tree().get_root().add_child(current_scene) func _ready(): # get the current scene # it is always the last child of root, # after the autoloaded nodes - var root = get_scene().get_root() + var root = get_tree().get_root() current_scene = root.get_child( root.get_child_count() -1 ) diff --git a/demos/misc/pause/spinpause.gd b/demos/misc/pause/spinpause.gd index c21c13b4e1..1b8f8388f0 100644 --- a/demos/misc/pause/spinpause.gd +++ b/demos/misc/pause/spinpause.gd @@ -5,11 +5,11 @@ extends Spatial func _on_pause_pressed(): get_node("pause_popup").set_exclusive(true) get_node("pause_popup").popup() - get_scene().set_pause(true) + get_tree().set_pause(true) func _on_unpause_pressed(): get_node("pause_popup").hide() - get_scene().set_pause(false) + get_tree().set_pause(false) diff --git a/demos/misc/tween/icon.png b/demos/misc/tween/icon.png Binary files differnew file mode 100644 index 0000000000..3e991fcc29 --- /dev/null +++ b/demos/misc/tween/icon.png diff --git a/demos/misc/tween/main.gd b/demos/misc/tween/main.gd index 364651c827..a0106a7682 100644 --- a/demos/misc/tween/main.gd +++ b/demos/misc/tween/main.gd @@ -112,8 +112,8 @@ func reset_tween(): tween.interpolate_property(sprite, "transform/rot", 360, 0, 2, state.trans, state.eases, 2) if get_node("modes/callback").is_pressed(): - tween.interpolate_callback(self, "on_callback", 0.5, "0.5 second's after") - tween.interpolate_callback(self, "on_callback", 1.2, "1.2 second's after") + tween.interpolate_callback(self, 0.5, "on_callback", "0.5 second's after") + tween.interpolate_callback(self, 0.2, "on_callback", "1.2 second's after") if get_node("modes/follow").is_pressed(): follow.show() diff --git a/demos/misc/udp_chat/chat.gd b/demos/misc/udp_chat/chat.gd new file mode 100644 index 0000000000..3270eebbfe --- /dev/null +++ b/demos/misc/udp_chat/chat.gd @@ -0,0 +1,72 @@ + +extends Panel + +# Really simple UDP chat client, not intended as a chat example!! +# (UDP can lose packets and you won't normally find out, so don't do a chat this way) +# This is just a demo that shows how to use the UDP class. + +var udp = PacketPeerUDP.new() + +func _process(delta): + + if (not udp.is_listening()): + return + + while(udp.get_available_packet_count()>0): + var packet = udp.get_var() + if (typeof(packet)==TYPE_STRING): + var host = udp.get_packet_ip() + var port = udp.get_packet_port() + get_node("chat/text").add_text("("+host+":"+str(port)+":) "+packet) + get_node("chat/text").newline() + + + +func _ready(): + # Initalization here + get_node("chat").add_style_override("panel",get_stylebox("bg","Tree")) + set_process(true) + + + +func send_message(text): + if (udp.is_listening()): + udp.put_var(text) + + +func _on_connect_toggled( pressed ): + + + if (pressed): + var err = udp.listen( get_node("listen_port").get_val() ) + if (err!=OK): + get_node("status").set_text("Error:\nCan't Listen.") + get_node("connect").set_pressed(false) + else: + get_node("status").set_text("Connected.") + get_node("connect").set_text("Disconnect") + err = udp.set_send_address(get_node("remote_host").get_text(),get_node("remote_port").get_val()) + if (err!=OK): + get_node("status").set_text("Error:\nCan't Resolve.") + get_node("connect").set_pressed(false) + else: + send_message("* "+get_node("user_name").get_text()+" entered chat.") + else: + + udp.close() + get_node("status").set_text("Disconnected.") + get_node("connect").set_text("Connect") + + + + +func _on_entry_line_text_entered( text ): + _on_entry_button_pressed(); + +func _on_entry_button_pressed(): + var msg = get_node("entry_line").get_text() + if (msg==""): + return + send_message(get_node("user_name").get_text()+"> "+msg) + + get_node("entry_line").set_text("") diff --git a/demos/misc/udp_chat/chat.scn b/demos/misc/udp_chat/chat.scn Binary files differnew file mode 100644 index 0000000000..efa4b799a0 --- /dev/null +++ b/demos/misc/udp_chat/chat.scn diff --git a/demos/misc/udp_chat/engine.cfg b/demos/misc/udp_chat/engine.cfg new file mode 100644 index 0000000000..584841ea83 --- /dev/null +++ b/demos/misc/udp_chat/engine.cfg @@ -0,0 +1,5 @@ +[application] + +name="UDP Chat" +main_scene="res://chat.scn" +icon="res://icon.png" diff --git a/demos/misc/udp_chat/icon.png b/demos/misc/udp_chat/icon.png Binary files differnew file mode 100644 index 0000000000..db6e21cce1 --- /dev/null +++ b/demos/misc/udp_chat/icon.png diff --git a/demos/misc/window_management/control.gd b/demos/misc/window_management/control.gd new file mode 100644 index 0000000000..5eb5817619 --- /dev/null +++ b/demos/misc/window_management/control.gd @@ -0,0 +1,177 @@ + +extends Control + +func _fixed_process(delta): + + var modetext = "Mode:\n" + + if(OS.is_window_fullscreen()): + modetext += "Fullscreen\n" + else: + modetext += "Windowed\n" + + if(!OS.is_window_resizable()): + modetext += "FixedSize\n" + + if(OS.is_window_minimized()): + modetext += "Minimized\n" + + if(OS.is_window_maximized()): + modetext += "Maximized\n" + + if(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED): + modetext += "MouseGrab\n" + get_node("Label_MouseGrab_KeyInfo").show() + else: + get_node("Label_MouseGrab_KeyInfo").hide() + + get_node("Label_Mode").set_text(modetext) + + get_node("Label_Position").set_text( str("Position:\n", OS.get_window_position() ) ) + + get_node("Label_Size").set_text(str("Size:\n", OS.get_window_size() ) ) + + get_node("Label_MousePosition").set_text(str("Mouse Position:\n", Input.get_mouse_pos() ) ) + + get_node("Label_Screen_Count").set_text( str("Screen_Count:\n", OS.get_screen_count() ) ) + + get_node("Label_Screen_Current").set_text( str("Screen:\n", OS.get_current_screen() ) ) + + get_node("Label_Screen0_Resolution").set_text( str("Screen0 Resolution:\n", OS.get_screen_size() ) ) + + get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position() ) ) + + if(OS.get_screen_count() > 1): + get_node("Button_Screen0").show() + get_node("Button_Screen1").show() + get_node("Label_Screen1_Resolution").show() + get_node("Label_Screen1_Position").show() + get_node("Label_Screen1_Resolution").set_text( str("Screen1 Resolution:\n", OS.get_screen_size(1) ) ) + get_node("Label_Screen1_Position").set_text( str("Screen1 Position:\n", OS.get_screen_position(1) ) ) + else: + get_node("Button_Screen0").hide() + get_node("Button_Screen1").hide() + get_node("Label_Screen1_Resolution").hide() + get_node("Label_Screen1_Position").hide() + + get_node("Button_Fullscreen").set_pressed( OS.is_window_fullscreen() ) + get_node("Button_FixedSize").set_pressed( !OS.is_window_resizable() ) + get_node("Button_Minimized").set_pressed( OS.is_window_minimized() ) + get_node("Button_Maximized").set_pressed( OS.is_window_maximized() ) + get_node("Button_Mouse_Grab").set_pressed( Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED ) + + +func check_wm_api(): + var s = "" + if( !OS.has_method("get_screen_count") ): + s += " - get_screen_count()\n" + + if( !OS.has_method("get_current_screen") ): + s += " - get_current_screen()\n" + + if( !OS.has_method("set_current_screen") ): + s += " - set_current_screen()\n" + + if( !OS.has_method("get_screen_position") ): + s += " - get_screen_position()\n" + + if( !OS.has_method("get_screen_size") ): + s += " - get_screen_size()\n" + + if( !OS.has_method("get_window_position") ): + s += " - get_window_position()\n" + + if( !OS.has_method("set_window_position") ): + s += " - set_window_position()\n" + + if( !OS.has_method("get_window_size") ): + s += " - get_window_size()\n" + + if( !OS.has_method("set_window_size") ): + s += " - set_window_size()\n" + + if( !OS.has_method("set_window_fullscreen") ): + s += " - set_window_fullscreen()\n" + + if( !OS.has_method("is_window_fullscreen") ): + s += " - is_window_fullscreen()\n" + + if( !OS.has_method("set_window_resizable") ): + s += " - set_window_resizable()\n" + + if( !OS.has_method("is_window_resizable") ): + s += " - is_window_resizable()\n" + + if( !OS.has_method("set_window_minimized") ): + s += " - set_window_minimized()\n" + + if( !OS.has_method("is_window_minimized") ): + s += " - is_window_minimized()\n" + + if( !OS.has_method("set_window_maximized") ): + s += " - set_window_maximized()\n" + + if( !OS.has_method("is_window_maximized") ): + s += " - is_window_maximized()\n" + + if( s.length() == 0 ): + return true + else: + var text = get_node("ImplementationDialog/Text").get_text() + get_node("ImplementationDialog/Text").set_text( text + s ) + get_node("ImplementationDialog").show() + return false + + +func _ready(): + if( check_wm_api() ): + set_fixed_process(true) + + +func _on_Button_MoveTo_pressed(): + OS.set_window_position( Vector2(100,100) ) + + +func _on_Button_Resize_pressed(): + OS.set_window_size( Vector2(1024,768) ) + + +func _on_Button_Screen0_pressed(): + OS.set_current_screen(0) + + +func _on_Button_Screen1_pressed(): + OS.set_current_screen(1) + + +func _on_Button_Fullscreen_pressed(): + if(OS.is_window_fullscreen()): + OS.set_window_fullscreen(false) + else: + OS.set_window_fullscreen(true) + + +func _on_Button_FixedSize_pressed(): + if(OS.is_window_resizable()): + OS.set_window_resizable(false) + else: + OS.set_window_resizable(true) + + +func _on_Button_Minimized_pressed(): + if(OS.is_window_minimized()): + OS.set_window_minimized(false) + else: + OS.set_window_minimized(true) + + +func _on_Button_Maximized_pressed(): + if(OS.is_window_maximized()): + OS.set_window_maximized(false) + else: + OS.set_window_maximized(true) + + +func _on_Button_Mouse_Grab_pressed(): + var observer = get_node("../Observer") + observer.state = observer.STATE_GRAB diff --git a/demos/misc/window_management/engine.cfg b/demos/misc/window_management/engine.cfg new file mode 100644 index 0000000000..c53bd45fb7 --- /dev/null +++ b/demos/misc/window_management/engine.cfg @@ -0,0 +1,19 @@ +[application] + +name="window_management" +main_scene="res://window_management.scn" +icon="icon.png" + +[display] + +fullscreen=false +resizable=true +width=800 +height=600 + +[input] + +move_forward=[key(W)] +move_backwards=[key(S)] +move_left=[key(A)] +move_right=[key(D)] diff --git a/demos/misc/window_management/icon.png b/demos/misc/window_management/icon.png Binary files differnew file mode 100644 index 0000000000..0c422e37b0 --- /dev/null +++ b/demos/misc/window_management/icon.png diff --git a/demos/misc/window_management/icon.png.flags b/demos/misc/window_management/icon.png.flags new file mode 100644 index 0000000000..5130fd1aab --- /dev/null +++ b/demos/misc/window_management/icon.png.flags @@ -0,0 +1 @@ +gen_mipmaps=false diff --git a/demos/misc/window_management/observer/observer.gd b/demos/misc/window_management/observer/observer.gd new file mode 100644 index 0000000000..d27912a670 --- /dev/null +++ b/demos/misc/window_management/observer/observer.gd @@ -0,0 +1,79 @@ + +extends Spatial + +var r_pos = Vector2() +var state + +const STATE_MENU=0 +const STATE_GRAB=1 + +func direction(vector): + var v = get_node("Camera").get_global_transform().basis * vector + v = v.normalized() + + return v + + +func impulse(event, action): + if(event.is_action(action) && event.is_pressed() && !event.is_echo()): + return true + else: + return false + + +func _fixed_process(delta): + + if(state != STATE_GRAB): + return + + if(Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED): + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + + var dir = Vector3() + var cam = get_global_transform() + var org = get_translation() + + if (Input.is_action_pressed("move_forward")): + dir += direction(Vector3(0,0,-1)) + if (Input.is_action_pressed("move_backwards")): + dir += direction(Vector3(0,0,1)) + if (Input.is_action_pressed("move_left")): + dir += direction(Vector3(-1,0,0)) + if (Input.is_action_pressed("move_right")): + dir += direction(Vector3(1,0,0)) + + dir = dir.normalized() + + move(dir * 10 * delta) + var d = delta * 0.1 + + var yaw = get_transform().rotated(Vector3(0,1,0), d * r_pos.x) + set_transform(yaw) + + var cam = get_node("Camera") + var pitch = cam.get_transform().rotated(Vector3(1,0,0), d * r_pos.y) + cam.set_transform(pitch) + + r_pos.x = 0.0 + r_pos.y = 0.0 + + +func _input( event ): + if(event.type == InputEvent.MOUSE_MOTION): + r_pos = event.relative_pos + + if(impulse(event, "ui_cancel")): + if(state == STATE_GRAB): + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + state = STATE_MENU + else: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + state = STATE_GRAB + + +func _ready(): + set_fixed_process(true) + set_process_input(true) + + state = STATE_MENU + diff --git a/demos/misc/window_management/observer/observer.scn b/demos/misc/window_management/observer/observer.scn Binary files differnew file mode 100644 index 0000000000..da29ad62b8 --- /dev/null +++ b/demos/misc/window_management/observer/observer.scn diff --git a/demos/misc/window_management/window_management.scn b/demos/misc/window_management/window_management.scn Binary files differnew file mode 100644 index 0000000000..c7d6260df6 --- /dev/null +++ b/demos/misc/window_management/window_management.scn diff --git a/demos/viewport/gui_in_3d/gui_3d.gd b/demos/viewport/gui_in_3d/gui_3d.gd index 5309db9acb..c2a9df0069 100644 --- a/demos/viewport/gui_in_3d/gui_3d.gd +++ b/demos/viewport/gui_in_3d/gui_3d.gd @@ -7,38 +7,39 @@ extends Spatial var prev_pos=null -func _input(ev): - if (ev.type in [InputEvent.MOUSE_BUTTON,InputEvent.MOUSE_MOTION]): - var pos = ev.pos - var rfrom = get_node("camera").project_ray_origin(pos) - var rnorm = get_node("camera").project_ray_normal(pos) + +func _input( ev ): + #all other (non-mouse) events + if (not ev.type in [InputEvent.MOUSE_BUTTON,InputEvent.MOUSE_MOTION,InputEvent.SCREEN_DRAG,InputEvent.SCREEN_TOUCH]): + get_node("viewport").input(ev) - #simple collision test against aligned plane - #for game UIs of this kind consider more complex collision against plane - var p = Plane(Vector3(0,0,1),0).intersects_ray(rfrom,rnorm) - if (p==null): - return - - pos.x=(p.x+1.5)*100 - pos.y=(-p.y+0.75)*100 - ev.pos=pos - ev.global_pos=pos - if (prev_pos==null): - prev_pos=pos - if (ev.type==InputEvent.MOUSE_MOTION): - ev.relative_pos=pos-prev_pos + +#mouse events for area +func _on_area_input_event( camera, ev, click_pos, click_normal, shape_idx ): + + #use click pos (click in 3d space, convert to area space + var pos = get_node("area").get_global_transform().affine_inverse() * click_pos + #convert to 2D + pos = Vector2(pos.x,pos.y) + #convert to viewport coordinate system + pos.x=(pos.x+1.5)*100 + pos.y=(-pos.y+0.75)*100 + #set to event + ev.pos=pos + ev.global_pos=pos + if (prev_pos==null): prev_pos=pos + if (ev.type==InputEvent.MOUSE_MOTION): + ev.relative_pos=pos-prev_pos + prev_pos=pos get_node("viewport").input(ev) - - + func _ready(): # Initalization here - get_node("quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, get_node("viewport").get_render_target_texture() ) + get_node("area/quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, get_node("viewport").get_render_target_texture() ) set_process_input(true) - pass - diff --git a/demos/viewport/gui_in_3d/gui_3d.scn b/demos/viewport/gui_in_3d/gui_3d.scn Binary files differindex df8f7d6dc5..c69d4dc73f 100644 --- a/demos/viewport/gui_in_3d/gui_3d.scn +++ b/demos/viewport/gui_in_3d/gui_3d.scn diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 527991d147..342941970f 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -9,273 +9,275 @@ </description> <methods> <method name="sin" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Standard sine function. </description> </method> <method name="cos" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Standard cosine function. </description> </method> <method name="tan" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Standard tangent function. </description> </method> <method name="sinh" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Hyperbolic sine. </description> </method> <method name="cosh" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Hyperbolic cosine. </description> </method> <method name="tanh" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Hyperbolic tangent. </description> </method> <method name="asin" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Arc-sine. </description> </method> <method name="acos" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Arc-cosine. </description> </method> <method name="atan" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Arc-tangent. </description> </method> <method name="atan2" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> <description> Arc-tangent that takes a 2D vector as argument, retuns the full -pi to +pi range. </description> </method> <method name="sqrt" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Square root. </description> </method> <method name="fmod" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> <description> Module (remainder of x/y). </description> </method> <method name="fposmod" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> <description> Module (remainder of x/y) that wraps equally in positive and negative. </description> </method> <method name="floor" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Floor (rounds down to nearest integer). </description> </method> <method name="ceil" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Ceiling (rounds up to nearest integer). </description> </method> <method name="round" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Round to nearest integer. </description> </method> <method name="abs" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Remove sign (works for integer and float). </description> </method> <method name="sign" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Return sign (-1 or +1). </description> </method> <method name="pow" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> <description> Power function, x elevate to y. </description> </method> <method name="log" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Natural logarithm. </description> </method> <method name="exp" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Exponential logarithm. </description> </method> <method name="isnan" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Return true if the float is not a number. </description> </method> <method name="isinf" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> <description> Return true if the float is infinite. </description> </method> <method name="ease" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> - <argument index="1" name="curve" type="real"> + <argument index="1" name="curve" type="float"> </argument> <description> Easing function, based on exponent. 0 is constant, 1 is linear, 0 to 1 is ease-in, 1+ is ease out. Negative values are in-out/out in. </description> </method> <method name="decimals" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="step" type="real"> + <argument index="0" name="step" type="float"> </argument> <description> Return the amount of decimals in the floating point value. </description> </method> <method name="stepify" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="s" type="real"> + <argument index="0" name="s" type="float"> </argument> - <argument index="1" name="step" type="real"> + <argument index="1" name="step" type="float"> </argument> <description> Snap float value to a given step. </description> </method> <method name="lerp" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="a" type="real"> + <argument index="0" name="from" type="float"> </argument> - <argument index="1" name="b" type="real"> + <argument index="1" name="to" type="float"> </argument> - <argument index="2" name="c" type="real"> + <argument index="2" name="weight" type="float"> </argument> <description> + Linear interpolates between two values by a normalized value. </description> </method> <method name="dectime" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> - <argument index="1" name="amount" type="real"> + <argument index="1" name="amount" type="float"> </argument> - <argument index="2" name="step" type="real"> + <argument index="2" name="step" type="float"> </argument> <description> + Decreases time by a specified amount. </description> </method> <method name="randomize" > @@ -297,18 +299,18 @@ </description> </method> <method name="randf" > - <return type="real"> + <return type="float"> </return> <description> Random value (0 to 1 float). </description> </method> <method name="rand_range" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="from" type="real"> + <argument index="0" name="from" type="float"> </argument> - <argument index="1" name="to" type="real"> + <argument index="1" name="to" type="float"> </argument> <description> Random range, any floating point value between @@ -318,78 +320,78 @@ <method name="rand_seed" > <return type="Array"> </return> - <argument index="0" name="seed" type="real"> + <argument index="0" name="seed" type="float"> </argument> <description> Random from seed, pass a seed and an array with both number and new seed is returned. </description> </method> <method name="deg2rad" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="deg" type="real"> + <argument index="0" name="deg" type="float"> </argument> <description> Convert from degrees to radians. </description> </method> <method name="rad2deg" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="rad" type="real"> + <argument index="0" name="rad" type="float"> </argument> <description> Convert from radias to degrees. </description> </method> <method name="linear2db" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="nrg" type="real"> + <argument index="0" name="nrg" type="float"> </argument> <description> Convert from linear energy to decibels (audio). </description> </method> <method name="db2linear" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="db" type="real"> + <argument index="0" name="db" type="float"> </argument> <description> Convert from decibels to linear energy (audio). </description> </method> <method name="max" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="a" type="real"> + <argument index="0" name="a" type="float"> </argument> - <argument index="1" name="b" type="real"> + <argument index="1" name="b" type="float"> </argument> <description> Return the maximum of two values. </description> </method> <method name="min" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="a" type="real"> + <argument index="0" name="a" type="float"> </argument> - <argument index="1" name="b" type="real"> + <argument index="1" name="b" type="float"> </argument> <description> Return the minimum of two values. </description> </method> <method name="clamp" > - <return type="real"> + <return type="float"> </return> - <argument index="0" name="val" type="real"> + <argument index="0" name="val" type="float"> </argument> - <argument index="1" name="min" type="real"> + <argument index="1" name="min" type="float"> </argument> - <argument index="2" name="max" type="real"> + <argument index="2" name="max" type="float"> </argument> <description> Clamp both values to a range. @@ -421,6 +423,7 @@ <argument index="1" name="funcname" type="String"> </argument> <description> + Returns a reference to the specified function </description> </method> <method name="convert" > @@ -475,6 +478,7 @@ <argument index="1" name="..." type="var"> </argument> <description> + Print one or more arguments to the console with a tab between each argument. </description> </method> <method name="printerr" > @@ -499,6 +503,24 @@ Print one or more arguments to strings in the best way possible to console. No newline is added at the end. </description> </method> + <method name="var2str" > + <return type="String"> + </return> + <argument index="0" name="var" type="var"> + </argument> + <description> + Converts the value of a variable to a String. + </description> + </method> + <method name="str2var:var" > + <return type="String"> + </return> + <argument index="0" name="str" type="String"> + </argument> + <description> + Converts the value of a String to a variable. + </description> + </method> <method name="range" > <return type="Array"> </return> @@ -538,6 +560,15 @@ back into an instance. Useful for deserializing. </description> </method> + <method name="hash" > + <return type="int"> + </return> + <argument index="0" name="var:var" type="var"> + </argument> + <description> + Hashes the variable passed and returns an integer. + </description> + </method> <method name="print_stack" > <return type="Nil"> </return> @@ -549,7 +580,7 @@ </methods> <constants> <constant name="PI" value="3.141593"> - Constant that represents how many times the diameter of a + Constant that represents how many times the diameter of a circumference fits around it's perimeter. </constant> </constants> @@ -568,79 +599,52 @@ <member name="Performance" type="Performance"> </member> <member name="Globals" type="Globals"> - The file engine.cfg is read into this singleton. </member> <member name="IP" type="IP"> - Global IP protocol functions (like hostname resolution). </member> <member name="Geometry" type="Geometry"> - Geometry helpers. </member> <member name="ResourceLoader" type="ResourceLoader"> - Singleton that loads resources (load() calls this) </member> <member name="ResourceSaver" type="ResourceSaver"> - Singleton that saves resources. </member> <member name="PathRemap" type="PathRemap"> - Uset to setup remaps for the filesystem. </member> <member name="OS" type="OS"> - Operating system functions. </member> <member name="Marshalls" type="Reference"> - Used to serialize and deserialize, helpers. </member> <member name="TranslationServer" type="TranslationServer"> - Server that takes care of translating between different - languages. </member> <member name="TS" type="TranslationServer"> - Short version for TranslationServer. </member> <member name="Input" type="Input"> - Global input variables and functions. </member> - <member name="SceneIO" type="SceneIO"> - Deprecaed. + <member name="InputMap" type="InputMap"> </member> <member name="VisualServer" type="VisualServer"> - Server that handles anything visual at low level. </member> <member name="VS" type="VisualServer"> - Short for VisualServer. </member> <member name="AudioServer" type="AudioServer"> - Server that handles anything audio at low level. </member> <member name="AS" type="AudioServer"> - Short for AudioServer. </member> <member name="PhysicsServer" type="PhysicsServer"> - Server that handles anything 3D physics at low level. </member> <member name="PS" type="PhysicsServer"> - Short for PhysicsServer. </member> <member name="Physics2DServer" type="Physics2DServer"> - Server that handles anything 2D physics at low level. </member> <member name="PS2D" type="Physics2DServer"> - Short for Physics2DServer. </member> <member name="SpatialSoundServer" type="SpatialSound2DServer"> - Server that handles spatial audio positioning in 3D at low - level. </member> <member name="SS" type="SpatialSound2DServer"> - Short for SpatialSoundServer. </member> <member name="SpatialSound2DServer" type="SpatialSound2DServer"> - Server that handles spatial audio positioning in 2D at low - level. </member> <member name="SS2D" type="SpatialSound2DServer"> - Short for SpatialSound2DServer. </member> </members> <constants> @@ -1443,20 +1447,38 @@ <constant name="PROPERTY_HINT_ENUM" value="3"> Property hint is an enumerated value, like "Hello,Something,Else". This is valid for integers, floats and strings properties. </constant> + <constant name="PROPERTY_HINT_EXP_EASING" value="4"> + </constant> <constant name="PROPERTY_HINT_LENGTH" value="5"> </constant> + <constant name="PROPERTY_HINT_KEY_ACCEL" value="6"> + </constant> <constant name="PROPERTY_HINT_FLAGS" value="7"> Property hint is a bitmask description, for bits 0,1,2,3 abd 5 the hint would be like "Bit0,Bit1,Bit2,Bit3,,Bit5". Valid only for integers. </constant> + <constant name="PROPERTY_HINT_ALL_FLAGS" value="8"> + </constant> <constant name="PROPERTY_HINT_FILE" value="9"> String property is a file (so pop up a file dialog when edited). Hint string can be a set of wildcards like "*.doc". </constant> <constant name="PROPERTY_HINT_DIR" value="10"> String property is a directory (so pop up a file dialog when edited). </constant> + <constant name="PROPERTY_HINT_GLOBAL_FILE" value="11"> + </constant> + <constant name="PROPERTY_HINT_GLOBAL_DIR" value="12"> + </constant> <constant name="PROPERTY_HINT_RESOURCE_TYPE" value="13"> String property is a resource, so open the resource popup menu when edited. </constant> + <constant name="PROPERTY_HINT_MULTILINE_TEXT" value="14"> + </constant> + <constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="15"> + </constant> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="16"> + </constant> + <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="17"> + </constant> <constant name="PROPERTY_USAGE_STORAGE" value="1"> Property will be used as storage (default). </constant> @@ -1586,7 +1608,7 @@ </description> </method> <method name="get_area" > - <return type="real"> + <return type="float"> </return> <description> Get the area inside the [AABB] @@ -1617,7 +1639,7 @@ </description> </method> <method name="get_longest_axis_size" > - <return type="real"> + <return type="float"> </return> <description> Return the scalar length of the longest axis of the @@ -1640,7 +1662,7 @@ </description> </method> <method name="get_shortest_axis_size" > - <return type="real"> + <return type="float"> </return> <description> Return the scalar length of the shortest axis of the @@ -1660,7 +1682,7 @@ <method name="grow" > <return type="AABB"> </return> - <argument index="0" name="by" type="real"> + <argument index="0" name="by" type="float"> </argument> <description> Return a copy of the AABB grown a given a mount of @@ -1718,6 +1740,16 @@ Return true if the AABB is at both sides of a plane. </description> </method> + <method name="intersects_segment" > + <return type="bool"> + </return> + <argument index="0" name="from" type="Vector3"> + </argument> + <argument index="1" name="to" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="merge" > <return type="AABB"> </return> @@ -1744,7 +1776,6 @@ <member name="size" type="Vector3"> </member> <member name="end" type="Vector3"> - Same as pos+size. </member> </members> <constants> @@ -1792,7 +1823,11 @@ <method name="add_button" > <return type="Button"> </return> - <argument index="0" name="text" type="String" default=""""> + <argument index="0" name="text" type="String"> + </argument> + <argument index="1" name="right" type="bool" default="false"> + </argument> + <argument index="2" name="action" type="String" default=""""> </argument> <description> </description> @@ -1933,7 +1968,7 @@ </argument> <description> Set the visible sprite frame index (from the list of - frames inside the [SpriteFrames] resource). + frames inside the [SpriteFrames] resource). </description> </method> <method name="get_frame" qualifiers="const" > @@ -1961,6 +1996,40 @@ <constants> </constants> </class> +<class name="AnimatedSprite3D" inherits="SpriteBase3D" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_sprite_frames" > + <argument index="0" name="sprite_frames" type="SpriteFrames"> + </argument> + <description> + </description> + </method> + <method name="get_sprite_frames" qualifiers="const" > + <return type="Texture"> + </return> + <description> + </description> + </method> + <method name="set_frame" > + <argument index="0" name="frame" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_frame" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Animation" inherits="Resource" category="Core"> <brief_description> Contains data used to animate everything in the engine. @@ -2048,7 +2117,7 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="time" type="real"> + <argument index="1" name="time" type="float"> </argument> <argument index="2" name="loc" type="Vector3"> </argument> @@ -2063,11 +2132,11 @@ <method name="track_insert_key" > <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="time" type="real"> + <argument index="1" name="time" type="float"> </argument> <argument index="2" name="key" type="var"> </argument> - <argument index="3" name="transition" type="real" default="1"> + <argument index="3" name="transition" type="float" default="1"> </argument> <description> Insert a generic key in a given track. @@ -2085,7 +2154,7 @@ <method name="track_remove_key_at_pos" > <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="pos" type="real"> + <argument index="1" name="pos" type="float"> </argument> <description> Remove a key by position (seconds) in a given track. @@ -2107,7 +2176,7 @@ </argument> <argument index="1" name="key_idx" type="int"> </argument> - <argument index="2" name="transition" type="real"> + <argument index="2" name="transition" type="float"> </argument> <description> Set the transition curve (easing) for a specific key (see built-in @@ -2115,7 +2184,7 @@ </description> </method> <method name="track_get_key_transition" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="idx" type="int"> </argument> @@ -2145,7 +2214,7 @@ </description> </method> <method name="track_get_key_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="idx" type="int"> </argument> @@ -2160,7 +2229,7 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="time" type="real"> + <argument index="1" name="time" type="float"> </argument> <argument index="2" name="exact" type="bool" default="false"> </argument> @@ -2191,7 +2260,7 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="time_sec" type="real"> + <argument index="1" name="time_sec" type="float"> </argument> <description> Return the interpolated value of a transform track at a given time (in seconds). An array consisting of 3 elements: position ([Vector3]), rotation ([Quat]) and scale ([Vector3]). @@ -2220,9 +2289,9 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="time_sec" type="real"> + <argument index="1" name="time_sec" type="float"> </argument> - <argument index="2" name="delta" type="real"> + <argument index="2" name="delta" type="float"> </argument> <description> Return all the key indices of a value track, given a position and delta time. @@ -2233,9 +2302,9 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="time_sec" type="real"> + <argument index="1" name="time_sec" type="float"> </argument> - <argument index="2" name="delta" type="real"> + <argument index="2" name="delta" type="float"> </argument> <description> Return all the key indices of a method track, given a position and delta time. @@ -2264,14 +2333,14 @@ </description> </method> <method name="set_length" > - <argument index="0" name="time_sec" type="real"> + <argument index="0" name="time_sec" type="float"> </argument> <description> Set the total length of the animation (in seconds). Note that length is not delimited by the last key, as this one may be before or after the end to ensure correct interpolation and looping. </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the total length of the animation (in seconds). @@ -2292,13 +2361,13 @@ </description> </method> <method name="set_step" > - <argument index="0" name="size_sec" type="real"> + <argument index="0" name="size_sec" type="float"> </argument> <description> </description> </method> <method name="get_step" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -2346,7 +2415,7 @@ <argument index="1" name="animation" type="Animation"> </argument> <description> - Add an animation resource to the player, which will be later referenced by the "name" arguemnt. + Add an animation resource to the player, which will be later referenced by the "name" argument. </description> </method> <method name="remove_animation" > @@ -2395,14 +2464,14 @@ </argument> <argument index="1" name="anim_to" type="String"> </argument> - <argument index="2" name="sec" type="real"> + <argument index="2" name="sec" type="float"> </argument> <description> Specify a blend time (in seconds) between two animations, referemced by their names. </description> </method> <method name="get_blend_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="anim_from" type="String"> </argument> @@ -2413,14 +2482,14 @@ </description> </method> <method name="set_default_blend_time" > - <argument index="0" name="sec" type="real"> + <argument index="0" name="sec" type="float"> </argument> <description> Set the default blend time between animations. </description> </method> <method name="get_default_blend_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the default blend time between animations. @@ -2429,9 +2498,9 @@ <method name="play" > <argument index="0" name="name" type="String" default=""""> </argument> - <argument index="1" name="custom_blend" type="real" default="-1"> + <argument index="1" name="custom_blend" type="float" default="-1"> </argument> - <argument index="2" name="custom_speed" type="real" default="1"> + <argument index="2" name="custom_speed" type="float" default="1"> </argument> <argument index="3" name="from_end" type="bool" default="false"> </argument> @@ -2501,14 +2570,14 @@ </description> </method> <method name="set_speed" > - <argument index="0" name="speed" type="real"> + <argument index="0" name="speed" type="float"> </argument> <description> Set a speed scaling ratio in a given animation channel (or channel 0 if none is provided). Default ratio is [i]1[/i] (no scaling). </description> </method> <method name="get_speed" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Get the speed scaling ratio in a given animation channel (or channel 0 if none is provided). Default ratio is [i]1[/i] (no scaling). @@ -2545,7 +2614,7 @@ </description> </method> <method name="seek" > - <argument index="0" name="pos_sec" type="real"> + <argument index="0" name="pos_sec" type="float"> </argument> <argument index="1" name="update" type="bool" default="false"> </argument> @@ -2557,7 +2626,7 @@ </description> </method> <method name="get_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the playback position (in seconds) in an animation channel (or channel 0 if none is provided) @@ -2592,7 +2661,7 @@ </description> </method> <method name="get_current_animation_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Get the position (in seconds) of the currently being @@ -2600,13 +2669,19 @@ </description> </method> <method name="get_current_animation_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Get the length (in seconds) of the currently being played animation. </description> </method> + <method name="advance" > + <argument index="0" name="delta" type="float"> + </argument> + <description> + </description> + </method> </methods> <signals> <signal name="animation_changed"> @@ -2627,11 +2702,11 @@ </signals> <constants> <constant name="ANIMATION_PROCESS_FIXED" value="0"> - Process animation on fixed process. This is specially useful + Process animation on fixed process. This is specially useful when animating kinematic bodies. </constant> <constant name="ANIMATION_PROCESS_IDLE" value="1"> - Process animation on idle process. + Process animation on idle process. </constant> </constants> </class> @@ -2695,7 +2770,7 @@ types of nodes have different amount of inputs. </description> </method> - <method name="node_get_input_sourcre" qualifiers="const" > + <method name="node_get_input_source" qualifiers="const" > <return type="String"> </return> <argument index="0" name="id" type="String"> @@ -2742,13 +2817,13 @@ <method name="oneshot_node_set_fadein_time" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="time_sec" type="real"> + <argument index="1" name="time_sec" type="float"> </argument> <description> </description> </method> <method name="oneshot_node_get_fadein_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2758,13 +2833,13 @@ <method name="oneshot_node_set_fadeout_time" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="time_sec" type="real"> + <argument index="1" name="time_sec" type="float"> </argument> <description> </description> </method> <method name="oneshot_node_get_fadeout_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2782,7 +2857,7 @@ <method name="oneshot_node_set_autorestart_delay" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="delay_sec" type="real"> + <argument index="1" name="delay_sec" type="float"> </argument> <description> </description> @@ -2790,7 +2865,7 @@ <method name="oneshot_node_set_autorestart_random_delay" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="rand_sec" type="real"> + <argument index="1" name="rand_sec" type="float"> </argument> <description> </description> @@ -2804,7 +2879,7 @@ </description> </method> <method name="oneshot_node_get_autorestart_delay" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2812,7 +2887,7 @@ </description> </method> <method name="oneshot_node_get_autorestart_random_delay" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2852,13 +2927,13 @@ <method name="mix_node_set_amount" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="ratio" type="real"> + <argument index="1" name="ratio" type="float"> </argument> <description> </description> </method> <method name="mix_node_get_amount" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2868,13 +2943,13 @@ <method name="blend2_node_set_amount" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="blend" type="real"> + <argument index="1" name="blend" type="float"> </argument> <description> </description> </method> <method name="blend2_node_get_amount" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2894,13 +2969,13 @@ <method name="blend3_node_set_amount" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="blend" type="real"> + <argument index="1" name="blend" type="float"> </argument> <description> </description> </method> <method name="blend3_node_get_amount" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2926,13 +3001,13 @@ <method name="timescale_node_set_scale" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="scale" type="real"> + <argument index="1" name="scale" type="float"> </argument> <description> </description> </method> <method name="timescale_node_get_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -2942,7 +3017,7 @@ <method name="timeseek_node_seek" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="pos_sec" type="real"> + <argument index="1" name="pos_sec" type="float"> </argument> <description> </description> @@ -2994,13 +3069,13 @@ <method name="transition_node_set_xfade_time" > <argument index="0" name="id" type="String"> </argument> - <argument index="1" name="time_sec" type="real"> + <argument index="1" name="time_sec" type="float"> </argument> <description> </description> </method> <method name="transition_node_get_xfade_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="id" type="String"> </argument> @@ -3182,37 +3257,37 @@ </description> </method> <method name="set_gravity" > - <argument index="0" name="gravity" type="real"> + <argument index="0" name="gravity" type="float"> </argument> <description> </description> </method> <method name="get_gravity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_density" > - <argument index="0" name="density" type="real"> + <argument index="0" name="density" type="float"> </argument> <description> </description> </method> <method name="get_density" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_priority" > - <argument index="0" name="priority" type="real"> + <argument index="0" name="priority" type="float"> </argument> <description> </description> </method> <method name="get_priority" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -3229,6 +3304,12 @@ <description> </description> </method> + <method name="get_overlapping_bodies" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> </methods> <signals> <signal name="body_enter"> @@ -3319,37 +3400,37 @@ </description> </method> <method name="set_gravity" > - <argument index="0" name="gravity" type="real"> + <argument index="0" name="gravity" type="float"> </argument> <description> </description> </method> <method name="get_gravity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_density" > - <argument index="0" name="density" type="real"> + <argument index="0" name="density" type="float"> </argument> <description> </description> </method> <method name="get_density" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_priority" > - <argument index="0" name="priority" type="real"> + <argument index="0" name="priority" type="float"> </argument> <description> </description> </method> <method name="get_priority" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -3366,6 +3447,12 @@ <description> </description> </method> + <method name="get_overlapping_bodies" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> </methods> <signals> <signal name="body_enter"> @@ -3793,7 +3880,7 @@ <method name="voice_set_volume" > <argument index="0" name="voice" type="RID"> </argument> - <argument index="1" name="volume" type="real"> + <argument index="1" name="volume" type="float"> </argument> <description> Change the volume of a currently playing voice."#10;"#9;"#9;"#9;Volume is expressed as linear gain where 0.0 is mute"#10;"#9;"#9;"#9;and 1.0 is default. @@ -3802,11 +3889,11 @@ <method name="voice_set_pan" > <argument index="0" name="voice" type="RID"> </argument> - <argument index="1" name="pan" type="real"> + <argument index="1" name="pan" type="float"> </argument> - <argument index="2" name="depth" type="real" default="0"> + <argument index="2" name="depth" type="float" default="0"> </argument> - <argument index="3" name="height" type="real" default="0"> + <argument index="3" name="height" type="float" default="0"> </argument> <description> Change the pan of a currently playing voice and,"#10;"#9;"#9;"#9;optionally, the depth and height for a positional/3D"#10;"#9;"#9;"#9;sound. Panning values are expressed within the -1 to"#10;"#9;"#9;"#9;+1 range. @@ -3817,11 +3904,11 @@ </argument> <argument index="1" name="type" type="int"> </argument> - <argument index="2" name="cutoff" type="real"> + <argument index="2" name="cutoff" type="float"> </argument> - <argument index="3" name="resonance" type="real"> + <argument index="3" name="resonance" type="float"> </argument> - <argument index="4" name="gain" type="real" default="0"> + <argument index="4" name="gain" type="float" default="0"> </argument> <description> Set a resonant filter post processing for the voice."#10;"#9;"#9;"#9;Filter type is a value from the FILTER_* enum. @@ -3830,7 +3917,7 @@ <method name="voice_set_chorus" > <argument index="0" name="voice" type="RID"> </argument> - <argument index="1" name="chorus" type="real"> + <argument index="1" name="chorus" type="float"> </argument> <description> Set chorus send post processing for the voice (from"#10;"#9;"#9;"#9;0 to 1). @@ -3841,7 +3928,7 @@ </argument> <argument index="1" name="room" type="int"> </argument> - <argument index="2" name="reverb" type="real"> + <argument index="2" name="reverb" type="float"> </argument> <description> Set the reverb send post processing for the voice (from"#10;"#9;"#9;"#9;0 to 1) and the reverb type, from the REVERB_* enum. @@ -3866,7 +3953,7 @@ </description> </method> <method name="voice_get_volume" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3875,7 +3962,7 @@ </description> </method> <method name="voice_get_pan" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3884,7 +3971,7 @@ </description> </method> <method name="voice_get_pan_height" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3893,7 +3980,7 @@ </description> </method> <method name="voice_get_pan_depth" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3911,7 +3998,7 @@ </description> </method> <method name="voice_get_filter_cutoff" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3920,7 +4007,7 @@ </description> </method> <method name="voice_get_filter_resonance" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3929,7 +4016,7 @@ </description> </method> <method name="voice_get_chorus" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3947,7 +4034,7 @@ </description> </method> <method name="voice_get_reverb" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="RID"> </argument> @@ -3988,39 +4075,39 @@ </description> </method> <method name="set_stream_global_volume_scale" > - <argument index="0" name="scale" type="real"> + <argument index="0" name="scale" type="float"> </argument> <description> Set global scale for stream playback. Default is 1.0. </description> </method> <method name="get_stream_global_volume_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the global scale for stream playback. </description> </method> <method name="set_fx_global_volume_scale" > - <argument index="0" name="scale" type="real"> + <argument index="0" name="scale" type="float"> </argument> <description> </description> </method> <method name="get_fx_global_volume_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_event_voice_global_volume_scale" > - <argument index="0" name="scale" type="real"> + <argument index="0" name="scale" type="float"> </argument> <description> </description> </method> <method name="get_event_voice_global_volume_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -4141,21 +4228,21 @@ </description> </method> <method name="seek_pos" > - <argument index="0" name="pos" type="real"> + <argument index="0" name="pos" type="float"> </argument> <description> Seek to a certain position (in seconds) in an audio"#10;"#9;"#9;"#9;stream. </description> </method> <method name="get_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the current playing position (in seconds) of the audio"#10;"#9;"#9;"#9;stream (if supported). Since this value is updated"#10;"#9;"#9;"#9;internally, it may not be exact or updated"#10;"#9;"#9;"#9;continuosly. Accuracy depends on the sample buffer"#10;"#9;"#9;"#9;size of the audio driver. </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -4208,42 +4295,42 @@ </description> </method> <method name="set_pitch_scale" > - <argument index="0" name="pitch_scale" type="real"> + <argument index="0" name="pitch_scale" type="float"> </argument> <description> Set pitch scale for the speech. Animating this value holds amusing results. </description> </method> <method name="get_pitch_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the pitch scale. </description> </method> <method name="set_pitch_random_scale" > - <argument index="0" name="pitch_random_scale" type="real"> + <argument index="0" name="pitch_random_scale" type="float"> </argument> <description> Set the random scaling for the pitch. </description> </method> <method name="get_pitch_random_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the pitch random scaling. </description> </method> <method name="set_xfade_time" > - <argument index="0" name="sec" type="real"> + <argument index="0" name="sec" type="float"> </argument> <description> Set the cross-fade time between random phonemes. </description> </method> <method name="get_xfade_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the cross-fade time between random phonemes. @@ -4329,6 +4416,374 @@ <constants> </constants> </class> +<class name="BakedLight" inherits="Resource" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_mode" > + <argument index="0" name="mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_octree" > + <argument index="0" name="octree" type="RawArray"> + </argument> + <description> + </description> + </method> + <method name="get_octree" qualifiers="const" > + <return type="RawArray"> + </return> + <description> + </description> + </method> + <method name="set_light" > + <argument index="0" name="light" type="RawArray"> + </argument> + <description> + </description> + </method> + <method name="get_light" qualifiers="const" > + <return type="RawArray"> + </return> + <description> + </description> + </method> + <method name="set_sampler_octree" > + <argument index="0" name="sampler_octree" type="IntArray"> + </argument> + <description> + </description> + </method> + <method name="get_sampler_octree" qualifiers="const" > + <return type="IntArray"> + </return> + <description> + </description> + </method> + <method name="add_lightmap" > + <argument index="0" name="texture" type="Texture"> + </argument> + <argument index="1" name="gen_size" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="erase_lightmap" > + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="clear_lightmaps" > + <description> + </description> + </method> + <method name="set_cell_subdivision" > + <argument index="0" name="cell_subdivision" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_cell_subdivision" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_initial_lattice_subdiv" > + <argument index="0" name="cell_subdivision" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_initial_lattice_subdiv" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_plot_size" > + <argument index="0" name="plot_size" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_plot_size" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_bounces" > + <argument index="0" name="bounces" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_bounces" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_cell_extra_margin" > + <argument index="0" name="cell_extra_margin" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_cell_extra_margin" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_edge_damp" > + <argument index="0" name="edge_damp" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_edge_damp" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_normal_damp" > + <argument index="0" name="normal_damp" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_normal_damp" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_tint" > + <argument index="0" name="tint" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_tint" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_saturation" > + <argument index="0" name="saturation" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_saturation" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_ao_radius" > + <argument index="0" name="ao_radius" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_ao_radius" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_ao_strength" > + <argument index="0" name="ao_strength" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_ao_strength" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_format" > + <argument index="0" name="format" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_format" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_transfer_lightmaps_only_to_uv2" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_transfer_lightmaps_only_to_uv2" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_energy_multiplier" > + <argument index="0" name="energy_multiplier" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_energy_multiplier" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_gamma_adjust" > + <argument index="0" name="gamma_adjust" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_gamma_adjust" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_bake_flag" > + <argument index="0" name="flag" type="int"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_bake_flag" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="flag" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + <constant name="MODE_OCTREE" value="0"> + </constant> + <constant name="MODE_LIGHTMAPS" value="1"> + </constant> + <constant name="BAKE_DIFFUSE" value="0"> + </constant> + <constant name="BAKE_SPECULAR" value="1"> + </constant> + <constant name="BAKE_TRANSLUCENT" value="2"> + </constant> + <constant name="BAKE_CONSERVE_ENERGY" value="3"> + </constant> + <constant name="BAKE_MAX" value="5"> + </constant> + </constants> +</class> +<class name="BakedLightInstance" inherits="VisualInstance" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_baked_light" > + <argument index="0" name="baked_light" type="Object"> + </argument> + <description> + </description> + </method> + <method name="get_baked_light" qualifiers="const" > + <return type="Object"> + </return> + <description> + </description> + </method> + <method name="get_baked_light_instance" qualifiers="const" > + <return type="RID"> + </return> + <description> + </description> + </method> + </methods> + <signals> + <signal name="baked_light_changed"> + <description> + </description> + </signal> + </signals> + <constants> + </constants> +</class> +<class name="BakedLightSampler" inherits="VisualInstance" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_param" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_resolution" > + <argument index="0" name="resolution" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_resolution" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <constants> + <constant name="PARAM_RADIUS" value="0"> + </constant> + <constant name="PARAM_STRENGTH" value="1"> + </constant> + <constant name="PARAM_ATTENUATION" value="2"> + </constant> + <constant name="PARAM_DETAIL_RATIO" value="3"> + </constant> + <constant name="PARAM_MAX" value="4"> + </constant> + </constants> +</class> <class name="BaseButton" inherits="Control" category="Core"> <brief_description> Provides a base class for different kinds of buttons. @@ -4351,6 +4806,12 @@ Return when the button is pressed (only if toggle_mode is active). </description> </method> + <method name="is_hovered" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="set_toggle_mode" > <argument index="0" name="enabled" type="bool"> </argument> @@ -4393,8 +4854,19 @@ Return the state of the click_on_press property (see [method set_click_on_press]). </description> </method> + <method name="get_draw_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + Return the visual state used to draw the button. This is useful mainly when implementing your own draw code by either overiding _draw() or connecting to "draw" signal. The visual state of the button is defined by the DRAW_* enum. + </description> + </method> </methods> <signals> + <signal name="released"> + <description> + </description> + </signal> <signal name="toggled"> <argument index="0" name="pressed" type="bool"> </argument> @@ -4409,6 +4881,14 @@ </signal> </signals> <constants> + <constant name="DRAW_NORMAL" value="0"> + </constant> + <constant name="DRAW_PRESSED" value="1"> + </constant> + <constant name="DRAW_HOVER" value="2"> + </constant> + <constant name="DRAW_DISABLED" value="3"> + </constant> </constants> </class> <class name="BitMap" inherits="Resource" category="Core"> @@ -4594,6 +5074,30 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="font_color_disabled" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="font_color_pressed" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="pressed" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="disabled" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="ButtonArray" inherits="Control" category="Core"> <brief_description> @@ -4820,22 +5324,22 @@ </description> </method> <method name="set_perspective" > - <argument index="0" name="fov" type="real"> + <argument index="0" name="fov" type="float"> </argument> - <argument index="1" name="z_near" type="real"> + <argument index="1" name="z_near" type="float"> </argument> - <argument index="2" name="z_far" type="real"> + <argument index="2" name="z_far" type="float"> </argument> <description> Set the camera projection to perspective mode, by specifying a [i]FOV[/i] Y angle in degrees (FOV means Field of View), and the [i]near[/i] and [i]far[/i] clip planes in worldspace units. </description> </method> <method name="set_orthogonal" > - <argument index="0" name="size" type="real"> + <argument index="0" name="size" type="float"> </argument> - <argument index="1" name="z_near" type="real"> + <argument index="1" name="z_near" type="float"> </argument> - <argument index="2" name="z_far" type="real"> + <argument index="2" name="z_far" type="float"> </argument> <description> Set the camera projection to orthogonal mode, by specifying a"#10;"#9;"#9;"#9;width and the [i]near[/i] and [i]far[/i] clip planes in worldspace units. (As a hint, 2D games often use this projection, with values specified in pixels) @@ -4865,25 +5369,25 @@ </description> </method> <method name="get_fov" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_size" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_zfar" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_znear" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -4936,14 +5440,14 @@ <description> </description> </method> - <method name="set_use_vertical_aspect" > - <argument index="0" name="enable" type="bool"> + <method name="set_keep_aspect_mode" > + <argument index="0" name="mode" type="int"> </argument> <description> </description> </method> - <method name="is_using_vertical_aspect" qualifiers="const" > - <return type="bool"> + <method name="get_keep_aspect_mode" qualifiers="const" > + <return type="int"> </return> <description> </description> @@ -4956,6 +5460,10 @@ <constant name="PROJECTION_ORTHOGONAL" value="1"> Orthogonal Projection (objects remain the same size on the screen no matter how far away they are). </constant> + <constant name="KEEP_WIDTH" value="0"> + </constant> + <constant name="KEEP_HEIGHT" value="1"> + </constant> </constants> </class> <class name="Camera2D" inherits="Node2D" category="Core"> @@ -5067,25 +5575,25 @@ </description> </method> <method name="set_v_offset" > - <argument index="0" name="ofs" type="real"> + <argument index="0" name="ofs" type="float"> </argument> <description> </description> </method> <method name="get_v_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_h_offset" > - <argument index="0" name="ofs" type="real"> + <argument index="0" name="ofs" type="float"> </argument> <description> </description> </method> <method name="get_h_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -5093,14 +5601,14 @@ <method name="set_drag_margin" > <argument index="0" name="margin" type="int"> </argument> - <argument index="1" name="drag_margin" type="real"> + <argument index="1" name="drag_margin" type="float"> </argument> <description> Set the margins needed to drag the camera (relative to the screen size). Margin uses the MARGIN_* enum. Drag margins of 0,0,0,0 will keep the camera at the center of the screen, while drag margins of 1,1,1,1 will only move when the camera is at the edges. </description> </method> <method name="get_drag_margin" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="margin" type="int"> </argument> @@ -5134,13 +5642,13 @@ </description> </method> <method name="set_follow_smoothing" > - <argument index="0" name="follow_smoothing" type="real"> + <argument index="0" name="follow_smoothing" type="float"> </argument> <description> </description> </method> <method name="get_follow_smoothing" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -5189,7 +5697,7 @@ </description> </method> <method name="edit_rotate" > - <argument index="0" name="degrees" type="real"> + <argument index="0" name="degrees" type="float"> </argument> <description> Used for editing, handle rotation. @@ -5267,27 +5775,27 @@ </description> </method> <method name="set_opacity" > - <argument index="0" name="opacity" type="real"> + <argument index="0" name="opacity" type="float"> </argument> <description> Set canvas item opacity. This will affect the canvas item and all the children. </description> </method> <method name="get_opacity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the canvas item opacity. This affects the canvas item and all the children. </description> </method> <method name="set_self_opacity" > - <argument index="0" name="self_opacity" type="real"> + <argument index="0" name="self_opacity" type="float"> </argument> <description> </description> </method> <method name="get_self_opacity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Set canvas item self-opacity. This does not affect the opacity of children items. @@ -5312,7 +5820,7 @@ </argument> <argument index="2" name="color" type="Color"> </argument> - <argument index="3" name="width" type="real" default="1"> + <argument index="3" name="width" type="float" default="1"> </argument> <description> Draw a line from a 2D point to another, with a given color and width. @@ -5330,7 +5838,7 @@ <method name="draw_circle" > <argument index="0" name="pos" type="Vector2"> </argument> - <argument index="1" name="radius" type="real"> + <argument index="1" name="radius" type="float"> </argument> <argument index="2" name="color" type="Color"> </argument> @@ -5391,7 +5899,7 @@ </argument> <argument index="3" name="texture" type="Texture" default="Object()"> </argument> - <argument index="4" name="width" type="real" default="1"> + <argument index="4" name="width" type="float" default="1"> </argument> <description> Draw a custom primitive, 1 point for a point, 2 points for a line, 3 points for a triangle and 4 points for a quad. @@ -5402,11 +5910,9 @@ </argument> <argument index="1" name="colors" type="ColorArray"> </argument> - <argument index="2" name="uvs" type="Vector2Array"> - </argument> - <argument index="3" name="texture" type="Texture" default="Array()"> + <argument index="2" name="uvs" type="Vector2Array" default="Array()"> </argument> - <argument index="4" name="arg4" type="real" default="Object()"> + <argument index="3" name="texture" type="Texture" default="Object()"> </argument> <description> Draw a polygon of any amount of points, convex or concave. @@ -5415,13 +5921,11 @@ <method name="draw_colored_polygon" > <argument index="0" name="points" type="Vector2Array"> </argument> - <argument index="1" name="color" type="ColorArray"> - </argument> - <argument index="2" name="uvs" type="Vector2Array"> + <argument index="1" name="color" type="Color"> </argument> - <argument index="3" name="texture" type="Texture" default="Array()"> + <argument index="2" name="uvs" type="Vector2Array" default="Array()"> </argument> - <argument index="4" name="arg4" type="real" default="Object()"> + <argument index="3" name="texture" type="Texture" default="Object()"> </argument> <description> Draw a colored polygon of any amount of points, convex or concave. @@ -5443,7 +5947,7 @@ </description> </method> <method name="draw_char" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="font" type="Font"> </argument> @@ -5462,7 +5966,7 @@ <method name="draw_set_transform" > <argument index="0" name="pos" type="Vector2"> </argument> - <argument index="1" name="rot" type="real"> + <argument index="1" name="rot" type="float"> </argument> <argument index="2" name="scale" type="Vector2"> </argument> @@ -5506,12 +6010,6 @@ <description> </description> </method> - <method name="get_viewport" qualifiers="const" > - <return type="Object"> - </return> - <description> - </description> - </method> </methods> <signals> <signal name="item_rect_changed"> @@ -5548,6 +6046,8 @@ <constant name="BLEND_MODE_MUL" value="3"> Multiplicative blending mode. </constant> + <constant name="BLEND_MODE_PREMULT_ALPHA" value="4"> + </constant> <constant name="NOTIFICATION_DRAW" value="30"> CanvasItem is requested to draw. </constant> @@ -5616,14 +6116,14 @@ </description> </method> <method name="set_rotation" > - <argument index="0" name="rotation" type="real"> + <argument index="0" name="rotation" type="float"> </argument> <description> Set the base rotation for this layer (helper). </description> </method> <method name="get_rotation" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the base rotation for this layer (helper). @@ -5670,28 +6170,28 @@ </description> <methods> <method name="set_radius" > - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> <description> Set the capsule radius. </description> </method> <method name="get_radius" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the capsule radius. </description> </method> <method name="set_height" > - <argument index="0" name="height" type="real"> + <argument index="0" name="height" type="float"> </argument> <description> Set the capsule height. </description> </method> <method name="get_height" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the capsule height. @@ -5710,28 +6210,28 @@ </description> <methods> <method name="set_radius" > - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> <description> Radius of the [CapsuleShape2D]. </description> </method> <method name="get_radius" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the radius of the [CapsuleShape2D]. </description> </method> <method name="set_height" > - <argument index="0" name="height" type="real"> + <argument index="0" name="height" type="float"> </argument> <description> Height of the [CapsuleShape2D]. </description> </method> <method name="get_height" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the height of the [CapsuleShape2D]. @@ -5741,238 +6241,26 @@ <constants> </constants> </class> -<class name="CarBody" inherits="PhysicsBody" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - <method name="set_max_steer_angle" > - <argument index="0" name="value" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_steer_rate" > - <argument index="0" name="rate" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_drive_torque" > - <argument index="0" name="value" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_max_steer_angle" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_steer_rate" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_drive_torque" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_target_steering" > - <argument index="0" name="amount" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_target_accelerate" > - <argument index="0" name="amount" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_hand_brake" > - <argument index="0" name="amount" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_target_steering" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_target_accelerate" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_hand_brake" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_mass" > - <argument index="0" name="mass" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_mass" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_friction" > - <argument index="0" name="friction" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_friction" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> -<class name="CarWheel" inherits="Spatial" category="Core"> +<class name="CenterContainer" inherits="Container" category="Core"> <brief_description> + Keeps children controls centered. </brief_description> <description> + CenterContainer Keeps children controls centered. This container keeps all children to their minimum size, in the center. </description> <methods> - <method name="set_side_friction" > - <argument index="0" name="friction" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_forward_friction" > - <argument index="0" name="friction" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_travel" > - <argument index="0" name="distance" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_radius" > - <argument index="0" name="radius" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_resting_frac" > - <argument index="0" name="frac" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_damping_frac" > - <argument index="0" name="frac" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_num_rays" > - <argument index="0" name="amount" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_side_friction" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_forward_friction" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_travel" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_radius" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_resting_frac" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_damping_frac" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="get_num_rays" qualifiers="const" > - <return type="int"> - </return> - <description> - </description> - </method> - <method name="set_type_drive" > + <method name="set_use_top_left" > <argument index="0" name="enable" type="bool"> </argument> <description> </description> </method> - <method name="is_type_drive" qualifiers="const" > + <method name="is_using_top_left" qualifiers="const" > <return type="bool"> </return> <description> </description> </method> - <method name="set_type_steer" > - <argument index="0" name="enable" type="bool"> - </argument> - <description> - </description> - </method> - <method name="is_type_steer" qualifiers="const" > - <return type="bool"> - </return> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> -<class name="CenterContainer" inherits="Container" category="Core"> - <brief_description> - Keeps children controls centered. - </brief_description> - <description> - CenterContainer Keeps children controls centered. This container keeps all children to their minimum size, in the center. - </description> - <methods> </methods> <constants> </constants> @@ -5988,6 +6276,36 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="check_vadjust" type="int"> + </theme_item> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="font_color_disabled" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="font_color_pressed" type="Color"> + </theme_item> + <theme_item name="off" type="Texture"> + </theme_item> + <theme_item name="on" type="Texture"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="pressed" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="disabled" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="CircleShape2D" inherits="Shape2D" category="Core"> <brief_description> @@ -5998,14 +6316,14 @@ </description> <methods> <method name="set_radius" > - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> <description> Set the radius of the circle shape; </description> </method> <method name="get_radius" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the radius of the circle shape. @@ -6021,6 +6339,20 @@ <description> </description> <methods> + <method name="_input_event" qualifiers="virtual" > + <argument index="0" name="camera" type="Object"> + </argument> + <argument index="1" name="event" type="InputEvent"> + </argument> + <argument index="2" name="click_pos" type="Vector3"> + </argument> + <argument index="3" name="click_normal" type="Vector3"> + </argument> + <argument index="4" name="shape_idx" type="int"> + </argument> + <description> + </description> + </method> <method name="add_shape" > <argument index="0" name="shape" type="Shape"> </argument> @@ -6093,6 +6425,30 @@ <description> </description> </method> + <method name="set_ray_pickable" > + <argument index="0" name="ray_pickable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_ray_pickable" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_capture_input_on_drag" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_capture_input_on_drag" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="get_rid" qualifiers="const" > <return type="RID"> </return> @@ -6100,6 +6456,30 @@ </description> </method> </methods> + <signals> + <signal name="mouse_enter"> + <description> + </description> + </signal> + <signal name="input_event"> + <argument index="0" name="camera" type="Object"> + </argument> + <argument index="1" name="event" type="InputEvent"> + </argument> + <argument index="2" name="click_pos" type="Vector3"> + </argument> + <argument index="3" name="click_normal" type="Vector3"> + </argument> + <argument index="4" name="shape_idx" type="int"> + </argument> + <description> + </description> + </signal> + <signal name="mouse_exit"> + <description> + </description> + </signal> + </signals> <constants> </constants> </class> @@ -6201,6 +6581,52 @@ <constants> </constants> </class> +<class name="CollisionPolygon" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_polygon" > + <argument index="0" name="polygon" type="Vector2Array"> + </argument> + <description> + </description> + </method> + <method name="get_polygon" qualifiers="const" > + <return type="Vector2Array"> + </return> + <description> + </description> + </method> + <method name="set_depth" > + <argument index="0" name="depth" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_depth" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_build_mode" > + <argument index="0" name="arg0" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_build_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="CollisionPolygon2D" inherits="Node2D" category="Core"> <brief_description> Editor-Only class. @@ -6259,7 +6685,7 @@ </description> </method> <method name="gray" > - <return type="real"> + <return type="float"> </return> <description> Convert the color to gray. @@ -6277,7 +6703,7 @@ </return> <argument index="0" name="b" type="Color"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> Return the linear interpolation with another color. @@ -6307,24 +6733,38 @@ </description> </method> <method name="Color" > - <argument index="0" name="r" type="real"> + <argument index="0" name="r" type="float"> </argument> - <argument index="1" name="g" type="real"> + <argument index="1" name="g" type="float"> </argument> - <argument index="2" name="b" type="real"> + <argument index="2" name="b" type="float"> </argument> - <argument index="3" name="a" type="real"> + <argument index="3" name="a" type="float"> </argument> <description> Construct the color from an RGBA profile. </description> </method> <method name="Color" > - <argument index="0" name="r" type="real"> + <argument index="0" name="r" type="float"> </argument> - <argument index="1" name="g" type="real"> + <argument index="1" name="g" type="float"> </argument> - <argument index="2" name="b" type="real"> + <argument index="2" name="b" type="float"> + </argument> + <description> + Construct the color from an RGBA profile. + </description> + </method> + <method name="Color" > + <argument index="0" name="from" type="int"> + </argument> + <description> + Construct the color from an RGBA profile. + </description> + </method> + <method name="Color" > + <argument index="0" name="from" type="String"> </argument> <description> Construct the color from an RGBA profile. @@ -6332,19 +6772,19 @@ </method> </methods> <members> - <member name="r" type="real"> + <member name="r" type="float"> </member> - <member name="g" type="real"> + <member name="g" type="float"> </member> - <member name="b" type="real"> + <member name="b" type="float"> </member> - <member name="a" type="real"> + <member name="a" type="float"> </member> - <member name="h" type="real"> + <member name="h" type="float"> </member> - <member name="s" type="real"> + <member name="s" type="float"> </member> - <member name="v" type="real"> + <member name="v" type="float"> </member> </members> <constants> @@ -6466,6 +6906,18 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="value_width" type="int"> + </theme_item> + <theme_item name="value_height" type="int"> + </theme_item> + <theme_item name="color_width" type="int"> + </theme_item> + <theme_item name="label_width" type="int"> + </theme_item> + <theme_item name="hseparator" type="int"> + </theme_item> + </theme_items> </class> <class name="ColorPickerButton" inherits="Button" category="Core"> <brief_description> @@ -6508,6 +6960,30 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="font_color_disabled" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="font_color_pressed" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="pressed" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="disabled" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="ConcavePolygonShape" inherits="Shape" category="Core"> <brief_description> @@ -6561,6 +7037,44 @@ <constants> </constants> </class> +<class name="ConeTwistJoint" inherits="Joint" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_param" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + <constant name="PARAM_SWING_SPAN" value="0"> + </constant> + <constant name="PARAM_TWIST_SPAN" value="1"> + </constant> + <constant name="PARAM_BIAS" value="2"> + </constant> + <constant name="PARAM_SOFTNESS" value="3"> + </constant> + <constant name="PARAM_RELAXATION" value="4"> + </constant> + <constant name="PARAM_MAX" value="5"> + </constant> + </constants> +</class> <class name="ConfigFile" inherits="Reference" category="Core"> <brief_description> </brief_description> @@ -6800,7 +7314,7 @@ <method name="set_margin" > <argument index="0" name="margin" type="int"> </argument> - <argument index="1" name="offset" type="real"> + <argument index="1" name="offset" type="float"> </argument> <description> Set a margin offset. Margin can be one of (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Offset value being set depends on the anchor mode. @@ -6811,7 +7325,7 @@ </argument> <argument index="1" name="anchor_mode" type="int"> </argument> - <argument index="2" name="offset" type="real"> + <argument index="2" name="offset" type="float"> </argument> <description> Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM), and also set its offset. This is a helper (see [method set_anchor] and [method set_margin]). @@ -6859,7 +7373,7 @@ </description> </method> <method name="get_margin" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="margin" type="int"> </argument> @@ -6987,14 +7501,14 @@ </description> </method> <method name="set_stretch_ratio" > - <argument index="0" name="ratio" type="real"> + <argument index="0" name="ratio" type="float"> </argument> <description> Hint for containers, set the stretch ratio. This value is relative to other stretch ratio, so if this control has 2 and another has 1, this one will be twice as big. </description> </method> <method name="get_stretch_ratio" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Hint for containers, return the stretch ratio. This value is relative to other stretch ratio, so if this control has 2 and another has 1, this one will be twice as big. @@ -7282,6 +7796,8 @@ <constant name="ANCHOR_RATIO" value="2"> X and Y are a ratio (0 to 1) relative to the parent size 0 is left/top, 1 is right/bottom. </constant> + <constant name="ANCHOR_CENTER" value="3"> + </constant> <constant name="FOCUS_NONE" value="0"> Control can't acquire focus. </constant> @@ -7476,13 +7992,13 @@ </description> </method> <method name="set_lossy_storage_quality" > - <argument index="0" name="quality" type="real"> + <argument index="0" name="quality" type="float"> </argument> <description> </description> </method> <method name="get_lossy_storage_quality" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -7536,6 +8052,8 @@ </argument> <argument index="2" name="out" type="Vector2" default="Vector2(0,0)"> </argument> + <argument index="3" name="atpos" type="int" default="-1"> + </argument> <description> </description> </method> @@ -7598,50 +8116,48 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> </description> </method> - <method name="bake" qualifiers="const" > - <return type="Vector2Array"> + <method name="interpolatef" qualifiers="const" > + <return type="Vector2"> </return> - <argument index="0" name="subdivs" type="int" default="10"> + <argument index="0" name="fofs" type="float"> </argument> <description> </description> </method> - <method name="set_points_in" > - <argument index="0" name="arg0" type="Vector2Array"> - </argument> - <description> - </description> - </method> - <method name="set_points_out" > - <argument index="0" name="arg0" type="Vector2Array"> + <method name="set_bake_interval" > + <argument index="0" name="distance" type="float"> </argument> <description> </description> </method> - <method name="set_points_pos" > - <argument index="0" name="arg0" type="Vector2Array"> - </argument> + <method name="get_bake_interval" qualifiers="const" > + <return type="float"> + </return> <description> </description> </method> - <method name="get_points_in" qualifiers="const" > - <return type="Vector2Array"> + <method name="get_baked_length" qualifiers="const" > + <return type="float"> </return> <description> </description> </method> - <method name="get_points_out" qualifiers="const" > - <return type="Vector2Array"> + <method name="interpolate_baked" qualifiers="const" > + <return type="Vector2"> </return> + <argument index="0" name="offset" type="float"> + </argument> + <argument index="1" name="cubic" type="bool" default="false"> + </argument> <description> </description> </method> - <method name="get_points_pos" qualifiers="const" > + <method name="get_baked_points" qualifiers="const" > <return type="Vector2Array"> </return> <description> @@ -7694,13 +8210,13 @@ <method name="set_point_tilt" > <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="tilt" type="real"> + <argument index="1" name="tilt" type="float"> </argument> <description> </description> </method> <method name="get_point_tilt" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="idx" type="int"> </argument> @@ -7750,7 +8266,7 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> </description> @@ -7758,25 +8274,25 @@ <method name="interpolatef" qualifiers="const" > <return type="Vector3"> </return> - <argument index="0" name="fofs" type="real"> + <argument index="0" name="fofs" type="float"> </argument> <description> </description> </method> <method name="set_bake_interval" > - <argument index="0" name="distance" type="real"> + <argument index="0" name="distance" type="float"> </argument> <description> </description> </method> <method name="get_bake_interval" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_baked_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -7784,7 +8300,7 @@ <method name="interpolate_baked" qualifiers="const" > <return type="Vector3"> </return> - <argument index="0" name="offset" type="real"> + <argument index="0" name="offset" type="float"> </argument> <argument index="1" name="cubic" type="bool" default="false"> </argument> @@ -7816,56 +8332,56 @@ </description> <methods> <method name="set_length" > - <argument index="0" name="length" type="real"> + <argument index="0" name="length" type="float"> </argument> <description> Set the maximum length of the sprint joint. </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the maximum length of the sprint joint. </description> </method> <method name="set_rest_length" > - <argument index="0" name="rest_length" type="real"> + <argument index="0" name="rest_length" type="float"> </argument> <description> Set the resting length of the sprint joint. The joint will always try to go to back this length when pulled apart. </description> </method> <method name="get_rest_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the resting length of the sprint joint. The joint will always try to go to back this length when pulled apart. </description> </method> <method name="set_stiffness" > - <argument index="0" name="stiffness" type="real"> + <argument index="0" name="stiffness" type="float"> </argument> <description> Set the stiffness of the spring joint. </description> </method> <method name="get_stiffness" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the stiffness of the spring joint. </description> </method> <method name="set_damping" > - <argument index="0" name="damping" type="real"> + <argument index="0" name="damping" type="float"> </argument> <description> Set the damping of the spring joint. </description> </method> <method name="get_damping" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the damping of the spring joint. @@ -7973,13 +8489,13 @@ <method name="set_shadow_param" > <argument index="0" name="param" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_shadow_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="param" type="int"> </argument> @@ -7992,7 +8508,9 @@ </constant> <constant name="SHADOW_PERSPECTIVE" value="1"> </constant> - <constant name="SHADOW_PARALLEL_SPLIT" value="2"> + <constant name="SHADOW_PARALLEL_2_SPLITS" value="2"> + </constant> + <constant name="SHADOW_PARALLEL_4_SPLITS" value="3"> </constant> <constant name="SHADOW_PARAM_MAX_DISTANCE" value="0"> </constant> @@ -8090,6 +8608,14 @@ <description> </description> </method> + <method name="dir_exists" > + <return type="bool"> + </return> + <argument index="0" name="name" type="String"> + </argument> + <description> + </description> + </method> <method name="get_space_left" > <return type="int"> </return> @@ -8128,38 +8654,6 @@ <constants> </constants> </class> -<class name="EditableShape" inherits="Spatial" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - </methods> - <constants> - </constants> -</class> -<class name="EditableSphere" inherits="EditableShape" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - <method name="set_radius" > - <argument index="0" name="radius" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_radius" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> <class name="EditorImportPlugin" inherits="Reference" category="Core"> <brief_description> </brief_description> @@ -8488,67 +8982,97 @@ </constant> <constant name="BG_PARAM_ENERGY" value="3"> </constant> - <constant name="BG_PARAM_MAX" value="5"> + <constant name="BG_PARAM_GLOW" value="5"> + </constant> + <constant name="BG_PARAM_MAX" value="6"> + </constant> + <constant name="FX_AMBIENT_LIGHT" value="0"> + </constant> + <constant name="FX_FXAA" value="1"> + </constant> + <constant name="FX_GLOW" value="2"> + </constant> + <constant name="FX_DOF_BLUR" value="3"> + </constant> + <constant name="FX_HDR" value="4"> + </constant> + <constant name="FX_FOG" value="5"> + </constant> + <constant name="FX_BCS" value="6"> + </constant> + <constant name="FX_SRGB" value="7"> + </constant> + <constant name="FX_MAX" value="8"> + </constant> + <constant name="FX_BLUR_BLEND_MODE_ADDITIVE" value="0"> + </constant> + <constant name="FX_BLUR_BLEND_MODE_SCREEN" value="1"> + </constant> + <constant name="FX_BLUR_BLEND_MODE_SOFTLIGHT" value="2"> + </constant> + <constant name="FX_HDR_TONE_MAPPER_LINEAR" value="0"> </constant> - <constant name="FX_GLOW" value="0"> + <constant name="FX_HDR_TONE_MAPPER_LOG" value="1"> </constant> - <constant name="FX_DOF_BLUR" value="1"> + <constant name="FX_HDR_TONE_MAPPER_REINHARDT" value="2"> </constant> - <constant name="FX_HDR" value="2"> + <constant name="FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE" value="3"> </constant> - <constant name="FX_FOG" value="3"> + <constant name="FX_PARAM_AMBIENT_LIGHT_COLOR" value="0"> </constant> - <constant name="FX_BCS" value="4"> + <constant name="FX_PARAM_AMBIENT_LIGHT_ENERGY" value="1"> </constant> - <constant name="FX_GAMMA" value="5"> + <constant name="FX_PARAM_GLOW_BLUR_PASSES" value="2"> </constant> - <constant name="FX_MAX" value="6"> + <constant name="FX_PARAM_GLOW_BLUR_SCALE" value="3"> </constant> - <constant name="FX_PARAM_GLOW_BLUR_PASSES" value="0"> + <constant name="FX_PARAM_GLOW_BLUR_STRENGTH" value="4"> </constant> - <constant name="FX_PARAM_GLOW_BLOOM" value="1"> + <constant name="FX_PARAM_GLOW_BLUR_BLEND_MODE" value="5"> </constant> - <constant name="FX_PARAM_GLOW_BLOOM_TRESHOLD" value="2"> + <constant name="FX_PARAM_GLOW_BLOOM" value="6"> </constant> - <constant name="FX_PARAM_DOF_BLUR_PASSES" value="3"> + <constant name="FX_PARAM_GLOW_BLOOM_TRESHOLD" value="7"> </constant> - <constant name="FX_PARAM_DOF_BLUR_BEGIN" value="4"> + <constant name="FX_PARAM_DOF_BLUR_PASSES" value="8"> </constant> - <constant name="FX_PARAM_DOF_BLUR_RANGE" value="5"> + <constant name="FX_PARAM_DOF_BLUR_BEGIN" value="9"> </constant> - <constant name="FX_PARAM_HDR_EXPOSURE" value="6"> + <constant name="FX_PARAM_DOF_BLUR_RANGE" value="10"> </constant> - <constant name="FX_PARAM_HDR_SCALAR" value="7"> + <constant name="FX_PARAM_HDR_TONEMAPPER" value="11"> </constant> - <constant name="FX_PARAM_HDR_GLOW_TRESHOLD" value="8"> + <constant name="FX_PARAM_HDR_EXPOSURE" value="12"> </constant> - <constant name="FX_PARAM_HDR_GLOW_SCALE" value="9"> + <constant name="FX_PARAM_HDR_WHITE" value="13"> </constant> - <constant name="FX_PARAM_HDR_MIN_LUMINANCE" value="10"> + <constant name="FX_PARAM_HDR_GLOW_TRESHOLD" value="14"> </constant> - <constant name="FX_PARAM_HDR_MAX_LUMINANCE" value="11"> + <constant name="FX_PARAM_HDR_GLOW_SCALE" value="15"> </constant> - <constant name="FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED" value="12"> + <constant name="FX_PARAM_HDR_MIN_LUMINANCE" value="16"> </constant> - <constant name="FX_PARAM_FOG_BEGIN" value="13"> + <constant name="FX_PARAM_HDR_MAX_LUMINANCE" value="17"> </constant> - <constant name="FX_PARAM_FOG_ATTENUATION" value="16"> + <constant name="FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED" value="18"> </constant> - <constant name="FX_PARAM_FOG_BEGIN_COLOR" value="14"> + <constant name="FX_PARAM_FOG_BEGIN" value="19"> </constant> - <constant name="FX_PARAM_FOG_END_COLOR" value="15"> + <constant name="FX_PARAM_FOG_ATTENUATION" value="22"> </constant> - <constant name="FX_PARAM_FOG_BG" value="17"> + <constant name="FX_PARAM_FOG_BEGIN_COLOR" value="20"> </constant> - <constant name="FX_PARAM_BCS_BRIGHTNESS" value="18"> + <constant name="FX_PARAM_FOG_END_COLOR" value="21"> </constant> - <constant name="FX_PARAM_BCS_CONTRAST" value="19"> + <constant name="FX_PARAM_FOG_BG" value="23"> </constant> - <constant name="FX_PARAM_BCS_SATURATION" value="20"> + <constant name="FX_PARAM_BCS_BRIGHTNESS" value="24"> </constant> - <constant name="FX_PARAM_GAMMA" value="21"> + <constant name="FX_PARAM_BCS_CONTRAST" value="25"> </constant> - <constant name="FX_PARAM_MAX" value="22"> + <constant name="FX_PARAM_BCS_SATURATION" value="26"> + </constant> + <constant name="FX_PARAM_MAX" value="27"> </constant> </constants> </class> @@ -8559,13 +9083,13 @@ </description> <methods> <method name="set_stream" > - <argument index="0" name="stream" type="Stream"> + <argument index="0" name="stream" type="EventStream"> </argument> <description> </description> </method> <method name="get_stream" qualifiers="const" > - <return type="Stream"> + <return type="EventStream"> </return> <description> </description> @@ -8609,49 +9133,49 @@ </description> </method> <method name="set_volume" > - <argument index="0" name="volume" type="real"> + <argument index="0" name="volume" type="float"> </argument> <description> </description> </method> <method name="get_volume" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_pitch_scale" > - <argument index="0" name="pitch_scale" type="real"> + <argument index="0" name="pitch_scale" type="float"> </argument> <description> </description> </method> <method name="get_pitch_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_tempo_scale" > - <argument index="0" name="tempo_scale" type="real"> + <argument index="0" name="tempo_scale" type="float"> </argument> <description> </description> </method> <method name="get_tempo_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_volume_db" > - <argument index="0" name="db" type="real"> + <argument index="0" name="db" type="float"> </argument> <description> </description> </method> <method name="get_volume_db" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -8669,13 +9193,13 @@ </description> </method> <method name="get_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="seek_pos" > - <argument index="0" name="time" type="real"> + <argument index="0" name="time" type="float"> </argument> <description> </description> @@ -8695,13 +9219,13 @@ <method name="set_channel_volume" > <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="channel_volume" type="real"> + <argument index="1" name="channel_volume" type="float"> </argument> <description> </description> </method> <method name="get_channel_volumeidx" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -8709,13 +9233,13 @@ </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_channel_last_note_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -8752,6 +9276,30 @@ <description> </description> <methods> + <method name="open_encrypted" > + <return type="int"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="mode_flags" type="int"> + </argument> + <argument index="2" name="key" type="RawArray"> + </argument> + <description> + </description> + </method> + <method name="open_encrypted_with_pass" > + <return type="int"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="mode_flags" type="int"> + </argument> + <argument index="2" name="pass" type="String"> + </argument> + <description> + </description> + </method> <method name="open" > <return type="int"> </return> @@ -8827,19 +9375,19 @@ </description> </method> <method name="get_float" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_double" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_real" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -8917,19 +9465,19 @@ </description> </method> <method name="store_float" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> </method> <method name="store_double" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> </method> <method name="store_real" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> @@ -9123,6 +9671,12 @@ <constant name="ACCESS_FILESYSTEM" value="2"> </constant> </constants> + <theme_items> + <theme_item name="files_disabled" type="Color"> + </theme_item> + <theme_item name="folder" type="Texture"> + </theme_item> + </theme_items> </class> <class name="FixedMaterial" inherits="Material" category="Core"> <brief_description> @@ -9214,26 +9768,26 @@ Returns the special transform used to post-transform UV coordinates of the uv_xfrom tecoord mode: TEXCOORD_UV_TRANSFORM </description> </method> - <method name="set_point_size" > - <argument index="0" name="size" type="real"> + <method name="set_light_shader" > + <argument index="0" name="shader" type="int"> </argument> <description> </description> </method> - <method name="get_point_size" qualifiers="const" > - <return type="real"> + <method name="get_light_shader" qualifiers="const" > + <return type="int"> </return> <description> </description> </method> - <method name="set_detail_blend_mode" > - <argument index="0" name="mode" type="int"> + <method name="set_point_size" > + <argument index="0" name="size" type="float"> </argument> <description> </description> </method> - <method name="get_detail_blend_mode" qualifiers="const" > - <return type="int"> + <method name="get_point_size" qualifiers="const" > + <return type="float"> </return> <description> </description> @@ -9283,234 +9837,8 @@ </constant> <constant name="FLAG_USE_POINT_SIZE" value="2"> </constant> - </constants> -</class> -<class name="FollowCamera" inherits="Camera" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - <method name="set_orbit" > - <argument index="0" name="orbit" type="Vector2"> - </argument> - <description> - </description> - </method> - <method name="get_orbit" qualifiers="const" > - <return type="Vector2"> - </return> - <description> - </description> - </method> - <method name="set_orbit_x" > - <argument index="0" name="x" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_orbit_y" > - <argument index="0" name="y" type="real"> - </argument> - <description> - </description> - </method> - <method name="set_min_orbit_x" > - <argument index="0" name="x" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_min_orbit_x" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_max_orbit_x" > - <argument index="0" name="x" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_max_orbit_x" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_height" > - <argument index="0" name="height" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_height" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_inclination" > - <argument index="0" name="inclination" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_inclination" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="rotate_orbit" > - <argument index="0" name="arg0" type="Vector2"> - </argument> - <description> - </description> - </method> - <method name="set_distance" > - <argument index="0" name="distance" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_distance" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_max_distance" > - <argument index="0" name="max_distance" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_max_distance" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_min_distance" > - <argument index="0" name="min_distance" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_min_distance" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_clip" > - <argument index="0" name="enable" type="bool"> - </argument> - <description> - </description> - </method> - <method name="has_clip" qualifiers="const" > - <return type="bool"> - </return> - <description> - </description> - </method> - <method name="set_autoturn" > - <argument index="0" name="enable" type="bool"> - </argument> - <description> - </description> - </method> - <method name="has_autoturn" qualifiers="const" > - <return type="bool"> - </return> - <description> - </description> - </method> - <method name="set_autoturn_tolerance" > - <argument index="0" name="degrees" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_autoturn_tolerance" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_autoturn_speed" > - <argument index="0" name="speed" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_autoturn_speed" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_smoothing" > - <argument index="0" name="enable" type="bool"> - </argument> - <description> - </description> - </method> - <method name="has_smoothing" qualifiers="const" > - <return type="bool"> - </return> - <description> - </description> - </method> - <method name="set_rotation_smoothing" > - <argument index="0" name="amount" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_rotation_smoothing" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_translation_smoothing" > - <argument index="0" name="amount" type="real"> - </argument> - <description> - </description> - </method> - <method name="get_translation_smoothing" qualifiers="const" > - <return type="real"> - </return> - <description> - </description> - </method> - <method name="set_use_lookat_target" > - <argument index="0" name="use" type="bool"> - </argument> - <argument index="1" name="lookat" type="Vector3" default="Vector3(0, 0, 0)"> - </argument> - <description> - </description> - </method> - <method name="set_up_vector" > - <argument index="0" name="vector" type="Vector3"> - </argument> - <description> - </description> - </method> - <method name="get_up_vector" qualifiers="const" > - <return type="Vector3"> - </return> - <description> - </description> - </method> - </methods> - <constants> + <constant name="FLAG_DISCARD_ALPHA" value="3"> + </constant> </constants> </class> <class name="Font" inherits="Resource" category="Core"> @@ -9522,35 +9850,35 @@ </description> <methods> <method name="set_height" > - <argument index="0" name="px" type="real"> + <argument index="0" name="px" type="float"> </argument> <description> Set the total font height (ascent plus descent) in pixels. </description> </method> <method name="get_height" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the total font height (ascent plus descent) in pixels. </description> </method> <method name="set_ascent" > - <argument index="0" name="px" type="real"> + <argument index="0" name="px" type="float"> </argument> <description> Set the font ascent (number of pixels above the baseline). </description> </method> <method name="get_ascent" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the font ascent (number of pixels above the baseline). </description> </method> <method name="get_descent" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the font descent (number of pixels below the baseline). @@ -9594,7 +9922,7 @@ </argument> <argument index="3" name="align" type="Vector2" default="Vector2(0,0)"> </argument> - <argument index="4" name="advance" type="real" default="-1"> + <argument index="4" name="advance" type="float" default="-1"> </argument> <description> Add a character to the font, where "character" is the unicode value, "texture" is the texture index, "rect" is the region in the texture (in pixels!), "align" is the (optional) alignment for the character and "advance" is the (optional) advance. @@ -9641,7 +9969,7 @@ </description> </method> <method name="draw_char" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="canvas_item" type="RID"> </argument> @@ -9709,6 +10037,28 @@ <constants> </constants> </class> +<class name="GDFunctionState" inherits="Reference" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="resume" > + <argument index="0" name="arg" type="var" default="NULL"> + </argument> + <description> + </description> + </method> + <method name="is_valid" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="GDNativeClass" inherits="Reference" category="Core"> <brief_description> </brief_description> @@ -9737,6 +10087,150 @@ <constants> </constants> </class> +<class name="Generic6DOFJoint" inherits="Joint" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_param_x" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param_x" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_param_y" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param_y" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_param_z" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param_z" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_flag_x" > + <argument index="0" name="flag" type="int"> + </argument> + <argument index="1" name="value" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_flag_x" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="flag" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_flag_y" > + <argument index="0" name="flag" type="int"> + </argument> + <argument index="1" name="value" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_flag_y" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="flag" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_flag_z" > + <argument index="0" name="flag" type="int"> + </argument> + <argument index="1" name="value" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_flag_z" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="flag" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + <constant name="PARAM_LINEAR_LOWER_LIMIT" value="0"> + </constant> + <constant name="PARAM_LINEAR_UPPER_LIMIT" value="1"> + </constant> + <constant name="PARAM_LINEAR_LIMIT_SOFTNESS" value="2"> + </constant> + <constant name="PARAM_LINEAR_RESTITUTION" value="3"> + </constant> + <constant name="PARAM_LINEAR_DAMPING" value="4"> + </constant> + <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="5"> + </constant> + <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="6"> + </constant> + <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="7"> + </constant> + <constant name="PARAM_ANGULAR_DAMPING" value="8"> + </constant> + <constant name="PARAM_ANGULAR_RESTITUTION" value="9"> + </constant> + <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="10"> + </constant> + <constant name="PARAM_ANGULAR_ERP" value="11"> + </constant> + <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="12"> + </constant> + <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="13"> + </constant> + <constant name="PARAM_MAX" value="14"> + </constant> + <constant name="FLAG_ENABLE_LINEAR_LIMIT" value="0"> + </constant> + <constant name="FLAG_ENABLE_ANGULAR_LIMIT" value="1"> + </constant> + <constant name="FLAG_ENABLE_MOTOR" value="2"> + </constant> + <constant name="FLAG_MAX" value="3"> + </constant> + </constants> +</class> <class name="Geometry" inherits="Object" category="Core"> <brief_description> </brief_description> @@ -9754,9 +10248,9 @@ <method name="build_cylinder_planes" > <return type="Array"> </return> - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> - <argument index="1" name="height" type="real"> + <argument index="1" name="height" type="float"> </argument> <argument index="2" name="sides" type="int"> </argument> @@ -9768,9 +10262,9 @@ <method name="build_capsule_planes" > <return type="Array"> </return> - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> - <argument index="1" name="height" type="real"> + <argument index="1" name="height" type="float"> </argument> <argument index="2" name="sides" type="int"> </argument> @@ -9782,7 +10276,7 @@ </description> </method> <method name="segment_intersects_circle" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="segment_from" type="Vector2"> </argument> @@ -9790,7 +10284,7 @@ </argument> <argument index="2" name="circle_pos" type="Vector2"> </argument> - <argument index="3" name="circle_radius" type="real"> + <argument index="3" name="circle_radius" type="float"> </argument> <description> </description> @@ -9847,6 +10341,14 @@ <description> </description> </method> + <method name="get_uv84_normal_bit" > + <return type="int"> + </return> + <argument index="0" name="normal" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="ray_intersects_triangle" > <argument index="0" name="from" type="Vector3"> </argument> @@ -9884,7 +10386,7 @@ </argument> <argument index="2" name="spos" type="Vector3"> </argument> - <argument index="3" name="sradius" type="real"> + <argument index="3" name="sradius" type="float"> </argument> <description> </description> @@ -9896,9 +10398,9 @@ </argument> <argument index="1" name="to" type="Vector3"> </argument> - <argument index="2" name="height" type="real"> + <argument index="2" name="height" type="float"> </argument> - <argument index="3" name="radius" type="real"> + <argument index="3" name="radius" type="float"> </argument> <description> </description> @@ -9923,6 +10425,14 @@ <description> </description> </method> + <method name="make_atlas" > + <return type="Dictionary"> + </return> + <argument index="0" name="sizes" type="Vector2Array"> + </argument> + <description> + </description> + </method> </methods> <constants> </constants> @@ -9966,36 +10476,42 @@ </description> </method> <method name="set_draw_range_begin" > - <argument index="0" name="mode" type="real"> + <argument index="0" name="mode" type="float"> </argument> <description> </description> </method> <method name="get_draw_range_begin" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_draw_range_end" > - <argument index="0" name="mode" type="real"> + <argument index="0" name="mode" type="float"> </argument> <description> </description> </method> <method name="get_draw_range_end" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> - </methods> - <signals> - <signal name="visibility_changed"> + <method name="set_baked_light_texture_id" > + <argument index="0" name="id" type="int"> + </argument> <description> </description> - </signal> - </signals> + </method> + <method name="get_baked_light_texture_id" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + </methods> <constants> <constant name="FLAG_VISIBLE" value="0"> </constant> @@ -10011,7 +10527,7 @@ </constant> <constant name="FLAG_VISIBLE_IN_ALL_ROOMS" value="6"> </constant> - <constant name="FLAG_MAX" value="7"> + <constant name="FLAG_MAX" value="8"> </constant> </constants> </class> @@ -10115,6 +10631,14 @@ <description> </description> </method> + <method name="load_resource_pack" > + <return type="bool"> + </return> + <argument index="0" name="arg0" type="String"> + </argument> + <description> + </description> + </method> </methods> <constants> </constants> @@ -10140,6 +10664,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="separation" type="int"> + </theme_item> + </theme_items> </class> <class name="GridMap" inherits="Spatial" category="Core"> <brief_description> @@ -10172,13 +10700,13 @@ </description> </method> <method name="set_cell_size" > - <argument index="0" name="size" type="real"> + <argument index="0" name="size" type="float"> </argument> <description> </description> </method> <method name="get_cell_size" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -10287,7 +10815,7 @@ <description> </description> </method> - <method name="crate_area" > + <method name="create_area" > <return type="int"> </return> <argument index="0" name="id" type="int"> @@ -10340,13 +10868,13 @@ <method name="area_set_portal_disable_distance" > <argument index="0" name="area" type="int"> </argument> - <argument index="1" name="distance" type="real"> + <argument index="1" name="distance" type="float"> </argument> <description> </description> </method> <method name="area_get_portal_disable_distance" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="area" type="int"> </argument> @@ -10385,6 +10913,18 @@ <description> </description> </method> + <method name="set_use_baked_light" > + <argument index="0" name="use" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_using_baked_light" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="clear" > <description> </description> @@ -10404,28 +10944,28 @@ </description> <methods> <method name="set_length" > - <argument index="0" name="length" type="real"> + <argument index="0" name="length" type="float"> </argument> <description> Set the length of the groove. </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the length of the groove. </description> </method> <method name="set_initial_offset" > - <argument index="0" name="offset" type="real"> + <argument index="0" name="offset" type="float"> </argument> <description> Set the initial offset of the groove on body A. </description> </method> <method name="get_initial_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Set the final offset of the groove on body A. @@ -10446,6 +10986,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="separation" type="int"> + </theme_item> + </theme_items> </class> <class name="HButtonArray" inherits="ButtonArray" category="Core"> <brief_description> @@ -10458,6 +11002,28 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="button_separator" type="int"> + </theme_item> + <theme_item name="icon_separator" type="int"> + </theme_item> + <theme_item name="font_color_selected" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_selected" type="Font"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="selected" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="HScrollBar" inherits="ScrollBar" category="Core"> <brief_description> @@ -10470,6 +11036,24 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="increment_hilite" type="Texture"> + </theme_item> + <theme_item name="decrement_hilite" type="Texture"> + </theme_item> + <theme_item name="increment" type="Texture"> + </theme_item> + <theme_item name="decrement" type="Texture"> + </theme_item> + <theme_item name="grabber_hilite" type="StyleBox"> + </theme_item> + <theme_item name="grabber" type="StyleBox"> + </theme_item> + <theme_item name="scroll_focus" type="StyleBox"> + </theme_item> + <theme_item name="scroll" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="HSeparator" inherits="Separator" category="Core"> <brief_description> @@ -10482,6 +11066,12 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="separation" type="int"> + </theme_item> + <theme_item name="separator" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="HSlider" inherits="Slider" category="Core"> <brief_description> @@ -10494,6 +11084,20 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="tick" type="Texture"> + </theme_item> + <theme_item name="grabber_hilite" type="Texture"> + </theme_item> + <theme_item name="grabber" type="Texture"> + </theme_item> + <theme_item name="grabber_hilite" type="StyleBox"> + </theme_item> + <theme_item name="slider" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="HSplitContainer" inherits="SplitContainer" category="Core"> <brief_description> @@ -10506,6 +11110,16 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="autohide" type="int"> + </theme_item> + <theme_item name="separation" type="int"> + </theme_item> + <theme_item name="grabber" type="Texture"> + </theme_item> + <theme_item name="bg" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="HTTPClient" inherits="Reference" category="Core"> <brief_description> @@ -10520,6 +11134,10 @@ </argument> <argument index="1" name="port" type="int"> </argument> + <argument index="2" name="use_ssl" type="bool" default="false"> + </argument> + <argument index="3" name="arg3" type="bool" default="true"> + </argument> <description> </description> </method> @@ -10605,6 +11223,18 @@ <description> </description> </method> + <method name="set_blocking_mode" > + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_blocking_mode_enabled" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="get_status" qualifiers="const" > <return type="int"> </return> @@ -10655,6 +11285,8 @@ </constant> <constant name="STATUS_CONNECTION_ERROR" value="8"> </constant> + <constant name="STATUS_SSL_HANDSHAKE_ERROR" value="9"> + </constant> <constant name="RESPONSE_CONTINUE" value="100"> </constant> <constant name="RESPONSE_SWITCHING_PROTOCOLS" value="101"> @@ -10755,6 +11387,72 @@ </constant> </constants> </class> +<class name="HingeJoint" inherits="Joint" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_param" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_flag" > + <argument index="0" name="flag" type="int"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_flag" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="flag" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + <constant name="PARAM_BIAS" value="0"> + </constant> + <constant name="PARAM_LIMIT_UPPER" value="1"> + </constant> + <constant name="PARAM_LIMIT_LOWER" value="2"> + </constant> + <constant name="PARAM_LIMIT_BIAS" value="3"> + </constant> + <constant name="PARAM_LIMIT_SOFTNESS" value="4"> + </constant> + <constant name="PARAM_LIMIT_RELAXATION" value="5"> + </constant> + <constant name="PARAM_MOTOR_TARGET_VELOCITY" value="6"> + </constant> + <constant name="PARAM_MOTOR_MAX_IMPULSE" value="7"> + </constant> + <constant name="PARAM_MAX" value="8"> + </constant> + <constant name="FLAG_USE_LIMIT" value="0"> + </constant> + <constant name="FLAG_ENABLE_MOTOR" value="1"> + </constant> + <constant name="FLAG_MAX" value="2"> + </constant> + </constants> +</class> <class name="IP" inherits="Object" category="Core"> <brief_description> IP Protocol support functions. @@ -10806,6 +11504,12 @@ Erase a queue ID, removing it from the queue if needed. This should be used after a queue is completed to free it and enable more queries to happen. </description> </method> + <method name="get_local_addresses" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> </methods> <constants> <constant name="RESOLVER_STATUS_NONE" value="0"> @@ -10880,6 +11584,20 @@ <description> </description> </method> + <method name="converted" > + <return type="Image"> + </return> + <argument index="0" name="format" type="int" default="0"> + </argument> + <description> + </description> + </method> + <method name="decompressed" > + <return type="Image"> + </return> + <description> + </description> + </method> <method name="empty" > <return type="bool"> </return> @@ -10944,6 +11662,18 @@ <description> </description> </method> + <method name="put_pixel" > + <argument index="0" name="x" type="int"> + </argument> + <argument index="1" name="y" type="int"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <argument index="3" name="mipmap_level" type="int" default="0"> + </argument> + <description> + </description> + </method> <method name="resized" > <return type="Image"> </return> @@ -10956,6 +11686,14 @@ <description> </description> </method> + <method name="save_png" > + <return type="int"> + </return> + <argument index="0" name="path" type="String" default="0"> + </argument> + <description> + </description> + </method> </methods> <constants> <constant name="COMPRESS_BC" value="0"> @@ -11014,48 +11752,6 @@ </constant> </constants> </class> -<class name="ImagePathFinder" inherits="Resource" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - <method name="find_path" > - <return type="Vector2Array"> - </return> - <argument index="0" name="from" type="Vector2"> - </argument> - <argument index="1" name="to" type="Vector2"> - </argument> - <argument index="2" name="optimize" type="bool" default="false"> - </argument> - <description> - </description> - </method> - <method name="get_size" qualifiers="const" > - <return type="Vector2"> - </return> - <description> - </description> - </method> - <method name="is_solid" > - <return type="bool"> - </return> - <argument index="0" name="pos" type="Vector2"> - </argument> - <description> - </description> - </method> - <method name="create_from_image_alpha" > - <argument index="0" name="arg0" type="Image"> - </argument> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> <class name="ImageTexture" inherits="Texture" category="Core"> <brief_description> </brief_description> @@ -11119,13 +11815,13 @@ </description> </method> <method name="set_lossy_storage_quality" > - <argument index="0" name="quality" type="real"> + <argument index="0" name="quality" type="float"> </argument> <description> </description> </method> <method name="get_lossy_storage_quality" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -11134,6 +11830,10 @@ <description> </description> </method> + <method name="premultiply_alpha" > + <description> + </description> + </method> <method name="set_size_override" > <argument index="0" name="size" type="Vector2"> </argument> @@ -11150,6 +11850,78 @@ </constant> </constants> </class> +<class name="ImmediateGeometry" inherits="GeometryInstance" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="begin" > + <argument index="0" name="primitive" type="int"> + </argument> + <argument index="1" name="texture" type="Texture"> + </argument> + <description> + </description> + </method> + <method name="set_normal" > + <argument index="0" name="normal" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="set_tangent" > + <argument index="0" name="tangent" type="Plane"> + </argument> + <description> + </description> + </method> + <method name="set_color" > + <argument index="0" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="set_uv" > + <argument index="0" name="uv" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="set_uv2" > + <argument index="0" name="uv" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="add_vertex" > + <argument index="0" name="color" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="add_sphere" > + <argument index="0" name="lats" type="int"> + </argument> + <argument index="1" name="lons" type="int"> + </argument> + <argument index="2" name="radius" type="float"> + </argument> + <description> + </description> + </method> + <method name="end" > + <description> + </description> + </method> + <method name="clear" > + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Input" inherits="Object" category="Core"> <brief_description> </brief_description> @@ -11191,7 +11963,7 @@ </description> </method> <method name="get_joy_axis" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="device" type="int"> </argument> @@ -11200,6 +11972,14 @@ <description> </description> </method> + <method name="get_joy_name" > + <return type="String"> + </return> + <argument index="0" name="device" type="int"> + </argument> + <description> + </description> + </method> <method name="get_accelerometer" > <return type="Vector3"> </return> @@ -11239,7 +12019,23 @@ <description> </description> </method> + <method name="warp_mouse_pos" > + <argument index="0" name="to" type="Vector2"> + </argument> + <description> + </description> + </method> </methods> + <signals> + <signal name="joy_connection_changed"> + <argument index="0" name="index" type="int"> + </argument> + <argument index="1" name="connected" type="bool"> + </argument> + <description> + </description> + </signal> + </signals> <constants> <constant name="MOUSE_MODE_VISIBLE" value="0"> </constant> @@ -11420,7 +12216,7 @@ </member> <member name="pressed" type="bool"> </member> - <member name="pressure" type="real"> + <member name="pressure" type="float"> </member> </members> <constants> @@ -11480,7 +12276,7 @@ </member> <member name="axis" type="int"> </member> - <member name="value" type="real"> + <member name="value" type="float"> </member> </members> <constants> @@ -11722,9 +12518,9 @@ </member> <member name="relative_pos" type="Vector2"> </member> - <member name="speed_x" type="real"> + <member name="speed_x" type="float"> </member> - <member name="speed_y" type="real"> + <member name="speed_y" type="float"> </member> <member name="speed" type="Vector2"> </member> @@ -11786,21 +12582,21 @@ </member> <member name="index" type="int"> </member> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> <member name="pos" type="Vector2"> </member> - <member name="relative_x" type="real"> + <member name="relative_x" type="float"> </member> - <member name="relative_y" type="real"> + <member name="relative_y" type="float"> </member> <member name="relative_pos" type="Vector2"> </member> - <member name="speed_x" type="real"> + <member name="speed_x" type="float"> </member> - <member name="speed_y" type="real"> + <member name="speed_y" type="float"> </member> <member name="speed" type="Vector2"> </member> @@ -11862,9 +12658,9 @@ </member> <member name="index" type="int"> </member> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> <member name="pos" type="Vector2"> </member> @@ -11900,6 +12696,90 @@ Singleton that manages actions. InputMap has a list of the actions used in InputEvent, which can be modified. </description> <methods> + <method name="has_action" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_action_id" qualifiers="const" > + <return type="int"> + </return> + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_action_from_id" qualifiers="const" > + <return type="String"> + </return> + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="add_action" > + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="erase_action" > + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="action_add_event" > + <argument index="0" name="action" type="String"> + </argument> + <argument index="1" name="event" type="InputEvent"> + </argument> + <description> + </description> + </method> + <method name="action_has_event" > + <return type="bool"> + </return> + <argument index="0" name="action" type="String"> + </argument> + <argument index="1" name="event" type="InputEvent"> + </argument> + <description> + </description> + </method> + <method name="action_erase_event" > + <argument index="0" name="action" type="String"> + </argument> + <argument index="1" name="event" type="InputEvent"> + </argument> + <description> + </description> + </method> + <method name="get_action_list" > + <return type="bool"> + </return> + <argument index="0" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="event_is_action" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="event" type="InputEvent"> + </argument> + <argument index="1" name="action" type="String"> + </argument> + <description> + </description> + </method> + <method name="load_from_globals" > + <description> + </description> + </method> </methods> <constants> </constants> @@ -11981,19 +12861,19 @@ </description> </method> <method name="set_target" > - <argument index="0" name="target" type="Object"> + <argument index="0" name="target" type="Camera"> </argument> <description> </description> </method> <method name="set_speed" > - <argument index="0" name="speed" type="real"> + <argument index="0" name="speed" type="float"> </argument> <description> </description> </method> <method name="get_speed" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -12014,6 +12894,52 @@ <constants> </constants> </class> +<class name="Joint" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_node_a" > + <argument index="0" name="node" type="NodePath"> + </argument> + <description> + </description> + </method> + <method name="get_node_a" qualifiers="const" > + <return type="NodePath"> + </return> + <description> + </description> + </method> + <method name="set_node_b" > + <argument index="0" name="node" type="NodePath"> + </argument> + <description> + </description> + </method> + <method name="get_node_b" qualifiers="const" > + <return type="NodePath"> + </return> + <description> + </description> + </method> + <method name="set_solver_priority" > + <argument index="0" name="priority" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_solver_priority" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Joint2D" inherits="Node2D" category="Core"> <brief_description> Base node for all joint constraints in 2D phyisics. @@ -12051,13 +12977,143 @@ </description> </method> <method name="set_bias" > - <argument index="0" name="bias" type="real"> + <argument index="0" name="bias" type="float"> </argument> <description> </description> </method> <method name="get_bias" qualifiers="const" > - <return type="real"> + <return type="float"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> +<class name="KinematicBody" inherits="PhysicsBody" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="move" > + <return type="Vector3"> + </return> + <argument index="0" name="rel_vec" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="move_to" > + <return type="Vector3"> + </return> + <argument index="0" name="position" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="can_move_to" > + <return type="bool"> + </return> + <argument index="0" name="position" type="Vector3"> + </argument> + <argument index="1" name="arg1" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_colliding" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="get_collision_pos" qualifiers="const" > + <return type="Vector3"> + </return> + <description> + </description> + </method> + <method name="get_collision_normal" qualifiers="const" > + <return type="Vector3"> + </return> + <description> + </description> + </method> + <method name="get_collider_velocity" qualifiers="const" > + <return type="Vector3"> + </return> + <description> + </description> + </method> + <method name="get_collider" qualifiers="const" > + <description> + </description> + </method> + <method name="get_collider_shape" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_collide_with_static_bodies" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="can_collide_with_static_bodies" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_collide_with_kinematic_bodies" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="can_collide_with_kinematic_bodies" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_collide_with_rigid_bodies" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="can_collide_with_rigid_bodies" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_collide_with_character_bodies" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="can_collide_with_character_bodies" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_collision_margin" > + <argument index="0" name="pixels" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_collision_margin" qualifiers="const" > + <return type="float"> </return> <description> </description> @@ -12126,6 +13182,16 @@ <description> </description> </method> + <method name="get_collider_shape" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_collider_metadata" qualifiers="const" > + <description> + </description> + </method> <method name="set_collide_with_static_bodies" > <argument index="0" name="enable" type="bool"> </argument> @@ -12175,13 +13241,13 @@ </description> </method> <method name="set_collision_margin" > - <argument index="0" name="pixels" type="real"> + <argument index="0" name="pixels" type="float"> </argument> <description> </description> </method> <method name="get_collision_margin" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -12291,13 +13357,13 @@ </description> </method> <method name="set_percent_visible" > - <argument index="0" name="percent_visible" type="real"> + <argument index="0" name="percent_visible" type="float"> </argument> <description> </description> </method> <method name="get_percent_visible" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -12329,6 +13395,20 @@ Align the whole text by spreading the rows. </constant> </constants> + <theme_items> + <theme_item name="shadow_offset_x" type="int"> + </theme_item> + <theme_item name="shadow_offset_y" type="int"> + </theme_item> + <theme_item name="shadow_as_outline" type="int"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_shadow" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + </theme_items> </class> <class name="LargeTexture" inherits="Texture" category="Core"> <brief_description> @@ -12337,6 +13417,8 @@ </description> <methods> <method name="add_piece" > + <return type="int"> + </return> <argument index="0" name="ofs" type="Vector2"> </argument> <argument index="1" name="texture" type="Texture"> @@ -12344,6 +13426,22 @@ <description> </description> </method> + <method name="set_piece_offset" > + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="ofs" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="set_piece_texture" > + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="texture" type="Texture"> + </argument> + <description> + </description> + </method> <method name="set_size" > <argument index="0" name="size" type="Vector2"> </argument> @@ -12391,13 +13489,13 @@ <method name="set_parameter" > <argument index="0" name="variable" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_parameter" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -12456,6 +13554,42 @@ <description> </description> </method> + <method name="set_bake_mode" > + <argument index="0" name="bake_mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_bake_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_enabled" > + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_enabled" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_editor_only" > + <argument index="0" name="editor_only" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_editor_only" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> </methods> <constants> <constant name="PARAM_RADIUS" value="2"> @@ -12472,11 +13606,17 @@ </constant> <constant name="PARAM_SHADOW_Z_OFFSET" value="6"> </constant> - <constant name="COLOR_AMBIENT" value="0"> + <constant name="COLOR_DIFFUSE" value="0"> + </constant> + <constant name="COLOR_SPECULAR" value="1"> + </constant> + <constant name="BAKE_MODE_DISABLED" value="0"> </constant> - <constant name="COLOR_DIFFUSE" value="1"> + <constant name="BAKE_MODE_INDIRECT" value="1"> </constant> - <constant name="COLOR_SPECULAR" value="2"> + <constant name="BAKE_MODE_INDIRECT_AND_SHADOWS" value="2"> + </constant> + <constant name="BAKE_MODE_FULL" value="3"> </constant> </constants> </class> @@ -12575,9 +13715,11 @@ Return the [i]secret[/i] status of the [LineEdit] (see [method set_secret]). </description> </method> - <method name="select" qualifiers="const" > - <return type="bool"> - </return> + <method name="select" > + <argument index="0" name="from" type="int" default="0"> + </argument> + <argument index="1" name="to" type="int" default="-1"> + </argument> <description> </description> </method> @@ -12600,6 +13742,26 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="minimum_spaces" type="int"> + </theme_item> + <theme_item name="selection_color" type="Color"> + </theme_item> + <theme_item name="cursor_color" type="Color"> + </theme_item> + <theme_item name="font_color_selected" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="read_only" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="LineShape2D" inherits="Shape2D" category="Core"> <brief_description> @@ -12624,14 +13786,14 @@ </description> </method> <method name="set_d" > - <argument index="0" name="d" type="real"> + <argument index="0" name="d" type="float"> </argument> <description> Set the line distance from the origin. </description> </method> <method name="get_d" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the line distance from the origin. @@ -12665,6 +13827,8 @@ </constant> <constant name="NOTIFICATION_WM_UNFOCUS_REQUEST" value="8"> </constant> + <constant name="NOTIFICATION_OS_MEMORY_WARNING" value="9"> + </constant> </constants> </class> <class name="MarginContainer" inherits="Container" category="Core"> @@ -12678,6 +13842,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="margin" type="int"> + </theme_item> + </theme_items> </class> <class name="Marshalls" inherits="Reference" category="Core"> <brief_description> @@ -12729,22 +13897,6 @@ Return a [Material] flag, which toggles on or off a behavior when rendering. See enumeration FLAG_* for a list. </description> </method> - <method name="set_hint" > - <argument index="0" name="hint" type="int"> - </argument> - <argument index="1" name="enable" type="bool"> - </argument> - <description> - </description> - </method> - <method name="get_hint" qualifiers="const" > - <return type="bool"> - </return> - <argument index="0" name="hint" type="int"> - </argument> - <description> - </description> - </method> <method name="set_blend_mode" > <argument index="0" name="mode" type="int"> </argument> @@ -12759,30 +13911,30 @@ Return blend mode for the material, which can be one of BLEND_MODE_MIX (default), BLEND_MODE_ADD, BLEND_MODE_SUB. Keep in mind that only BLEND_MODE_MIX ensures that the material [i]may[/i] be opaque, any other blend mode will render with alpha blending enabled in raster-based [VisualServer] implementations. </description> </method> - <method name="set_shade_model" > - <argument index="0" name="model" type="int"> + <method name="set_line_width" > + <argument index="0" name="width" type="float"> </argument> <description> + Set the line width for geometry drawn with FLAG_WIREFRAME enabled, or LINE primitives. Note that not all hardware or VisualServer backends support this (like DirectX). </description> </method> - <method name="get_shade_model" qualifiers="const" > - <return type="int"> + <method name="get_line_width" qualifiers="const" > + <return type="float"> </return> <description> + Return the line width for geometry drawn with FLAG_WIREFRAME enabled, or LINE primitives. Note that not all hardware or VisualServer backends support this (like DirectX). </description> </method> - <method name="set_line_width" > - <argument index="0" name="width" type="real"> + <method name="set_depth_draw_mode" > + <argument index="0" name="mode" type="int"> </argument> <description> - Set the line width for geometry drawn with FLAG_WIREFRAME enabled, or LINE primitives. Note that not all hardware or VisualServer backends support this (like DirectX). </description> </method> - <method name="get_line_width" qualifiers="const" > - <return type="real"> + <method name="get_depth_draw_mode" qualifiers="const" > + <return type="int"> </return> <description> - Return the line width for geometry drawn with FLAG_WIREFRAME enabled, or LINE primitives. Note that not all hardware or VisualServer backends support this (like DirectX). </description> </method> </methods> @@ -12801,40 +13953,20 @@ </constant> <constant name="FLAG_ONTOP" value="4"> </constant> - <constant name="FLAG_WIREFRAME" value="5"> - Triangle geometry is drawn as lines if this flag is enabled. + <constant name="FLAG_LIGHTMAP_ON_UV2" value="5"> </constant> - <constant name="FLAG_BILLBOARD_TOGGLE" value="6"> - Geometry world transform is computed as billboard if this flag is enabled, often used for impostors. + <constant name="FLAG_COLOR_ARRAY_SRGB" value="6"> </constant> <constant name="FLAG_MAX" value="7"> Maximum amount of flags </constant> - <constant name="HINT_DECAL" value="0"> - </constant> - <constant name="HINT_OPAQUE_PRE_PASS" value="1"> - </constant> - <constant name="HINT_NO_SHADOW" value="2"> - </constant> - <constant name="HINT_NO_DEPTH_DRAW" value="3"> - </constant> - <constant name="HINT_MAX" value="4"> - </constant> - <constant name="SHADE_MODEL_LAMBERT" value="0"> - </constant> - <constant name="SHADE_MODEL_LAMBERT_WRAP" value="1"> - </constant> - <constant name="SHADE_MODEL_FRESNEL" value="2"> - </constant> - <constant name="SHADE_MODEL_TOON" value="3"> - </constant> - <constant name="SHADE_MODEL_CUSTOM_0" value="4"> + <constant name="DEPTH_DRAW_ALWAYS" value="0"> </constant> - <constant name="SHADE_MODEL_CUSTOM_1" value="5"> + <constant name="DEPTH_DRAW_OPAQUE_ONLY" value="1"> </constant> - <constant name="SHADE_MODEL_CUSTOM_2" value="6"> + <constant name="DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA" value="2"> </constant> - <constant name="SHADE_MODEL_CUSTOM_3" value="7"> + <constant name="DEPTH_DRAW_NEVER" value="3"> </constant> <constant name="BLEND_MODE_MIX" value="0"> Use the regular alpha blending equation (source and dest colors are faded) (default). @@ -12845,6 +13977,10 @@ <constant name="BLEND_MODE_SUB" value="2"> Use substractive blending equation, often used for some smoke effects or types of glass. </constant> + <constant name="BLEND_MODE_MUL" value="3"> + </constant> + <constant name="BLEND_MODE_PREMULT_ALPHA" value="4"> + </constant> </constants> </class> <class name="Matrix3" category="Built-In Types"> @@ -12856,7 +13992,7 @@ </description> <methods> <method name="determinant" > - <return type="real"> + <return type="float"> </return> <description> Return the determinant of the matrix. @@ -12875,6 +14011,12 @@ <description> </description> </method> + <method name="get_scale" > + <return type="Vector3"> + </return> + <description> + </description> + </method> <method name="inverse" > <return type="Matrix3"> </return> @@ -12894,7 +14036,7 @@ </return> <argument index="0" name="axis" type="Vector3"> </argument> - <argument index="1" name="phi" type="real"> + <argument index="1" name="phi" type="float"> </argument> <description> Return the rotated version of the matrix, by a given axis and angle. @@ -12910,7 +14052,7 @@ </description> </method> <method name="tdotx" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="with" type="Vector3"> </argument> @@ -12919,7 +14061,7 @@ </description> </method> <method name="tdoty" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="with" type="Vector3"> </argument> @@ -12928,7 +14070,7 @@ </description> </method> <method name="tdotz" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="with" type="Vector3"> </argument> @@ -12975,7 +14117,7 @@ <method name="Matrix3" > <argument index="0" name="axis" type="Vector3"> </argument> - <argument index="1" name="phi" type="real"> + <argument index="1" name="phi" type="float"> </argument> <description> Create a matrix from 3 axis vectors. @@ -13014,6 +14156,22 @@ <description> </description> </method> + <method name="basis_xform" > + <return type="Matrix32"> + </return> + <argument index="0" name="v" type="var"> + </argument> + <description> + </description> + </method> + <method name="basis_xform_inv" > + <return type="Matrix32"> + </return> + <argument index="0" name="v" type="var"> + </argument> + <description> + </description> + </method> <method name="get_origin" > <return type="Vector2"> </return> @@ -13021,7 +14179,13 @@ </description> </method> <method name="get_rotation" > - <return type="real"> + <return type="float"> + </return> + <description> + </description> + </method> + <method name="get_scale" > + <return type="Vector2"> </return> <description> </description> @@ -13031,7 +14195,7 @@ </return> <argument index="0" name="m" type="Matrix32"> </argument> - <argument index="1" name="c" type="real"> + <argument index="1" name="c" type="float"> </argument> <description> </description> @@ -13051,7 +14215,7 @@ <method name="rotated" > <return type="Matrix32"> </return> - <argument index="0" name="phi" type="real"> + <argument index="0" name="phi" type="float"> </argument> <description> </description> @@ -13100,11 +14264,11 @@ </method> </methods> <members> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> - <member name="o" type="real"> + <member name="o" type="float"> </member> </members> <constants> @@ -13134,6 +14298,28 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="font_color_disabled" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="font_color_pressed" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="pressed" type="StyleBox"> + </theme_item> + <theme_item name="disabled" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="Mesh" inherits="Resource" category="Core"> <brief_description> @@ -13280,6 +14466,22 @@ <description> </description> </method> + <method name="regen_normalmaps" > + <description> + </description> + </method> + <method name="set_custom_aabb" > + <argument index="0" name="aabb" type="AABB"> + </argument> + <description> + </description> + </method> + <method name="get_custom_aabb" qualifiers="const" > + <return type="AABB"> + </return> + <description> + </description> + </method> </methods> <constants> <constant name="NO_INDEX_ARRAY" value="-1"> @@ -13685,6 +14887,18 @@ Return the current [Mesh] resource for the instance. </description> </method> + <method name="set_skeleton_path" > + <argument index="0" name="skeleton_path" type="NodePath"> + </argument> + <description> + </description> + </method> + <method name="get_skeleton_path" > + <return type="NodePath"> + </return> + <description> + </description> + </method> <method name="get_aabb" qualifiers="const" > <return type="AABB"> </return> @@ -13947,6 +15161,172 @@ <constants> </constants> </class> +<class name="Navigation" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="navmesh_create" > + <return type="int"> + </return> + <argument index="0" name="mesh" type="NavigationMesh"> + </argument> + <argument index="1" name="xform" type="Transform"> + </argument> + <argument index="2" name="owner" type="Object" default="NULL"> + </argument> + <description> + </description> + </method> + <method name="navmesh_set_transform" > + <argument index="0" name="id" type="int"> + </argument> + <argument index="1" name="xform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="navmesh_remove" > + <argument index="0" name="id" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_simple_path" > + <return type="Vector3Array"> + </return> + <argument index="0" name="start" type="Vector3"> + </argument> + <argument index="1" name="end" type="Vector3"> + </argument> + <argument index="2" name="optimize" type="bool" default="true"> + </argument> + <description> + </description> + </method> + <method name="get_closest_point_to_segment" > + <return type="Vector3"> + </return> + <argument index="0" name="start" type="Vector3"> + </argument> + <argument index="1" name="end" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="get_closest_point" > + <return type="Vector3"> + </return> + <argument index="0" name="to_point" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="get_closest_point_normal" > + <return type="Vector3"> + </return> + <argument index="0" name="to_point" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="set_up_vector" > + <argument index="0" name="up" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="get_up_vector" qualifiers="const" > + <return type="Vector3"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> +<class name="NavigationMesh" inherits="Resource" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_vertices" > + <argument index="0" name="vertices" type="Vector3Array"> + </argument> + <description> + </description> + </method> + <method name="get_vertices" qualifiers="const" > + <return type="Vector3Array"> + </return> + <description> + </description> + </method> + <method name="add_polygon" > + <argument index="0" name="polygon" type="IntArray"> + </argument> + <description> + </description> + </method> + <method name="get_polygon_count" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_polygon" > + <return type="IntArray"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="clear_polygons" > + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> +<class name="NavigationMeshInstance" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_navigation_mesh" > + <argument index="0" name="navmesh" type="Object"> + </argument> + <description> + </description> + </method> + <method name="get_navigation_mesh" qualifiers="const" > + <return type="Object"> + </return> + <description> + </description> + </method> + <method name="set_enabled" > + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_enabled" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Nil" category="Built-In Types"> <brief_description> </brief_description> @@ -13966,7 +15346,7 @@ </description> </method> <method name="Nil" > - <argument index="0" name="from" type="real"> + <argument index="0" name="from" type="float"> </argument> <description> </description> @@ -14141,18 +15521,16 @@ Finally, when a node is freed, it will free all its children nodes too. </description> <methods> - <method name="_enter_scene" qualifiers="virtual" > + <method name="_enter_tree" qualifiers="virtual" > <description> - Called when entered the scene. </description> </method> - <method name="_exit_scene" qualifiers="virtual" > + <method name="_exit_tree" qualifiers="virtual" > <description> - Called when being removed from the scene. </description> </method> <method name="_fixed_process" qualifiers="virtual" > - <argument index="0" name="delta" type="real"> + <argument index="0" name="delta" type="float"> </argument> <description> Called for fixed processing (synced to the physics). @@ -14166,7 +15544,7 @@ </description> </method> <method name="_process" qualifiers="virtual" > - <argument index="0" name="delta" type="real"> + <argument index="0" name="delta" type="float"> </argument> <description> Called for processing. This is called every frame, with the delta time from the previous frame. @@ -14261,7 +15639,7 @@ <argument index="0" name="path" type="NodePath"> </argument> <description> - Fetch a node. NodePath must be valid (or else error will occur) and can be either the path to child node, a relative path (from the current node to another node), or an absolute path to a node.[br] Note: fetching absolute paths only works when the node is inside the scene tree (see [method is_inside_scene]). Examples. Assume your current node is Character and following tree:[br] + Fetch a node. NodePath must be valid (or else error will occur) and can be either the path to child node, a relative path (from the current node to another node), or an absolute path to a node.[br] Note: fetching absolute paths only works when the node is inside the scene tree (see [method is_inside_scene]). Examples. Assume your current node is Character and following tree:[br] root/[br] root/Character[br] root/Character/Sword[br] @@ -14301,11 +15679,10 @@ <description> </description> </method> - <method name="is_inside_scene" qualifiers="const" > + <method name="is_inside_tree" qualifiers="const" > <return type="bool"> </return> <description> - Return wether the node is inside a scene tree (a tree where the topmost node is a [RootNode]) </description> </method> <method name="is_a_parent_of" qualifiers="const" > @@ -14375,6 +15752,12 @@ Move a child node to a different position (order) amongst the other children. Since calls, signals, etc are performed by tree order, changing the order of chilren nodes may be useful. </description> </method> + <method name="get_groups" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> <method name="raise" > <description> Move this node to the top of the array of nodes of the parent node. This is often useful on GUIs ([Control]), because their order of drawing fully depends on their order in the tree. @@ -14440,7 +15823,7 @@ </description> </method> <method name="get_fixed_process_delta_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the time elapsed since the last fixed frame. This is always the same in fixed proecssing unless the frames per second is changed in [OS]. @@ -14461,7 +15844,7 @@ </description> </method> <method name="get_process_delta_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the time elapsed (in seconds) since the last process callback. This is almost always different each time. @@ -14502,6 +15885,18 @@ Return true if the node is processing unhandled input (see [method set_process_unhandled_input]). </description> </method> + <method name="set_process_unhandled_key_input" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_processing_unhandled_key_input" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="set_pause_mode" > <argument index="0" name="mode" type="int"> </argument> @@ -14531,11 +15926,10 @@ <description> </description> </method> - <method name="get_scene" qualifiers="const" > - <return type="SceneMainLoop"> + <method name="get_tree" qualifiers="const" > + <return type="SceneTree"> </return> <description> - Get the current SceneMainLoop. Only returned if the node is inside the scene, else returns null. </description> </method> <method name="duplicate" qualifiers="const" > @@ -14554,34 +15948,36 @@ Replace a node in a scene by a given one. Subscriptions that pass through this node will be lost. </description> </method> + <method name="get_viewport" qualifiers="const" > + <return type="Object"> + </return> + <description> + </description> + </method> <method name="queue_free" > <description> </description> </method> </methods> <signals> - <signal name="enter_scene"> + <signal name="renamed"> <description> - Emitted when the node enters the scene. + Emitted when the node is renamed. </description> </signal> - <signal name="renamed"> + <signal name="enter_tree"> <description> - Emitted when the node is renamed. </description> </signal> - <signal name="exit_scene"> + <signal name="exit_tree"> <description> - Emitted when the node exits the scene. </description> </signal> </signals> <constants> - <constant name="NOTIFICATION_ENTER_SCENE" value="10"> - Notification received when the node enters the Scene Tree and gains access to the [RootNode]. Note that children nodes will not have received the notification at that time yet. + <constant name="NOTIFICATION_ENTER_TREE" value="10"> </constant> - <constant name="NOTIFICATION_EXIT_SCENE" value="11"> - Notification received when the node exits the Scene Tree and loses access to the [RootNode]. Note that parent nodes will not have received the notification at that time yet. + <constant name="NOTIFICATION_EXIT_TREE" value="11"> </constant> <constant name="NOTIFICATION_MOVED_IN_PARENT" value="12"> </constant> @@ -14628,7 +16024,7 @@ </description> </method> <method name="set_rot" > - <argument index="0" name="rot" type="real"> + <argument index="0" name="rot" type="float"> </argument> <description> Set the rotation of the 2d node. @@ -14649,7 +16045,7 @@ </description> </method> <method name="get_rot" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the rotation of the 2D node. @@ -14662,6 +16058,28 @@ Return the scale of the 2D node. </description> </method> + <method name="rotate" > + <argument index="0" name="degrees" type="float"> + </argument> + <description> + </description> + </method> + <method name="move_local_x" > + <argument index="0" name="delta" type="float"> + </argument> + <argument index="1" name="scaled" type="bool" default="false"> + </argument> + <description> + </description> + </method> + <method name="move_local_y" > + <argument index="0" name="delta" type="float"> + </argument> + <argument index="1" name="scaled" type="bool" default="false"> + </argument> + <description> + </description> + </method> <method name="get_global_pos" qualifiers="const" > <return type="Vector2"> </return> @@ -14669,6 +16087,12 @@ Return the global position of the 2D node. </description> </method> + <method name="set_global_pos" > + <argument index="0" name="arg0" type="Vector2"> + </argument> + <description> + </description> + </method> <method name="set_transform" > <argument index="0" name="xform" type="Matrix32"> </argument> @@ -14857,6 +16281,30 @@ Return the amount of fixed iterations per second (for fixed process and physics). </description> </method> + <method name="set_target_fps" > + <argument index="0" name="target_fps" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_target_fps" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_time_scale" > + <argument index="0" name="time_scale" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_time_scale" > + <return type="float"> + </return> + <description> + </description> + </method> <method name="has_touchscreen_ui_hint" qualifiers="const" > <return type="bool"> </return> @@ -14900,6 +16348,8 @@ </argument> <argument index="2" name="blocking" type="bool"> </argument> + <argument index="3" name="output" type="Array" default="Array()"> + </argument> <description> Execute the binary file in given path, optionally blocking until it returns. A process ID is returned. </description> @@ -14921,6 +16371,12 @@ <description> </description> </method> + <method name="get_process_ID" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> <method name="get_environment" qualifiers="const" > <return type="String"> </return> @@ -15052,6 +16508,12 @@ <description> </description> </method> + <method name="is_debug_build" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="dump_memory_to_file" > <argument index="0" name="file" type="String"> </argument> @@ -15109,7 +16571,7 @@ </description> </method> <method name="get_frames_per_second" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -15118,11 +16580,23 @@ <description> </description> </method> + <method name="print_resources_by_type" > + <argument index="0" name="arg0" type="StringArray"> + </argument> + <description> + </description> + </method> <method name="native_video_play" > <return type="int"> </return> <argument index="0" name="arg0" type="String"> </argument> + <argument index="1" name="arg1" type="float"> + </argument> + <argument index="2" name="arg2" type="int"> + </argument> + <argument index="3" name="arg3" type="int"> + </argument> <description> </description> </method> @@ -15140,6 +16614,12 @@ <description> </description> </method> + <method name="set_use_file_access_save_and_swap" > + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> </methods> <constants> <constant name="DAY_SUNDAY" value="0"> @@ -15208,6 +16688,10 @@ Return the property list, array of dictionaries, dictionaries must countain: name:String, type:int (see TYPE_* enum in globals) and optionally: hint:int (see PROPERTY_HINT_* in globals), hint_string:String, usage:int (see PROPERTY_USAGE_* in globals). </description> </method> + <method name="_init" qualifiers="virtual" > + <description> + </description> + </method> <method name="_notification" qualifiers="virtual" > <argument index="0" name="what" type="int"> </argument> @@ -15419,6 +16903,8 @@ </description> </method> <method name="connect" > + <return type="int"> + </return> <argument index="0" name="signal" type="String"> </argument> <argument index="1" name="target" type="Object"> @@ -15479,9 +16965,9 @@ Set true if this object can translate strings (in calls to tr() ). Default is true. </description> </method> - <method name="can_translate_messages" > - <argument index="0" name="arg0" type="bool"> - </argument> + <method name="can_translate_messages" qualifiers="const" > + <return type="bool"> + </return> <description> Return true if this object can translate strings. </description> @@ -15716,6 +17202,72 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="arrow_margin" type="int"> + </theme_item> + <theme_item name="font_color_disabled" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="font_color_pressed" type="Color"> + </theme_item> + <theme_item name="arrow" type="Texture"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="pressed" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="disabled" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> +</class> +<class name="PCKPacker" inherits="Object" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="pck_start" > + <return type="int"> + </return> + <argument index="0" name="pck_name" type="String"> + </argument> + <argument index="1" name="alignment" type="int"> + </argument> + <description> + </description> + </method> + <method name="add_file" > + <return type="int"> + </return> + <argument index="0" name="pck_path" type="String"> + </argument> + <argument index="1" name="source_path" type="String"> + </argument> + <description> + </description> + </method> + <method name="flush" > + <return type="int"> + </return> + <argument index="0" name="arg0" type="bool"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> </class> <class name="PHashTranslation" inherits="Translation" category="Core"> <brief_description> @@ -15825,11 +17377,17 @@ <method name="put_var" > <return type="int"> </return> - <argument index="0" name="var" type="Variant"> + <argument index="0" name="var" type="var"> </argument> <description> </description> </method> + <method name="get_available_packet_count" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> @@ -15853,6 +17411,70 @@ <constants> </constants> </class> +<class name="PacketPeerUDP" inherits="PacketPeer" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="listen" > + <return type="int"> + </return> + <argument index="0" name="port" type="int"> + </argument> + <argument index="1" name="recv_buf_size" type="int" default="65536"> + </argument> + <description> + </description> + </method> + <method name="close" > + <description> + </description> + </method> + <method name="wait" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="is_listening" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="get_packet_ip" qualifiers="const" > + <return type="String"> + </return> + <description> + </description> + </method> + <method name="get_packet_address" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_packet_port" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_send_address" > + <return type="int"> + </return> + <argument index="0" name="host" type="String"> + </argument> + <argument index="1" name="port" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Panel" inherits="Control" category="Core"> <brief_description> Provides an opaque background for [Control] children. @@ -15865,6 +17487,14 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="panelf" type="StyleBox"> + </theme_item> + <theme_item name="panel" type="StyleBox"> + </theme_item> + <theme_item name="panelnc" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="PanelContainer" inherits="Container" category="Core"> <brief_description> @@ -15877,6 +17507,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="panel" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="ParallaxBackground" inherits="CanvasLayer" category="Core"> <brief_description> @@ -16001,49 +17635,49 @@ </description> </method> <method name="set_radius" > - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> <description> </description> </method> <method name="get_radius" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_disable_radius" > - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> <description> </description> </method> <method name="get_disable_radius" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_gravity" > - <argument index="0" name="gravity" type="real"> + <argument index="0" name="gravity" type="float"> </argument> <description> </description> </method> <method name="get_gravity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_absorption" > - <argument index="0" name="absorption" type="real"> + <argument index="0" name="absorption" type="float"> </argument> <description> </description> </method> <method name="get_absorption" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -16191,14 +17825,14 @@ <method name="set_variable" > <argument index="0" name="variable" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> Set a specific variable for the particle system (see VAR_* enum). </description> </method> <method name="get_variable" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="variable" type="int"> </argument> @@ -16209,14 +17843,14 @@ <method name="set_randomness" > <argument index="0" name="variable" type="int"> </argument> - <argument index="1" name="randomness" type="real"> + <argument index="1" name="randomness" type="float"> </argument> <description> Set the randomness for a specific variable of the particle system. Randomness produces small changes from the default each time a particle is emitted. </description> </method> <method name="get_randomness" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -16227,14 +17861,14 @@ <method name="set_color_phase_pos" > <argument index="0" name="phase" type="int"> </argument> - <argument index="1" name="pos" type="real"> + <argument index="1" name="pos" type="float"> </argument> <description> Set the position of a color phase (0 to 1) </description> </method> <method name="get_color_phase_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="phase" type="int"> </argument> @@ -16275,13 +17909,13 @@ </description> </method> <method name="set_emit_timeout" > - <argument index="0" name="arg0" type="real"> + <argument index="0" name="arg0" type="float"> </argument> <description> </description> </method> <method name="get_emit_timeout" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -16385,49 +18019,49 @@ </description> </method> <method name="set_lifetime" > - <argument index="0" name="lifetime" type="real"> + <argument index="0" name="lifetime" type="float"> </argument> <description> </description> </method> <method name="get_lifetime" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_time_scale" > - <argument index="0" name="time_scale" type="real"> + <argument index="0" name="time_scale" type="float"> </argument> <description> </description> </method> <method name="get_time_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_pre_process_time" > - <argument index="0" name="time" type="real"> + <argument index="0" name="time" type="float"> </argument> <description> </description> </method> <method name="get_pre_process_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_emit_timeout" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> </method> <method name="get_emit_timeout" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -16435,13 +18069,13 @@ <method name="set_param" > <argument index="0" name="param" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="param" type="int"> </argument> @@ -16451,13 +18085,13 @@ <method name="set_randomness" > <argument index="0" name="param" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_randomness" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="param" type="int"> </argument> @@ -16512,6 +18146,30 @@ <description> </description> </method> + <method name="set_h_frames" > + <argument index="0" name="enable" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_h_frames" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_v_frames" > + <argument index="0" name="enable" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_v_frames" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> <method name="set_emission_half_extents" > <argument index="0" name="extents" type="Vector2"> </argument> @@ -16555,13 +18213,13 @@ <method name="set_color_phase_pos" > <argument index="0" name="phase" type="int"> </argument> - <argument index="1" name="pos" type="real"> + <argument index="1" name="pos" type="float"> </argument> <description> </description> </method> <method name="get_color_phase_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="phase" type="int"> </argument> @@ -16569,7 +18227,7 @@ </description> </method> <method name="pre_process" > - <argument index="0" name="time" type="real"> + <argument index="0" name="time" type="float"> </argument> <description> </description> @@ -16599,13 +18257,13 @@ </description> </method> <method name="set_explosiveness" > - <argument index="0" name="amount" type="real"> + <argument index="0" name="amount" type="float"> </argument> <description> </description> </method> <method name="get_explosiveness" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -16640,13 +18298,13 @@ </constant> <constant name="PARAM_TANGENTIAL_ACCEL" value="8"> </constant> - <constant name="PARAM_INITIAL_SIZE" value="10"> + <constant name="PARAM_INITIAL_SIZE" value="11"> </constant> - <constant name="PARAM_FINAL_SIZE" value="11"> + <constant name="PARAM_FINAL_SIZE" value="12"> </constant> - <constant name="PARAM_HUE_VARIATION" value="12"> + <constant name="PARAM_HUE_VARIATION" value="13"> </constant> - <constant name="PARAM_MAX" value="13"> + <constant name="PARAM_MAX" value="16"> </constant> <constant name="MAX_COLOR_PHASES" value="4"> </constant> @@ -16703,49 +18361,49 @@ </description> <methods> <method name="set_offset" > - <argument index="0" name="offset" type="real"> + <argument index="0" name="offset" type="float"> </argument> <description> </description> </method> <method name="get_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_h_offset" > - <argument index="0" name="h_offset" type="real"> + <argument index="0" name="h_offset" type="float"> </argument> <description> </description> </method> <method name="get_h_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_v_offset" > - <argument index="0" name="v_offset" type="real"> + <argument index="0" name="v_offset" type="float"> </argument> <description> </description> </method> <method name="get_v_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_unit_offset" > - <argument index="0" name="unit_offset" type="real"> + <argument index="0" name="unit_offset" type="float"> </argument> <description> </description> </method> <method name="get_unit_offset" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -16798,6 +18456,100 @@ </constant> </constants> </class> +<class name="PathFollow2D" inherits="Node2D" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_offset" > + <argument index="0" name="offset" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_offset" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_h_offset" > + <argument index="0" name="h_offset" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_h_offset" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_v_offset" > + <argument index="0" name="v_offset" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_v_offset" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_unit_offset" > + <argument index="0" name="unit_offset" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_unit_offset" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_rotate" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_rotating" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_cubic_interpolation" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_cubic_interpolation" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_loop" > + <argument index="0" name="loop" type="bool"> + </argument> + <description> + </description> + </method> + <method name="has_loop" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="PathRemap" inherits="Object" category="Core"> <brief_description> Singleton containing the list of remapped resources. @@ -16858,7 +18610,7 @@ </description> <methods> <method name="get_monitor" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="monitor" type="int"> </argument> @@ -16909,7 +18661,19 @@ </constant> <constant name="RENDER_VERTEX_MEM_USED" value="19"> </constant> - <constant name="MONITOR_MAX" value="21"> + <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="21"> + </constant> + <constant name="PHYSICS_2D_COLLISION_PAIRS" value="22"> + </constant> + <constant name="PHYSICS_2D_ISLAND_COUNT" value="23"> + </constant> + <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="24"> + </constant> + <constant name="PHYSICS_3D_COLLISION_PAIRS" value="25"> + </constant> + <constant name="PHYSICS_3D_ISLAND_COUNT" value="26"> + </constant> + <constant name="MONITOR_MAX" value="27"> </constant> </constants> </class> @@ -16929,21 +18693,21 @@ </description> </method> <method name="get_total_density" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the space density currently being applied to this body. </description> </method> <method name="get_inverse_mass" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the inverse of the mass of the body. </description> </method> <method name="get_inverse_inertia" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the inverse of the inertia of the body. @@ -16964,14 +18728,14 @@ </description> </method> <method name="set_angular_velocity" > - <argument index="0" name="velocity" type="real"> + <argument index="0" name="velocity" type="float"> </argument> <description> Change the angular velocity of the body. </description> </method> <method name="get_angular_velocity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the angular velocity of the body. @@ -17083,6 +18847,12 @@ Return the collider shape index. </description> </method> + <method name="get_contact_collider_shape_metadata" qualifiers="const" > + <argument index="0" name="contact_idx" type="int"> + </argument> + <description> + </description> + </method> <method name="get_contact_collider_velocity_at_pos" qualifiers="const" > <return type="Vector2"> </return> @@ -17093,7 +18863,7 @@ </description> </method> <method name="get_step" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the timestep (delta) used for the simulation. @@ -17134,13 +18904,17 @@ </description> <methods> <method name="intersect_ray" > + <return type="Dictionary"> + </return> <argument index="0" name="from" type="Vector2"> </argument> <argument index="1" name="to" type="Vector2"> </argument> <argument index="2" name="exclude" type="Array" default="Array()"> </argument> - <argument index="3" name="umask" type="int" default="0"> + <argument index="3" name="layer_mask" type="int" default="2147483647"> + </argument> + <argument index="4" name="type_mask" type="int" default="15"> </argument> <description> Intersect a ray in a given space, the returned object is a dictionary with the following fields: [br] @@ -17151,40 +18925,61 @@ collider_id: collider id of the object agaisnt which the ray was stopped[br] collider: collider object agaisnt which the ray was stopped[br] rid: [RID] of the object agaisnt which the ray was stopped[br] - If the ray did not intersect anything, then null is returned instead of a [Dictionary]. + If the ray did not intersect anything, then an empty + dictionary (dir.empty()==true) is returned instead. </description> </method> <method name="intersect_shape" > - <argument index="0" name="shape" type="RID"> - </argument> - <argument index="1" name="xform" type="Matrix32"> - </argument> - <argument index="2" name="result_max" type="int"> - </argument> - <argument index="3" name="exclude" type="Array" default="Array()"> + <return type="Array"> + </return> + <argument index="0" name="shape" type="Physics2DShapeQueryParameters"> </argument> - <argument index="4" name="umask" type="int" default="0"> + <argument index="1" name="max_results" type="int" default="32"> </argument> <description> Intersect a given shape (RID or [Shape2D]) against the space, the intersected shapes are returned in a special result object. </description> </method> <method name="cast_motion" > - <argument index="0" name="shape" type="RID"> - </argument> - <argument index="1" name="xform" type="Matrix32"> + <return type="Array"> + </return> + <argument index="0" name="shape" type="Physics2DShapeQueryParameters"> </argument> - <argument index="2" name="motion" type="int"> + <description> + </description> + </method> + <method name="collide_shape" > + <return type="Array"> + </return> + <argument index="0" name="shape" type="Physics2DShapeQueryParameters"> </argument> - <argument index="3" name="exclude" type="Array" default="Array()"> + <argument index="1" name="max_results" type="int" default="32"> </argument> - <argument index="4" name="umask" type="int" default="0"> + <description> + </description> + </method> + <method name="get_rest_info" > + <return type="Dictionary"> + </return> + <argument index="0" name="shape" type="Physics2DShapeQueryParameters"> </argument> <description> </description> </method> </methods> <constants> + <constant name="TYPE_MASK_STATIC_BODY" value="1"> + </constant> + <constant name="TYPE_MASK_KINEMATIC_BODY" value="2"> + </constant> + <constant name="TYPE_MASK_RIGID_BODY" value="4"> + </constant> + <constant name="TYPE_MASK_CHARACTER_BODY" value="8"> + </constant> + <constant name="TYPE_MASK_AREA" value="16"> + </constant> + <constant name="TYPE_MASK_COLLISION" value="15"> + </constant> </constants> </class> <class name="Physics2DServer" inherits="Object" category="Core"> @@ -17252,13 +19047,13 @@ </argument> <argument index="1" name="param" type="int"> </argument> - <argument index="2" name="value" type="real"> + <argument index="2" name="value" type="float"> </argument> <description> </description> </method> <method name="space_get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="space" type="RID"> </argument> @@ -17316,20 +19111,20 @@ <method name="area_add_shape" > <argument index="0" name="area" type="RID"> </argument> - <argument index="1" name="shape" type="int"> + <argument index="1" name="shape" type="RID"> </argument> - <argument index="2" name="transform" type="RID" default="1,0, 0,1, 0,0"> + <argument index="2" name="transform" type="Matrix32" default="1,0, 0,1, 0,0"> </argument> <description> </description> </method> - <method name="area_set_shape" qualifiers="const" > - <return type="RID"> - </return> + <method name="area_set_shape" > <argument index="0" name="area" type="RID"> </argument> <argument index="1" name="shape_idx" type="int"> </argument> + <argument index="2" name="shape" type="RID"> + </argument> <description> </description> </method> @@ -17517,6 +19312,16 @@ <description> </description> </method> + <method name="body_set_shape_metadata" > + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="shape_idx" type="int"> + </argument> + <argument index="2" name="metadata" type="var"> + </argument> + <description> + </description> + </method> <method name="body_get_shape_count" qualifiers="const" > <return type="int"> </return> @@ -17545,6 +19350,14 @@ <description> </description> </method> + <method name="body_get_shape_metadata" qualifiers="const" > + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="shape_idx" type="int"> + </argument> + <description> + </description> + </method> <method name="body_remove_shape" > <argument index="0" name="body" type="RID"> </argument> @@ -17611,18 +19424,54 @@ <description> </description> </method> + <method name="body_set_layer_mask" > + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="body_get_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="arg1" type="int"> + </argument> + <description> + </description> + </method> + <method name="body_set_user_mask" > + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="body_get_user_mask" qualifiers="const" > + <return type="int"> + </return> + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="arg1" type="int"> + </argument> + <description> + </description> + </method> <method name="body_set_param" > <argument index="0" name="body" type="RID"> </argument> <argument index="1" name="param" type="int"> </argument> - <argument index="2" name="value" type="real"> + <argument index="2" name="value" type="float"> </argument> <description> </description> </method> <method name="body_get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="body" type="RID"> </argument> @@ -17732,13 +19581,13 @@ </argument> <argument index="1" name="param" type="int"> </argument> - <argument index="2" name="value" type="real"> + <argument index="2" name="value" type="float"> </argument> <description> </description> </method> <method name="joint_get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="joint" type="RID"> </argument> @@ -17794,13 +19643,13 @@ </argument> <argument index="1" name="param" type="int"> </argument> - <argument index="2" name="value" type="real" default="RID()"> + <argument index="2" name="value" type="float" default="RID()"> </argument> <description> </description> </method> <method name="damped_string_joint_get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="joint" type="RID"> </argument> @@ -17817,7 +19666,7 @@ <description> </description> </method> - <method name="free" > + <method name="free_rid" > <argument index="0" name="rid" type="RID"> </argument> <description> @@ -17829,6 +19678,14 @@ <description> </description> </method> + <method name="get_process_info" > + <return type="int"> + </return> + <argument index="0" name="arg0" type="int"> + </argument> + <description> + </description> + </method> </methods> <constants> <constant name="SHAPE_LINE" value="0"> @@ -17913,6 +19770,12 @@ </constant> <constant name="AREA_BODY_REMOVED" value="1"> </constant> + <constant name="INFO_ACTIVE_OBJECTS" value="0"> + </constant> + <constant name="INFO_COLLISION_PAIRS" value="1"> + </constant> + <constant name="INFO_ISLAND_COUNT" value="2"> + </constant> </constants> </class> <class name="Physics2DServerSW" inherits="Physics2DServer" category="Core"> @@ -17925,6 +19788,106 @@ <constants> </constants> </class> +<class name="Physics2DShapeQueryParameters" inherits="Reference" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_shape" > + <argument index="0" name="shape" type="Shape2D"> + </argument> + <description> + </description> + </method> + <method name="set_shape_rid" > + <argument index="0" name="shape" type="RID"> + </argument> + <description> + </description> + </method> + <method name="get_shape_rid" qualifiers="const" > + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="set_transform" > + <argument index="0" name="transform" type="Matrix32"> + </argument> + <description> + </description> + </method> + <method name="get_transform" qualifiers="const" > + <return type="Matrix32"> + </return> + <description> + </description> + </method> + <method name="set_motion" > + <argument index="0" name="motion" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_motion" qualifiers="const" > + <return type="Vector2"> + </return> + <description> + </description> + </method> + <method name="set_margin" > + <argument index="0" name="margin" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_margin" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_layer_mask" > + <argument index="0" name="layer_mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_object_type_mask" > + <argument index="0" name="object_type_mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_object_type_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_exclude" > + <argument index="0" name="exclude" type="Array"> + </argument> + <description> + </description> + </method> + <method name="get_exclude" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Physics2DShapeQueryResult" inherits="Reference" category="Core"> <brief_description> </brief_description> @@ -17981,6 +19944,30 @@ PhysicsBody is an abstract base class for implementing a physics body. All PhysicsBody types inherit from it. </description> <methods> + <method name="set_layer_mask" > + <argument index="0" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="add_collision_exception_with" > + <argument index="0" name="body" type="PhysicsBody"> + </argument> + <description> + </description> + </method> + <method name="remove_collision_exception_with" > + <argument index="0" name="body" type="PhysicsBody"> + </argument> + <description> + </description> + </method> </methods> <constants> </constants> @@ -17991,6 +19978,30 @@ <description> </description> <methods> + <method name="set_layer_mask" > + <argument index="0" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="add_collision_exception_with" > + <argument index="0" name="body" type="PhysicsBody2D"> + </argument> + <description> + </description> + </method> + <method name="remove_collision_exception_with" > + <argument index="0" name="body" type="PhysicsBody2D"> + </argument> + <description> + </description> + </method> </methods> <constants> </constants> @@ -18008,13 +20019,13 @@ </description> </method> <method name="get_total_density" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_inverse_mass" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -18069,6 +20080,14 @@ <description> </description> </method> + <method name="apply_impulse" > + <argument index="0" name="pos" type="Vector3"> + </argument> + <argument index="1" name="j" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="set_sleep_state" > <argument index="0" name="enabled" type="bool"> </argument> @@ -18160,7 +20179,7 @@ </description> </method> <method name="get_step" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -18196,33 +20215,73 @@ </description> <methods> <method name="intersect_ray" > + <return type="Dictionary"> + </return> <argument index="0" name="from" type="Vector3"> </argument> <argument index="1" name="to" type="Vector3"> </argument> <argument index="2" name="exclude" type="Array" default="Array()"> </argument> - <argument index="3" name="umask" type="int" default="0"> + <argument index="3" name="layer_mask" type="int" default="2147483647"> + </argument> + <argument index="4" name="type_mask" type="int" default="15"> </argument> <description> </description> </method> <method name="intersect_shape" > - <argument index="0" name="shape" type="RID"> + <return type="Array"> + </return> + <argument index="0" name="shape" type="PhysicsShapeQueryParameters"> </argument> - <argument index="1" name="xform" type="Transform"> + <argument index="1" name="max_results" type="int" default="32"> + </argument> + <description> + </description> + </method> + <method name="cast_motion" > + <return type="Array"> + </return> + <argument index="0" name="shape" type="PhysicsShapeQueryParameters"> </argument> - <argument index="2" name="result_max" type="int"> + <argument index="1" name="motion" type="Vector3"> </argument> - <argument index="3" name="exclude" type="Array" default="Array()"> + <description> + </description> + </method> + <method name="collide_shape" > + <return type="Array"> + </return> + <argument index="0" name="shape" type="PhysicsShapeQueryParameters"> </argument> - <argument index="4" name="umask" type="int" default="0"> + <argument index="1" name="max_results" type="int" default="32"> + </argument> + <description> + </description> + </method> + <method name="get_rest_info" > + <return type="Dictionary"> + </return> + <argument index="0" name="shape" type="PhysicsShapeQueryParameters"> </argument> <description> </description> </method> </methods> <constants> + <constant name="TYPE_MASK_STATIC_BODY" value="1"> + </constant> + <constant name="TYPE_MASK_KINEMATIC_BODY" value="2"> + </constant> + <constant name="TYPE_MASK_RIGID_BODY" value="4"> + </constant> + <constant name="TYPE_MASK_CHARACTER_BODY" value="8"> + </constant> + <constant name="TYPE_MASK_AREA" value="16"> + </constant> + <constant name="TYPE_MASK_COLLISION" value="15"> + </constant> </constants> </class> <class name="PhysicsServer" inherits="Object" category="Core"> @@ -18288,13 +20347,13 @@ </argument> <argument index="1" name="param" type="int"> </argument> - <argument index="2" name="value" type="real"> + <argument index="2" name="value" type="float"> </argument> <description> </description> </method> <method name="space_get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="space" type="RID"> </argument> @@ -18352,20 +20411,20 @@ <method name="area_add_shape" > <argument index="0" name="area" type="RID"> </argument> - <argument index="1" name="shape" type="int"> + <argument index="1" name="shape" type="RID"> </argument> - <argument index="2" name="transform" type="RID" default="Transform()"> + <argument index="2" name="transform" type="Transform" default="Transform()"> </argument> <description> </description> </method> - <method name="area_set_shape" qualifiers="const" > - <return type="RID"> - </return> + <method name="area_set_shape" > <argument index="0" name="area" type="RID"> </argument> <argument index="1" name="shape_idx" type="int"> </argument> + <argument index="2" name="shape" type="RID"> + </argument> <description> </description> </method> @@ -18421,19 +20480,21 @@ <description> </description> </method> - <method name="area_set_param" qualifiers="const" > + <method name="area_set_param" > <argument index="0" name="area" type="RID"> </argument> <argument index="1" name="param" type="int"> </argument> + <argument index="2" name="value" type="var"> + </argument> <description> </description> </method> - <method name="area_set_transform" qualifiers="const" > - <return type="Transform"> - </return> + <method name="area_set_transform" > <argument index="0" name="area" type="RID"> </argument> + <argument index="1" name="transform" type="Transform"> + </argument> <description> </description> </method> @@ -18479,6 +20540,22 @@ <description> </description> </method> + <method name="area_set_ray_pickable" > + <argument index="0" name="area" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="area_is_ray_pickable" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="area" type="RID"> + </argument> + <description> + </description> + </method> <method name="body_create" > <return type="RID"> </return> @@ -18632,13 +20709,13 @@ </argument> <argument index="1" name="param" type="int"> </argument> - <argument index="2" name="value" type="real"> + <argument index="2" name="value" type="float"> </argument> <description> </description> </method> <method name="body_get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="body" type="RID"> </argument> @@ -18647,14 +20724,6 @@ <description> </description> </method> - <method name="body_static_simulate_motion" > - <argument index="0" name="body" type="RID"> - </argument> - <argument index="1" name="new_xform" type="Transform"> - </argument> - <description> - </description> - </method> <method name="body_set_state" > <argument index="0" name="body" type="RID"> </argument> @@ -18691,6 +20760,22 @@ <description> </description> </method> + <method name="body_set_axis_lock" > + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="axis" type="int"> + </argument> + <description> + </description> + </method> + <method name="body_get_axis_lock" qualifiers="const" > + <return type="int"> + </return> + <argument index="0" name="body" type="RID"> + </argument> + <description> + </description> + </method> <method name="body_add_collision_exception" > <argument index="0" name="body" type="RID"> </argument> @@ -18751,7 +20836,297 @@ <description> </description> </method> - <method name="free" > + <method name="body_set_ray_pickable" > + <argument index="0" name="body" type="RID"> + </argument> + <argument index="1" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="body_is_ray_pickable" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="body" type="RID"> + </argument> + <description> + </description> + </method> + <method name="joint_create_pin" > + <return type="RID"> + </return> + <argument index="0" name="body_A" type="RID"> + </argument> + <argument index="1" name="local_A" type="Vector3"> + </argument> + <argument index="2" name="body_B" type="RID"> + </argument> + <argument index="3" name="local_B" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="pin_joint_set_param" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <argument index="2" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="pin_joint_get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="pin_joint_set_local_A" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="local_A" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="pin_joint_get_local_A" qualifiers="const" > + <return type="Vector3"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <description> + </description> + </method> + <method name="pin_joint_set_local_B" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="local_B" type="Vector3"> + </argument> + <description> + </description> + </method> + <method name="pin_joint_get_local_B" qualifiers="const" > + <return type="Vector3"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <description> + </description> + </method> + <method name="joint_create_hinge" > + <return type="RID"> + </return> + <argument index="0" name="body_A" type="RID"> + </argument> + <argument index="1" name="hinge_A" type="Transform"> + </argument> + <argument index="2" name="body_B" type="RID"> + </argument> + <argument index="3" name="hinge_B" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="hinge_joint_set_param" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <argument index="2" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="hinge_joint_get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="hinge_joint_set_flag" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="flag" type="int"> + </argument> + <argument index="2" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="hinge_joint_get_flag" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="flag" type="int"> + </argument> + <description> + </description> + </method> + <method name="joint_create_slider" > + <return type="RID"> + </return> + <argument index="0" name="body_A" type="RID"> + </argument> + <argument index="1" name="local_ref_A" type="Transform"> + </argument> + <argument index="2" name="body_B" type="RID"> + </argument> + <argument index="3" name="local_ref_B" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="slider_joint_set_param" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <argument index="2" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="slider_joint_get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="joint_create_cone_twist" > + <return type="RID"> + </return> + <argument index="0" name="body_A" type="RID"> + </argument> + <argument index="1" name="local_ref_A" type="Transform"> + </argument> + <argument index="2" name="body_B" type="RID"> + </argument> + <argument index="3" name="local_ref_B" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="cone_twist_joint_set_param" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <argument index="2" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="cone_twist_joint_get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="joint_get_type" qualifiers="const" > + <return type="int"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <description> + </description> + </method> + <method name="joint_set_solver_priority" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="priority" type="int"> + </argument> + <description> + </description> + </method> + <method name="joint_get_solver_priority" qualifiers="const" > + <return type="int"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <description> + </description> + </method> + <method name="joint_create_generic_6dof" > + <return type="RID"> + </return> + <argument index="0" name="body_A" type="RID"> + </argument> + <argument index="1" name="local_ref_A" type="Transform"> + </argument> + <argument index="2" name="body_B" type="RID"> + </argument> + <argument index="3" name="local_ref_B" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="generic_6dof_joint_set_param" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="axis" type="int"> + </argument> + <argument index="2" name="param" type="int"> + </argument> + <argument index="3" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="generic_6dof_joint_get_param" > + <return type="float"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="axis" type="int"> + </argument> + <argument index="2" name="param" type="int"> + </argument> + <description> + </description> + </method> + <method name="generic_6dof_joint_set_flag" > + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="axis" type="int"> + </argument> + <argument index="2" name="flag" type="int"> + </argument> + <argument index="3" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="generic_6dof_joint_get_flag" > + <return type="bool"> + </return> + <argument index="0" name="joint" type="RID"> + </argument> + <argument index="1" name="axis" type="int"> + </argument> + <argument index="2" name="flag" type="int"> + </argument> + <description> + </description> + </method> + <method name="free_rid" > <argument index="0" name="rid" type="RID"> </argument> <description> @@ -18763,8 +21138,142 @@ <description> </description> </method> + <method name="get_process_info" > + <return type="int"> + </return> + <argument index="0" name="arg0" type="int"> + </argument> + <description> + </description> + </method> </methods> <constants> + <constant name="JOINT_PIN" value="0"> + </constant> + <constant name="JOINT_HINGE" value="1"> + </constant> + <constant name="JOINT_SLIDER" value="2"> + </constant> + <constant name="JOINT_CONE_TWIST" value="3"> + </constant> + <constant name="JOINT_6DOF" value="4"> + </constant> + <constant name="PIN_JOINT_BIAS" value="0"> + </constant> + <constant name="PIN_JOINT_DAMPING" value="1"> + </constant> + <constant name="PIN_JOINT_IMPULSE_CLAMP" value="2"> + </constant> + <constant name="HINGE_JOINT_BIAS" value="0"> + </constant> + <constant name="HINGE_JOINT_LIMIT_UPPER" value="1"> + </constant> + <constant name="HINGE_JOINT_LIMIT_LOWER" value="2"> + </constant> + <constant name="HINGE_JOINT_LIMIT_BIAS" value="3"> + </constant> + <constant name="HINGE_JOINT_LIMIT_SOFTNESS" value="4"> + </constant> + <constant name="HINGE_JOINT_LIMIT_RELAXATION" value="5"> + </constant> + <constant name="HINGE_JOINT_MOTOR_TARGET_VELOCITY" value="6"> + </constant> + <constant name="HINGE_JOINT_MOTOR_MAX_IMPULSE" value="7"> + </constant> + <constant name="HINGE_JOINT_FLAG_USE_LIMIT" value="0"> + </constant> + <constant name="HINGE_JOINT_FLAG_ENABLE_MOTOR" value="1"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_LIMIT_UPPER" value="0"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_LIMIT_LOWER" value="1"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS" value="2"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION" value="3"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_LIMIT_DAMPING" value="4"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_MOTION_SOFTNESS" value="5"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_MOTION_RESTITUTION" value="6"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_MOTION_DAMPING" value="7"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS" value="8"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION" value="9"> + </constant> + <constant name="SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING" value="10"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_LIMIT_UPPER" value="11"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_LIMIT_LOWER" value="12"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS" value="13"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION" value="14"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_LIMIT_DAMPING" value="15"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS" value="16"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION" value="17"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_MOTION_DAMPING" value="18"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS" value="19"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION" value="20"> + </constant> + <constant name="SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING" value="21"> + </constant> + <constant name="SLIDER_JOINT_MAX" value="22"> + </constant> + <constant name="CONE_TWIST_JOINT_SWING_SPAN" value="0"> + </constant> + <constant name="CONE_TWIST_JOINT_TWIST_SPAN" value="1"> + </constant> + <constant name="CONE_TWIST_JOINT_BIAS" value="2"> + </constant> + <constant name="CONE_TWIST_JOINT_SOFTNESS" value="3"> + </constant> + <constant name="CONE_TWIST_JOINT_RELAXATION" value="4"> + </constant> + <constant name="G6DOF_JOINT_LINEAR_LOWER_LIMIT" value="0"> + </constant> + <constant name="G6DOF_JOINT_LINEAR_UPPER_LIMIT" value="1"> + </constant> + <constant name="G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS" value="2"> + </constant> + <constant name="G6DOF_JOINT_LINEAR_RESTITUTION" value="3"> + </constant> + <constant name="G6DOF_JOINT_LINEAR_DAMPING" value="4"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="5"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="6"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="7"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="8"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="9"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="10"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_ERP" value="11"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="12"> + </constant> + <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="13"> + </constant> + <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT" value="0"> + </constant> + <constant name="G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT" value="1"> + </constant> + <constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="2"> + </constant> <constant name="SHAPE_PLANE" value="0"> </constant> <constant name="SHAPE_RAY" value="1"> @@ -18831,6 +21340,12 @@ </constant> <constant name="AREA_BODY_REMOVED" value="1"> </constant> + <constant name="INFO_ACTIVE_OBJECTS" value="0"> + </constant> + <constant name="INFO_COLLISION_PAIRS" value="1"> + </constant> + <constant name="INFO_ISLAND_COUNT" value="2"> + </constant> </constants> </class> <class name="PhysicsServerSW" inherits="PhysicsServer" category="Core"> @@ -18843,6 +21358,94 @@ <constants> </constants> </class> +<class name="PhysicsShapeQueryParameters" inherits="Reference" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_shape" > + <argument index="0" name="shape" type="Shape"> + </argument> + <description> + </description> + </method> + <method name="set_shape_rid" > + <argument index="0" name="shape" type="RID"> + </argument> + <description> + </description> + </method> + <method name="get_shape_rid" qualifiers="const" > + <return type="RID"> + </return> + <description> + </description> + </method> + <method name="set_transform" > + <argument index="0" name="transform" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="get_transform" qualifiers="const" > + <return type="Transform"> + </return> + <description> + </description> + </method> + <method name="set_margin" > + <argument index="0" name="margin" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_margin" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_layer_mask" > + <argument index="0" name="layer_mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_object_type_mask" > + <argument index="0" name="object_type_mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_object_type_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_exclude" > + <argument index="0" name="exclude" type="Array"> + </argument> + <description> + </description> + </method> + <method name="get_exclude" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="PhysicsShapeQueryResult" inherits="Reference" category="Core"> <brief_description> Result of a shape query in Physics2DServer. @@ -18892,6 +21495,38 @@ <constants> </constants> </class> +<class name="PinJoint" inherits="Joint" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_param" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + <constant name="PARAM_BIAS" value="0"> + </constant> + <constant name="PARAM_DAMPING" value="1"> + </constant> + <constant name="PARAM_IMPULSE_CLAMP" value="2"> + </constant> + </constants> +</class> <class name="PinJoint2D" inherits="Joint2D" category="Core"> <brief_description> Pin Joint for 2D Shapes. @@ -18919,7 +21554,7 @@ </description> </method> <method name="distance_to" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="point" type="Vector3"> </argument> @@ -18937,7 +21572,7 @@ </return> <argument index="0" name="point" type="Vector3"> </argument> - <argument index="1" name="epsilon" type="real" default="0.00001"> + <argument index="1" name="epsilon" type="float" default="0.00001"> </argument> <description> Returns true if "p" is inside the plane (by a very minimum treshold). @@ -19002,13 +21637,13 @@ </description> </method> <method name="Plane" > - <argument index="0" name="a" type="real"> + <argument index="0" name="a" type="float"> </argument> - <argument index="1" name="b" type="real"> + <argument index="1" name="b" type="float"> </argument> - <argument index="2" name="c" type="real"> + <argument index="2" name="c" type="float"> </argument> - <argument index="3" name="d" type="real"> + <argument index="3" name="d" type="float"> </argument> <description> </description> @@ -19026,7 +21661,7 @@ <method name="Plane" > <argument index="0" name="normal" type="Vector3"> </argument> - <argument index="1" name="d" type="real"> + <argument index="1" name="d" type="float"> </argument> <description> </description> @@ -19035,13 +21670,13 @@ <members> <member name="normal" type="Vector3"> </member> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> - <member name="z" type="real"> + <member name="z" type="float"> </member> - <member name="d" type="real"> + <member name="d" type="float"> </member> </members> <constants> @@ -19069,6 +21704,224 @@ <constants> </constants> </class> +<class name="Polygon2D" inherits="Node2D" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_polygon" > + <argument index="0" name="polygon" type="Vector2Array"> + </argument> + <description> + </description> + </method> + <method name="get_polygon" qualifiers="const" > + <return type="Vector2Array"> + </return> + <description> + </description> + </method> + <method name="set_uv" > + <argument index="0" name="uv" type="Vector2Array"> + </argument> + <description> + </description> + </method> + <method name="get_uv" qualifiers="const" > + <return type="Vector2Array"> + </return> + <description> + </description> + </method> + <method name="set_color" > + <argument index="0" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="get_color" qualifiers="const" > + <return type="Color"> + </return> + <description> + </description> + </method> + <method name="set_texture" > + <argument index="0" name="texture" type="Object"> + </argument> + <description> + </description> + </method> + <method name="get_texture" qualifiers="const" > + <return type="Object"> + </return> + <description> + </description> + </method> + <method name="set_texture_offset" > + <argument index="0" name="texture_offset" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_texture_offset" qualifiers="const" > + <return type="Vector2"> + </return> + <description> + </description> + </method> + <method name="set_texture_rotation" > + <argument index="0" name="texture_rotation" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_texture_rotation" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_texture_scale" > + <argument index="0" name="texture_scale" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_texture_scale" qualifiers="const" > + <return type="Vector2"> + </return> + <description> + </description> + </method> + <method name="set_texture_repeat" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_texture_repeat" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_invert" > + <argument index="0" name="invert" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_invert" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_invert_border" > + <argument index="0" name="invert_border" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_invert_border" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_offset" > + <argument index="0" name="offset" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_offset" qualifiers="const" > + <return type="Vector2"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> +<class name="PolygonPathFinder" inherits="Resource" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="setup" > + <argument index="0" name="points" type="Vector2Array"> + </argument> + <argument index="1" name="connections" type="IntArray"> + </argument> + <description> + </description> + </method> + <method name="find_path" > + <return type="Vector2Array"> + </return> + <argument index="0" name="from" type="Vector2"> + </argument> + <argument index="1" name="to" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_intersections" qualifiers="const" > + <return type="Vector2Array"> + </return> + <argument index="0" name="from" type="Vector2"> + </argument> + <argument index="1" name="to" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_closest_point" qualifiers="const" > + <return type="Vector2"> + </return> + <argument index="0" name="point" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="is_point_inside" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="point" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="set_point_penalty" > + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="penalty" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_point_penalty" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_bounds" qualifiers="const" > + <return type="Rect2"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="Popup" inherits="Control" category="Core"> <brief_description> Base container control for popups and dialogs. @@ -19085,7 +21938,7 @@ </description> </method> <method name="popup_centered_ratio" > - <argument index="0" name="ratio" type="real" default="0.75"> + <argument index="0" name="ratio" type="float" default="0.75"> </argument> <description> Popup (show the control in modal form) in the center of the screen, scalled at a ratio of size of the screen. @@ -19116,6 +21969,10 @@ </method> </methods> <signals> + <signal name="popup_hide"> + <description> + </description> + </signal> <signal name="about_to_show"> <description> This signal is emitted when a popup is about to be shown. (often used in [PopupMenu] for clearing the list of options and creating a new one according to the current context). @@ -19125,6 +21982,8 @@ <constants> <constant name="NOTIFICATION_POST_POPUP" value="80"> </constant> + <constant name="NOTIFICATION_POPUP_HIDE" value="81"> + </constant> </constants> </class> <class name="PopupDialog" inherits="Popup" category="Core"> @@ -19197,7 +22056,7 @@ <method name="add_submenu_item" > <argument index="0" name="label" type="String"> </argument> - <argument index="1" name="submenu" type="int"> + <argument index="1" name="submenu" type="String"> </argument> <argument index="2" name="id" type="int" default="-1"> </argument> @@ -19416,6 +22275,36 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="vseparation" type="int"> + </theme_item> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="font_color_disabled" type="Color"> + </theme_item> + <theme_item name="font_color_accel" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="submenu" type="Texture"> + </theme_item> + <theme_item name="checked" type="Texture"> + </theme_item> + <theme_item name="unchecked" type="Texture"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="panel_disabled" type="StyleBox"> + </theme_item> + <theme_item name="panel" type="StyleBox"> + </theme_item> + <theme_item name="separator" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="PopupPanel" inherits="Popup" category="Core"> <brief_description> @@ -19427,6 +22316,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="panel" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="Portal" inherits="VisualInstance" category="Core"> <brief_description> @@ -19466,14 +22359,14 @@ </description> </method> <method name="set_disable_distance" > - <argument index="0" name="distance" type="real"> + <argument index="0" name="distance" type="float"> </argument> <description> Set the distance threshold for disabling the portal. Every time that the portal goes beyond "distance", it disables itself, becoming the opaque color (see [method set_disabled_color]). </description> </method> <method name="get_disable_distance" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the distance threshold for disabling the portal. Every time that the portal goes beyond "distance", it disables itself, becoming the opaque color (see [method set_disabled_color]). @@ -19494,14 +22387,14 @@ </description> </method> <method name="set_connect_range" > - <argument index="0" name="range" type="real"> + <argument index="0" name="range" type="float"> </argument> <description> Set the range for auto-connecting two portals from different rooms sharing the same space. </description> </method> <method name="get_connect_range" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the range for auto-connecting two portals from different rooms sharing the same space. @@ -19543,9 +22436,33 @@ General purpose progres bar. Shows fill percentage from right to left. </description> <methods> + <method name="set_percent_visible" > + <argument index="0" name="visible" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_percent_visible" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> + <theme_items> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_shadow" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="fg" type="StyleBox"> + </theme_item> + <theme_item name="bg" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="ProximityGroup" inherits="Spatial" category="Core"> <brief_description> @@ -19676,13 +22593,13 @@ </argument> <argument index="2" name="post_b" type="Quat"> </argument> - <argument index="3" name="t" type="real"> + <argument index="3" name="t" type="float"> </argument> <description> </description> </method> <method name="dot" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="b" type="Quat"> </argument> @@ -19698,14 +22615,14 @@ </description> </method> <method name="length" > - <return type="real"> + <return type="float"> </return> <description> Returns the length of the quaternion. </description> </method> <method name="length_squared" > - <return type="real"> + <return type="float"> </return> <description> Returns the length of the quaternion, minus the square root. @@ -19723,7 +22640,7 @@ </return> <argument index="0" name="b" type="Quat"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> Perform a spherical-linear interpolation with another quaternion. @@ -19734,19 +22651,19 @@ </return> <argument index="0" name="b" type="Quat"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> </description> </method> <method name="Quat" > - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> - <argument index="2" name="z" type="real"> + <argument index="2" name="z" type="float"> </argument> - <argument index="3" name="w" type="real"> + <argument index="3" name="w" type="float"> </argument> <description> </description> @@ -19759,13 +22676,13 @@ </method> </methods> <members> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> - <member name="z" type="real"> + <member name="z" type="float"> </member> - <member name="w" type="real"> + <member name="w" type="float"> </member> </members> <constants> @@ -19802,48 +22719,48 @@ </description> <methods> <method name="get_val" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the current value. </description> </method> <method name="get_value" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_min" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the minimum value. </description> </method> <method name="get_max" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the maximum value. </description> </method> <method name="get_step" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the stepping, if step is 0, stepping is disabled. </description> </method> <method name="get_page" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the page size, if page is 0, paging is disabled. </description> </method> <method name="get_unit_value" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return value mapped to 0 to 1 (unit) range. @@ -19856,46 +22773,46 @@ </description> </method> <method name="set_val" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> </method> <method name="set_value" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> </method> <method name="set_min" > - <argument index="0" name="minimum" type="real"> + <argument index="0" name="minimum" type="float"> </argument> <description> Set minimum value, clamped range value to it if it"apos;s less. </description> </method> <method name="set_max" > - <argument index="0" name="maximum" type="real"> + <argument index="0" name="maximum" type="float"> </argument> <description> </description> </method> <method name="set_step" > - <argument index="0" name="step" type="real"> + <argument index="0" name="step" type="float"> </argument> <description> Set step value. If step is 0, stepping will be disabled. </description> </method> <method name="set_page" > - <argument index="0" name="pagesize" type="real"> + <argument index="0" name="pagesize" type="float"> </argument> <description> Set page size. Page is mainly used for scrollbars or anything that controls text scrolling. </description> </method> <method name="set_unit_value" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> Set value mapped to 0 to 1 (unit) range, it will then be converted to the actual value within min and max. @@ -19932,7 +22849,7 @@ </methods> <signals> <signal name="value_changed"> - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> This signal is emitted when value changes. @@ -20135,6 +23052,46 @@ <description> </description> </method> + <method name="add_exception_rid" > + <argument index="0" name="rid" type="RID"> + </argument> + <description> + </description> + </method> + <method name="add_exception" > + <argument index="0" name="node" type="Object"> + </argument> + <description> + </description> + </method> + <method name="remove_exception_rid" > + <argument index="0" name="rid" type="RID"> + </argument> + <description> + </description> + </method> + <method name="remove_exception" > + <argument index="0" name="node" type="Object"> + </argument> + <description> + </description> + </method> + <method name="clear_exceptions" > + <description> + </description> + </method> + <method name="set_layer_mask" > + <argument index="0" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> @@ -20146,13 +23103,13 @@ </description> <methods> <method name="set_length" > - <argument index="0" name="length" type="real"> + <argument index="0" name="length" type="float"> </argument> <description> </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -20170,13 +23127,13 @@ </description> <methods> <method name="set_length" > - <argument index="0" name="length" type="real"> + <argument index="0" name="length" type="float"> </argument> <description> </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -20194,7 +23151,7 @@ </description> <methods> <method name="get" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="idx" type="int"> </argument> @@ -20202,7 +23159,7 @@ </description> </method> <method name="push_back" > - <argument index="0" name="value" type="real"> + <argument index="0" name="value" type="float"> </argument> <description> </description> @@ -20216,7 +23173,7 @@ <method name="set" > <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> @@ -20268,7 +23225,7 @@ </description> </method> <method name="get_area" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -20276,7 +23233,7 @@ <method name="grow" > <return type="Rect2"> </return> - <argument index="0" name="by" type="real"> + <argument index="0" name="by" type="float"> </argument> <description> </description> @@ -20320,13 +23277,13 @@ </description> </method> <method name="Rect2" > - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> - <argument index="2" name="width" type="real"> + <argument index="2" name="width" type="float"> </argument> - <argument index="3" name="height" type="real"> + <argument index="3" name="height" type="float"> </argument> <description> </description> @@ -20410,6 +23367,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="border" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="RegEx" inherits="Reference" category="Core"> <brief_description> @@ -20494,6 +23455,12 @@ Set the path of the resource. This is useful mainly for editors when saving/loading, and shouldn"apos;t be changed by anything else. </description> </method> + <method name="take_over_path" > + <argument index="0" name="path" type="String"> + </argument> + <description> + </description> + </method> <method name="get_path" qualifiers="const" > <return type="String"> </return> @@ -20836,6 +23803,18 @@ </method> </methods> <constants> + <constant name="FLAG_RELATIVE_PATHS" value="1"> + </constant> + <constant name="FLAG_BUNDLE_RESOURCES" value="2"> + </constant> + <constant name="FLAG_CHANGE_PATH" value="4"> + </constant> + <constant name="FLAG_OMIT_EDITOR_PROPERTIES" value="8"> + </constant> + <constant name="FLAG_SAVE_BIG_ENDIAN" value="16"> + </constant> + <constant name="FLAG_COMPRESS" value="32"> + </constant> </constants> </class> <class name="RichTextLabel" inherits="Control" category="Core"> @@ -20972,6 +23951,22 @@ Return true if selecting the text inside this richtext is allowed. </description> </method> + <method name="parse_bbcode" > + <return type="int"> + </return> + <argument index="0" name="bbcode" type="String"> + </argument> + <description> + </description> + </method> + <method name="append_bbcode" > + <return type="int"> + </return> + <argument index="0" name="bbcode" type="String"> + </argument> + <description> + </description> + </method> </methods> <signals> <signal name="meta_clicked"> @@ -21019,6 +24014,20 @@ <constant name="ITEM_META" value="10"> </constant> </constants> + <theme_items> + <theme_item name="line_separation" type="int"> + </theme_item> + <theme_item name="default_color" type="Color"> + </theme_item> + <theme_item name="selection_color" type="Color"> + </theme_item> + <theme_item name="font_color_selected" type="Color"> + </theme_item> + <theme_item name="default_font" type="Font"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="RigidBody" inherits="PhysicsBody" category="Core"> <brief_description> @@ -21045,49 +24054,49 @@ </description> </method> <method name="set_mass" > - <argument index="0" name="mass" type="real"> + <argument index="0" name="mass" type="float"> </argument> <description> </description> </method> <method name="get_mass" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_weight" > - <argument index="0" name="weight" type="real"> + <argument index="0" name="weight" type="float"> </argument> <description> </description> </method> <method name="get_weight" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_friction" > - <argument index="0" name="friction" type="real"> + <argument index="0" name="friction" type="float"> </argument> <description> </description> </method> <method name="get_friction" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_bounce" > - <argument index="0" name="bounce" type="real"> + <argument index="0" name="bounce" type="float"> </argument> <description> </description> </method> <method name="get_bounce" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -21178,13 +24187,13 @@ <description> </description> </method> - <method name="set_active" > - <argument index="0" name="active" type="bool"> + <method name="set_sleeping" > + <argument index="0" name="sleeping" type="bool"> </argument> <description> </description> </method> - <method name="is_active" qualifiers="const" > + <method name="is_sleeping" qualifiers="const" > <return type="bool"> </return> <description> @@ -21202,6 +24211,24 @@ <description> </description> </method> + <method name="set_axis_lock" > + <argument index="0" name="axis_lock" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_axis_lock" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_colliding_bodies" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> </methods> <signals> <signal name="body_enter"> @@ -21284,56 +24311,56 @@ </description> </method> <method name="set_mass" > - <argument index="0" name="mass" type="real"> + <argument index="0" name="mass" type="float"> </argument> <description> Set the body mass. </description> </method> <method name="get_mass" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the body mass. </description> </method> <method name="set_weight" > - <argument index="0" name="weight" type="real"> + <argument index="0" name="weight" type="float"> </argument> <description> Set the body mass given standard earth-weight (gravity 9.8). Not really useful for 2D since most measuers for this node are in pixels. </description> </method> <method name="get_weight" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the body mass given standard earth-weight (gravity 9.8). </description> </method> <method name="set_friction" > - <argument index="0" name="friction" type="real"> + <argument index="0" name="friction" type="float"> </argument> <description> Set the body friction, from 0 (friction less) to 1 (full friction). </description> </method> <method name="get_friction" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the body friction. </description> </method> <method name="set_bounce" > - <argument index="0" name="bounce" type="real"> + <argument index="0" name="bounce" type="float"> </argument> <description> Set the body bounciness, from 0 (no bounce) to 1 (bounce). </description> </method> <method name="get_bounce" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the body bouncyness. @@ -21354,14 +24381,14 @@ </description> </method> <method name="set_angular_velocity" > - <argument index="0" name="angular_velocity" type="real"> + <argument index="0" name="angular_velocity" type="float"> </argument> <description> Set the body angular velocity. Can be used sporadically, but[b] DONT SET THIS IN EVERY FRAME [/b], because physics may be running in another thread and definitely runs at a different granularity. Use [_integrate_forces] as your process loop if you want to have precise control of the body state. </description> </method> <method name="get_angular_velocity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the body angular velocity. This changes by physics granularity. See [set_angular_velocity]. @@ -21449,18 +24476,16 @@ <description> </description> </method> - <method name="set_active" > - <argument index="0" name="active" type="bool"> + <method name="set_sleeping" > + <argument index="0" name="sleeping" type="bool"> </argument> <description> - Change the body state between sleeping/active states. As a note, static bodies can never be active. </description> </method> - <method name="is_active" qualifiers="const" > + <method name="is_sleeping" qualifiers="const" > <return type="bool"> </return> <description> - Return the body state. As a note, static bodies are never active. </description> </method> <method name="set_can_sleep" > @@ -21477,6 +24502,12 @@ Return true if the body has the ability to fall asleep when not moving. See [set_can_sleep]. </description> </method> + <method name="get_colliding_bodies" qualifiers="const" > + <return type="Array"> + </return> + <description> + </description> + </method> </methods> <signals> <signal name="body_enter"> @@ -21799,13 +24830,13 @@ <method name="sample_set_volume_db" > <argument index="0" name="name" type="String"> </argument> - <argument index="1" name="db" type="real"> + <argument index="1" name="db" type="float"> </argument> <description> </description> </method> <method name="sample_get_volume_db" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="name" type="String"> </argument> @@ -21815,13 +24846,13 @@ <method name="sample_set_pitch_scale" > <argument index="0" name="name" type="String"> </argument> - <argument index="1" name="pitch" type="real"> + <argument index="1" name="pitch" type="float"> </argument> <description> </description> </method> <method name="sample_get_pitch_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="name" type="String"> </argument> @@ -21900,7 +24931,7 @@ <method name="set_pitch_scale" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="ratio" type="real"> + <argument index="1" name="ratio" type="float"> </argument> <description> Scale the pitch (mix rate) of a voice by a ratio value "ratio". A ratio of 1.0 means the voice is unscaled. @@ -21909,7 +24940,7 @@ <method name="set_volume" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="nrg" type="real"> + <argument index="1" name="nrg" type="float"> </argument> <description> Set the volume of a voice, 0db is maximum volume (every about -6db, volume is reduced in half). "db" does in fact go from zero to negative. @@ -21918,7 +24949,7 @@ <method name="set_volume_db" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="nrg" type="real"> + <argument index="1" name="nrg" type="float"> </argument> <description> </description> @@ -21926,11 +24957,11 @@ <method name="set_pan" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="pan" type="real"> + <argument index="1" name="pan" type="float"> </argument> - <argument index="2" name="depth" type="real" default="0"> + <argument index="2" name="depth" type="float" default="0"> </argument> - <argument index="3" name="height" type="real" default="0"> + <argument index="3" name="height" type="float" default="0"> </argument> <description> Set the panning of a voice. Panning goes from -1 (left) to +1 (right). Optionally, if the hardware supports 3D sound, also set depth and height (also in range -1 to +1). @@ -21941,11 +24972,11 @@ </argument> <argument index="1" name="type" type="int"> </argument> - <argument index="2" name="cutoff_hz" type="real"> + <argument index="2" name="cutoff_hz" type="float"> </argument> - <argument index="3" name="resonance" type="real"> + <argument index="3" name="resonance" type="float"> </argument> - <argument index="4" name="gain" type="real" default="0"> + <argument index="4" name="gain" type="float" default="0"> </argument> <description> Set and enable a filter of a voice, with type "type" (see FILTER_* enum), cutoff (0 to 22khz) frequency and resonance (0+). @@ -21954,7 +24985,7 @@ <method name="set_chorus" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="send" type="real"> + <argument index="1" name="send" type="float"> </argument> <description> Set the chorus send level of a voice (0 to 1). For setting chorus parameters, see [AudioServer]. @@ -21965,7 +24996,7 @@ </argument> <argument index="1" name="room_type" type="int"> </argument> - <argument index="2" name="send" type="real"> + <argument index="2" name="send" type="float"> </argument> <description> Set the reverb send level and type of a voice (0 to 1). (see REVERB_* enum for type). @@ -21981,7 +25012,7 @@ </description> </method> <method name="get_pitch_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -21990,7 +25021,7 @@ </description> </method> <method name="get_volume" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -21999,7 +25030,7 @@ </description> </method> <method name="get_volume_db" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22007,7 +25038,7 @@ </description> </method> <method name="get_pan" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22016,7 +25047,7 @@ </description> </method> <method name="get_pan_depth" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22025,7 +25056,7 @@ </description> </method> <method name="get_pan_height" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22043,7 +25074,7 @@ </description> </method> <method name="get_filter_cutoff" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22052,7 +25083,7 @@ </description> </method> <method name="get_filter_resonance" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22061,7 +25092,7 @@ </description> </method> <method name="get_filter_gain" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22069,7 +25100,7 @@ </description> </method> <method name="get_chorus" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22078,7 +25109,7 @@ </description> </method> <method name="get_reverb_room" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22087,7 +25118,7 @@ </description> </method> <method name="get_reverb" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="voice" type="int"> </argument> @@ -22096,29 +25127,29 @@ </description> </method> <method name="set_default_pitch_scale" > - <argument index="0" name="ratio" type="real"> + <argument index="0" name="ratio" type="float"> </argument> <description> </description> </method> <method name="set_default_volume" > - <argument index="0" name="nrg" type="real"> + <argument index="0" name="nrg" type="float"> </argument> <description> </description> </method> <method name="set_default_volume_db" > - <argument index="0" name="db" type="real"> + <argument index="0" name="db" type="float"> </argument> <description> </description> </method> <method name="set_default_pan" > - <argument index="0" name="pan" type="real"> + <argument index="0" name="pan" type="float"> </argument> - <argument index="1" name="depth" type="real" default="0"> + <argument index="1" name="depth" type="float" default="0"> </argument> - <argument index="2" name="height" type="real" default="0"> + <argument index="2" name="height" type="float" default="0"> </argument> <description> </description> @@ -22126,17 +25157,17 @@ <method name="set_default_filter" > <argument index="0" name="type" type="int"> </argument> - <argument index="1" name="cutoff_hz" type="real"> + <argument index="1" name="cutoff_hz" type="float"> </argument> - <argument index="2" name="resonance" type="real"> + <argument index="2" name="resonance" type="float"> </argument> - <argument index="3" name="gain" type="real" default="0"> + <argument index="3" name="gain" type="float" default="0"> </argument> <description> </description> </method> <method name="set_default_chorus" > - <argument index="0" name="send" type="real"> + <argument index="0" name="send" type="float"> </argument> <description> </description> @@ -22144,43 +25175,43 @@ <method name="set_default_reverb" > <argument index="0" name="room_type" type="int"> </argument> - <argument index="1" name="send" type="real"> + <argument index="1" name="send" type="float"> </argument> <description> </description> </method> <method name="get_default_pitch_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_volume" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_volume_db" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_pan" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_pan_depth" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_pan_height" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -22192,37 +25223,37 @@ </description> </method> <method name="get_default_filter_cutoff" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_filter_resonance" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_filter_gain" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_chorus" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_reverb_room" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="get_default_reverb" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -22331,7 +25362,7 @@ <method name="voice_set_pitch_scale" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="ratio" type="real"> + <argument index="1" name="ratio" type="float"> </argument> <description> Change the pitch scale of a currently playing voice. @@ -22340,7 +25371,7 @@ <method name="voice_set_volume_scale_db" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="db" type="real"> + <argument index="1" name="db" type="float"> </argument> <description> Change the volume scale of a currently playing voice (using dB). @@ -22368,13 +25399,13 @@ </description> </method> <method name="set_random_pitch_scale" > - <argument index="0" name="val" type="real"> + <argument index="0" name="val" type="float"> </argument> <description> </description> </method> <method name="get_random_pitch_scale" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -22388,89 +25419,12 @@ </constant> </constants> </class> -<class name="SceneIO" inherits="Object" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - <method name="load" > - <return type="Node"> - </return> - <argument index="0" name="path" type="String"> - </argument> - <description> - </description> - </method> - <method name="save" > - <return type="int"> - </return> - <argument index="0" name="path" type="String"> - </argument> - <argument index="1" name="scene" type="Node"> - </argument> - <argument index="2" name="flags" type="int" default="0"> - </argument> - <argument index="3" name="optimizer" type="OptimizedSaver" default="Object()"> - </argument> - <description> - </description> - </method> - <method name="load_interactive" > - <return type="SceneInteractiveLoader"> - </return> - <argument index="0" name="path" type="String"> - </argument> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> -<class name="SceneInteractiveLoader" inherits="Reference" category="Core"> +<class name="SceneTree" inherits="MainLoop" category="Core"> <brief_description> </brief_description> <description> </description> <methods> - <method name="get_scene" > - <return type="Object"> - </return> - <description> - </description> - </method> - <method name="poll" > - <return type="int"> - </return> - <description> - </description> - </method> - <method name="get_stage" qualifiers="const" > - <return type="int"> - </return> - <description> - </description> - </method> - <method name="get_stage_count" qualifiers="const" > - <return type="int"> - </return> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> -<class name="SceneMainLoop" inherits="MainLoop" category="Core"> - <brief_description> - Scene-Based implementation of the MainLoop. - </brief_description> - <description> - Scene implementation of the MainLoop. All scenes edited using the editor are loaded with this main loop, which provides the base for the scene system.[br] - All group operations (get nodes, call, etc) is performed here. All nodes in a group can be called a specific functions, set a property or notified. This happens in scene-order. - </description> - <methods> <method name="notify_group" > <argument index="0" name="call_flags" type="int"> </argument> @@ -22479,7 +25433,6 @@ <argument index="2" name="notification" type="int"> </argument> <description> - Call a notification in all the nodes belonging to a given group. See GROUP_CALL_* enum for options. </description> </method> <method name="set_group" > @@ -22492,7 +25445,6 @@ <argument index="3" name="value" type="var"> </argument> <description> - Set a property in all the nodes belonging to a given group. See GROUP_CALL_* enum for options. </description> </method> <method name="get_nodes_in_group" > @@ -22501,7 +25453,6 @@ <argument index="0" name="arg0" type="String"> </argument> <description> - Get all the nods belonging to a given group. </description> </method> <method name="get_root" qualifiers="const" > @@ -22514,40 +25465,46 @@ <argument index="0" name="enabled" type="bool"> </argument> <description> - Set to true if the application will quit automatically when quit is requested (Alt-f4 or ctrl-c). </description> </method> <method name="set_editor_hint" > <argument index="0" name="enable" type="bool"> </argument> <description> - Set to true to tell nodes and the scene that it is being edited. This is used by editors, not release. </description> </method> <method name="is_editor_hint" qualifiers="const" > <return type="bool"> </return> <description> - Return true if the scene is being run inside an editor. + </description> + </method> + <method name="set_edited_scene_root" > + <argument index="0" name="scene" type="Object"> + </argument> + <description> + </description> + </method> + <method name="get_edited_scene_root" qualifiers="const" > + <return type="Object"> + </return> + <description> </description> </method> <method name="set_pause" > <argument index="0" name="enable" type="bool"> </argument> <description> - Set pause. The built-in pause system is very basic and only meant to avoid processing nodes not allowed to work in pause mode. </description> </method> <method name="is_paused" qualifiers="const" > <return type="bool"> </return> <description> - Return true if the scene is paused. </description> </method> <method name="set_input_as_handled" > <description> - Handle a current input event (avoid further processing of it). </description> </method> <method name="get_node_count" qualifiers="const" > @@ -22560,19 +25517,26 @@ <return type="int"> </return> <description> - Return the frame index (how many frames were drawn). </description> </method> <method name="quit" > <description> - Quit the application. + </description> + </method> + <method name="set_screen_stretch" > + <argument index="0" name="mode" type="int"> + </argument> + <argument index="1" name="aspect" type="int"> + </argument> + <argument index="2" name="minsize" type="Vector2"> + </argument> + <description> </description> </method> <method name="queue_delete" > <argument index="0" name="obj" type="Object"> </argument> <description> - Queue an object for deletion next time the loop goes idle. </description> </method> <method name="call_group" > @@ -22593,78 +25557,48 @@ <argument index="7" name="arg4" type="var" default="NULL"> </argument> <description> - Call a function for all the nodes in a given group. </description> </method> </methods> <signals> <signal name="screen_resized"> <description> - Emitted when the screen changes size. </description> </signal> <signal name="node_removed"> <argument index="0" name="node" type="Object"> </argument> <description> - Emitted when a node is removed from the scene. </description> </signal> <signal name="tree_changed"> <description> - Emitted when the scene tree changed (nodes added/removed/moved/etc) </description> </signal> </signals> <constants> <constant name="GROUP_CALL_DEFAULT" value="0"> - Regular group call flag (no flags). </constant> <constant name="GROUP_CALL_REVERSE" value="1"> - Call a group in inverse-scene order. </constant> <constant name="GROUP_CALL_REALTIME" value="2"> - Call a group immediately (usually calls are delivered on idle). </constant> <constant name="GROUP_CALL_UNIQUE" value="4"> - Call a group only once, even if call is performed many times. </constant> - </constants> -</class> -<class name="ScenePreloader" inherits="Resource" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> - <method name="load_scene" > - <return type="int"> - </return> - <argument index="0" name="path" type="String"> - </argument> - <description> - </description> - </method> - <method name="get_scene_path" qualifiers="const" > - <return type="String"> - </return> - <description> - </description> - </method> - <method name="instance" qualifiers="const" > - <return type="Node"> - </return> - <description> - </description> - </method> - <method name="can_instance" qualifiers="const" > - <return type="bool"> - </return> - <description> - </description> - </method> - </methods> - <constants> + <constant name="STRETCH_MODE_DISABLED" value="0"> + </constant> + <constant name="STRETCH_MODE_2D" value="1"> + </constant> + <constant name="STRETCH_MODE_VIEWPORT" value="2"> + </constant> + <constant name="STRETCH_ASPECT_IGNORE" value="0"> + </constant> + <constant name="STRETCH_ASPECT_KEEP" value="1"> + </constant> + <constant name="STRETCH_ASPECT_KEEP_WIDTH" value="2"> + </constant> + <constant name="STRETCH_ASPECT_KEEP_HEIGHT" value="3"> + </constant> </constants> </class> <class name="Script" inherits="Resource" category="Core"> @@ -22732,13 +25666,13 @@ </description> <methods> <method name="set_custom_step" > - <argument index="0" name="step" type="real"> + <argument index="0" name="step" type="float"> </argument> <description> </description> </method> <method name="get_custom_step" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -22900,10 +25834,12 @@ </argument> <argument index="1" name="fcode" type="String"> </argument> - <argument index="2" name="vofs" type="int" default="0"> + <argument index="2" name="lcode" type="String"> </argument> <argument index="3" name="fofs" type="int" default="0"> </argument> + <argument index="4" name="lofs" type="int" default="0"> + </argument> <description> </description> </method> @@ -22919,6 +25855,12 @@ <description> </description> </method> + <method name="get_light_code" qualifiers="const" > + <return type="String"> + </return> + <description> + </description> + </method> <method name="has_param" qualifiers="const" > <return type="bool"> </return> @@ -22955,6 +25897,20 @@ <description> </description> </method> + <method name="set_shader_param" > + <argument index="0" name="param" type="String"> + </argument> + <argument index="1" name="value" type="var"> + </argument> + <description> + </description> + </method> + <method name="get_shader_param" qualifiers="const" > + <argument index="0" name="param" type="String"> + </argument> + <description> + </description> + </method> </methods> <constants> </constants> @@ -22978,14 +25934,14 @@ </description> <methods> <method name="set_custom_solver_bias" > - <argument index="0" name="bias" type="real"> + <argument index="0" name="bias" type="float"> </argument> <description> Use a custom solver bias. No need to change this unless you really know what you are doing. </description> </method> <method name="get_custom_solver_bias" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the custom solver bias. No need to change this unless you really know what you are doing. @@ -23032,10 +25988,14 @@ <method name="collide_with_motion_and_get_contacts" > <argument index="0" name="local_xform" type="Matrix32"> </argument> - <argument index="1" name="local_motion" type="Object"> + <argument index="1" name="local_motion" type="Vector2"> </argument> <argument index="2" name="with_shape" type="Shape2D"> </argument> + <argument index="3" name="shape_xform" type="Matrix32"> + </argument> + <argument index="4" name="shape_motion" type="Vector2"> + </argument> <description> </description> </method> @@ -23169,6 +26129,22 @@ Return the pose transform for bone "bone_idx". </description> </method> + <method name="set_bone_global_pose" > + <argument index="0" name="bone_idx" type="int"> + </argument> + <argument index="1" name="pose" type="Transform"> + </argument> + <description> + </description> + </method> + <method name="get_bone_global_pose" qualifiers="const" > + <return type="Transform"> + </return> + <argument index="0" name="bone_idx" type="int"> + </argument> + <description> + </description> + </method> <method name="get_bone_custom_pose" qualifiers="const" > <return type="Transform"> </return> @@ -23239,6 +26215,78 @@ <constants> </constants> </class> +<class name="SliderJoint" inherits="Joint" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_param" > + <argument index="0" name="param" type="int"> + </argument> + <argument index="1" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_param" qualifiers="const" > + <return type="float"> + </return> + <argument index="0" name="param" type="int"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + <constant name="PARAM_LINEAR_LIMIT_UPPER" value="0"> + </constant> + <constant name="PARAM_LINEAR_LIMIT_LOWER" value="1"> + </constant> + <constant name="PARAM_LINEAR_LIMIT_SOFTNESS" value="2"> + </constant> + <constant name="PARAM_LINEAR_LIMIT_RESTITUTION" value="3"> + </constant> + <constant name="PARAM_LINEAR_LIMIT_DAMPING" value="4"> + </constant> + <constant name="PARAM_LINEAR_MOTION_SOFTNESS" value="5"> + </constant> + <constant name="PARAM_LINEAR_MOTION_RESTITUTION" value="6"> + </constant> + <constant name="PARAM_LINEAR_MOTION_DAMPING" value="7"> + </constant> + <constant name="PARAM_LINEAR_ORTHOGONAL_SOFTNESS" value="8"> + </constant> + <constant name="PARAM_LINEAR_ORTHOGONAL_RESTITUTION" value="9"> + </constant> + <constant name="PARAM_LINEAR_ORTHOGONAL_DAMPING" value="10"> + </constant> + <constant name="PARAM_ANGULAR_LIMIT_UPPER" value="11"> + </constant> + <constant name="PARAM_ANGULAR_LIMIT_LOWER" value="12"> + </constant> + <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="13"> + </constant> + <constant name="PARAM_ANGULAR_LIMIT_RESTITUTION" value="14"> + </constant> + <constant name="PARAM_ANGULAR_LIMIT_DAMPING" value="15"> + </constant> + <constant name="PARAM_ANGULAR_MOTION_SOFTNESS" value="16"> + </constant> + <constant name="PARAM_ANGULAR_MOTION_RESTITUTION" value="17"> + </constant> + <constant name="PARAM_ANGULAR_MOTION_DAMPING" value="18"> + </constant> + <constant name="PARAM_ANGULAR_ORTHOGONAL_SOFTNESS" value="19"> + </constant> + <constant name="PARAM_ANGULAR_ORTHOGONAL_RESTITUTION" value="20"> + </constant> + <constant name="PARAM_ANGULAR_ORTHOGONAL_DAMPING" value="21"> + </constant> + <constant name="PARAM_MAX" value="22"> + </constant> + </constants> +</class> <class name="SoundPlayer2D" inherits="Node2D" category="Core"> <brief_description> Base class for playing spatial 2D sound. @@ -23250,13 +26298,13 @@ <method name="set_param" > <argument index="0" name="param" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="param" type="int"> </argument> @@ -23288,13 +26336,13 @@ <method name="set_param" > <argument index="0" name="param" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="param" type="int"> </argument> @@ -23448,7 +26496,33 @@ <description> </description> </method> + <method name="show" > + <description> + </description> + </method> + <method name="hide" > + <description> + </description> + </method> + <method name="is_visible" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="is_hidden" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> </methods> + <signals> + <signal name="visibility_changed"> + <description> + </description> + </signal> + </signals> <constants> <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29"> Spatial nodes receive this notifacation with their global transform changes. This means that either the current or a parent node changed it's transform. @@ -23457,6 +26531,8 @@ </constant> <constant name="NOTIFICATION_EXIT_WORLD" value="42"> </constant> + <constant name="NOTIFICATION_VISIBILITY_CHANGED" value="43"> + </constant> </constants> </class> <class name="SpatialPlayer" inherits="Spatial" category="Core"> @@ -23468,13 +26544,13 @@ <method name="set_param" > <argument index="0" name="param" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_param" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="param" type="int"> </argument> @@ -23544,7 +26620,7 @@ <method name="voice_set_pitch_scale" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="ratio" type="real"> + <argument index="1" name="ratio" type="float"> </argument> <description> </description> @@ -23552,7 +26628,7 @@ <method name="voice_set_volume_scale_db" > <argument index="0" name="voice" type="int"> </argument> - <argument index="1" name="db" type="real"> + <argument index="1" name="db" type="float"> </argument> <description> </description> @@ -23682,13 +26758,13 @@ </description> </method> <method name="get_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="seek_pos" > - <argument index="0" name="time" type="real"> + <argument index="0" name="time" type="float"> </argument> <description> </description> @@ -23704,13 +26780,13 @@ </description> <methods> <method name="set_radius" > - <argument index="0" name="radius" type="real"> + <argument index="0" name="radius" type="float"> </argument> <description> </description> </method> <method name="get_radius" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -23777,6 +26853,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="updown" type="Texture"> + </theme_item> + </theme_items> </class> <class name="SplitContainer" inherits="Container" category="Core"> <brief_description> @@ -24008,6 +27088,240 @@ <constants> </constants> </class> +<class name="Sprite3D" inherits="SpriteBase3D" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_texture" > + <argument index="0" name="texture" type="Texture"> + </argument> + <description> + </description> + </method> + <method name="get_texture" qualifiers="const" > + <return type="Texture"> + </return> + <description> + </description> + </method> + <method name="set_region" > + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_region" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_region_rect" > + <argument index="0" name="rect" type="Rect2"> + </argument> + <description> + </description> + </method> + <method name="get_region_rect" qualifiers="const" > + <return type="Rect2"> + </return> + <description> + </description> + </method> + <method name="set_frame" > + <argument index="0" name="frame" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_frame" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_vframes" > + <argument index="0" name="vframes" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_vframes" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_hframes" > + <argument index="0" name="hframes" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_hframes" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> +<class name="SpriteBase3D" inherits="GeometryInstance" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_centered" > + <argument index="0" name="centered" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_centered" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_offset" > + <argument index="0" name="offset" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_offset" qualifiers="const" > + <return type="Vector2"> + </return> + <description> + </description> + </method> + <method name="set_flip_h" > + <argument index="0" name="flip_h" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_flipped_h" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_flip_v" > + <argument index="0" name="flip_v" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_flipped_v" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_modulate" > + <argument index="0" name="modulate" type="Color"> + </argument> + <description> + </description> + </method> + <method name="get_modulate" qualifiers="const" > + <return type="Color"> + </return> + <description> + </description> + </method> + <method name="set_opacity" > + <argument index="0" name="opacity" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_opacity" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_pixel_size" > + <argument index="0" name="pixel_size" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_pixel_size" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_axis" > + <argument index="0" name="axis" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_axis" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_draw_flag" > + <argument index="0" name="flag" type="int"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_draw_flag" qualifiers="const" > + <return type="bool"> + </return> + <argument index="0" name="flag" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_alpha_cut_mode" > + <argument index="0" name="mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_alpha_cut_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_item_rect" qualifiers="const" > + <return type="Rect2"> + </return> + <description> + </description> + </method> + </methods> + <constants> + <constant name="FLAG_TRANSPARENT" value="0"> + </constant> + <constant name="FLAG_SHADED" value="1"> + </constant> + <constant name="FLAG_MAX" value="2"> + </constant> + <constant name="ALPHA_CUT_DISABLED" value="0"> + </constant> + <constant name="ALPHA_CUT_DISCARD" value="1"> + </constant> + <constant name="ALPHA_CUT_OPAQUE_PREPASS" value="2"> + </constant> + </constants> +</class> <class name="SpriteFrames" inherits="Resource" category="Core"> <brief_description> Sprite frame library for AnimatedSprite. @@ -24073,18 +27387,6 @@ StaticBody implements a static collision [Node], by utilizing a rigid body in the [PhysicsServer]. Static bodies are used for static collision. For more information on physics body nodes, see [PhysicsBody]. </description> <methods> - <method name="set_simulate_motion" > - <argument index="0" name="enabled" type="bool"> - </argument> - <description> - </description> - </method> - <method name="is_simulating_motion" qualifiers="const" > - <return type="bool"> - </return> - <description> - </description> - </method> <method name="set_constant_linear_velocity" > <argument index="0" name="vel" type="Vector3"> </argument> @@ -24109,6 +27411,30 @@ <description> </description> </method> + <method name="set_friction" > + <argument index="0" name="friction" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_friction" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_bounce" > + <argument index="0" name="bounce" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_bounce" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> @@ -24131,7 +27457,7 @@ </description> </method> <method name="set_constant_angular_velocity" > - <argument index="0" name="vel" type="real"> + <argument index="0" name="vel" type="float"> </argument> <description> Set a constant angular velocity for the body. @@ -24145,32 +27471,32 @@ </description> </method> <method name="get_constant_angular_velocity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the constant angular velocity for the body. </description> </method> <method name="set_friction" > - <argument index="0" name="friction" type="real"> + <argument index="0" name="friction" type="float"> </argument> <description> </description> </method> <method name="get_friction" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_bounce" > - <argument index="0" name="bounce" type="real"> + <argument index="0" name="bounce" type="float"> </argument> <description> </description> </method> <method name="get_bounce" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -24227,6 +27553,54 @@ <constants> </constants> </class> +<class name="StreamPeerSSL" inherits="StreamPeer" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="accept" > + <return type="int"> + </return> + <argument index="0" name="stream" type="StreamPeer"> + </argument> + <description> + </description> + </method> + <method name="connect" > + <return type="int"> + </return> + <argument index="0" name="stream" type="StreamPeer"> + </argument> + <argument index="1" name="validate_certs" type="bool" default="false"> + </argument> + <argument index="2" name="for_hostname" type="String" default=""""> + </argument> + <description> + </description> + </method> + <method name="get_status" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="disconnect" > + <description> + </description> + </method> + </methods> + <constants> + <constant name="STATUS_DISCONNECTED" value="0"> + </constant> + <constant name="STATUS_CONNECTED" value="1"> + </constant> + <constant name="STATUS_ERROR_NO_CERTIFICATE" value="2"> + </constant> + <constant name="STATUS_ERROR_HOSTNAME_MISMATCH" value="3"> + </constant> + </constants> +</class> <class name="StreamPeerTCP" inherits="StreamPeer" category="Core"> <brief_description> TCP Stream peer. @@ -24251,6 +27625,12 @@ <description> </description> </method> + <method name="get_status" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> <method name="get_connected_host" qualifiers="const" > <return type="String"> </return> @@ -24269,6 +27649,14 @@ </method> </methods> <constants> + <constant name="STATUS_NONE" value="0"> + </constant> + <constant name="STATUS_CONNECTING" value="1"> + </constant> + <constant name="STATUS_CONNECTED" value="2"> + </constant> + <constant name="STATUS_ERROR" value="3"> + </constant> </constants> </class> <class name="StreamPlayer" inherits="Node" category="Core"> @@ -24330,25 +27718,25 @@ </description> </method> <method name="set_volume" > - <argument index="0" name="volume" type="real"> + <argument index="0" name="volume" type="float"> </argument> <description> </description> </method> <method name="get_volume" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_volume_db" > - <argument index="0" name="db" type="real"> + <argument index="0" name="db" type="float"> </argument> <description> </description> </method> <method name="get_volume_db" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -24366,13 +27754,13 @@ </description> </method> <method name="get_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="seek_pos" > - <argument index="0" name="time" type="real"> + <argument index="0" name="time" type="float"> </argument> <description> </description> @@ -24390,7 +27778,7 @@ </description> </method> <method name="get_length" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -24600,6 +27988,18 @@ Do a simple, case insensitive, expression matching, using ? and * wildcards. </description> </method> + <method name="md5_buffer" > + <return type="RawArray"> + </return> + <description> + </description> + </method> + <method name="md5_text" > + <return type="String"> + </return> + <description> + </description> + </method> <method name="nocasecmp_to" > <return type="int"> </return> @@ -24746,7 +28146,7 @@ </description> </method> <method name="to_float" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -24863,14 +28263,14 @@ <method name="set_default_margin" > <argument index="0" name="margin" type="int"> </argument> - <argument index="1" name="offset" type="real"> + <argument index="1" name="offset" type="float"> </argument> <description> Set the default offset "offset" of the margin "margin" (see MARGIN_* enum) for a StyleBox, Controls that draw styleboxes with context inside need to know the margin, so the border of the stylebox is not occluded. </description> </method> <method name="get_default_margin" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="margin" type="int"> </argument> @@ -24879,7 +28279,7 @@ </description> </method> <method name="get_margin" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="margin" type="int"> </argument> @@ -25054,14 +28454,14 @@ <method name="set_expand_margin_size" > <argument index="0" name="margin" type="int"> </argument> - <argument index="1" name="size" type="real"> + <argument index="1" name="size" type="float"> </argument> <description> Set an expand margin size (from enum MARGIN_*). Parts of the image below the size of the margin (and in the direction of the margin) will not expand. </description> </method> <method name="get_expand_margin_size" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -25096,13 +28496,13 @@ <method name="set_margin_size" > <argument index="0" name="margin" type="int"> </argument> - <argument index="1" name="size" type="real"> + <argument index="1" name="size" type="float"> </argument> <description> </description> </method> <method name="get_margin_size" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -25112,13 +28512,13 @@ <method name="set_expand_margin_size" > <argument index="0" name="margin" type="int"> </argument> - <argument index="1" name="size" type="real"> + <argument index="1" name="size" type="float"> </argument> <description> </description> </method> <method name="get_expand_margin_size" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="int"> </argument> @@ -25203,6 +28603,12 @@ <description> </description> </method> + <method name="add_smooth_group" > + <argument index="0" name="smooth" type="bool"> + </argument> + <description> + </description> + </method> <method name="set_material" > <argument index="0" name="material" type="Material"> </argument> @@ -25217,15 +28623,7 @@ <description> </description> </method> - <method name="generate_flat_normals" > - <description> - </description> - </method> - <method name="generate_smooth_normals" > - <description> - </description> - </method> - <method name="generate_tangents" > + <method name="generate_normals" > <description> </description> </method> @@ -25392,6 +28790,38 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="label_valign_fg" type="int"> + </theme_item> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="label_valign_bg" type="int"> + </theme_item> + <theme_item name="top_margin" type="int"> + </theme_item> + <theme_item name="side_margin" type="int"> + </theme_item> + <theme_item name="font_color_bg" type="Color"> + </theme_item> + <theme_item name="font_color_fg" type="Color"> + </theme_item> + <theme_item name="increment_hilite" type="Texture"> + </theme_item> + <theme_item name="decrement_hilite" type="Texture"> + </theme_item> + <theme_item name="increment" type="Texture"> + </theme_item> + <theme_item name="decrement" type="Texture"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="tab_fg" type="StyleBox"> + </theme_item> + <theme_item name="tab_bg" type="StyleBox"> + </theme_item> + <theme_item name="panel" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="Tabs" inherits="Control" category="Core"> <brief_description> @@ -25457,6 +28887,14 @@ <description> </description> </method> + <method name="add_tab" > + <argument index="0" name="title" type="String"> + </argument> + <argument index="1" name="icon" type="Texture"> + </argument> + <description> + </description> + </method> </methods> <signals> <signal name="tab_changed"> @@ -25468,6 +28906,28 @@ </signals> <constants> </constants> + <theme_items> + <theme_item name="label_valign_fg" type="int"> + </theme_item> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="label_valign_bg" type="int"> + </theme_item> + <theme_item name="top_margin" type="int"> + </theme_item> + <theme_item name="font_color_bg" type="Color"> + </theme_item> + <theme_item name="font_color_fg" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="tab_fg" type="StyleBox"> + </theme_item> + <theme_item name="tab_bg" type="StyleBox"> + </theme_item> + <theme_item name="panel" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="TestCube" inherits="GeometryInstance" category="Core"> <brief_description> @@ -25648,6 +29108,12 @@ Return the text inside the selection. </description> </method> + <method name="get_word_under_cursor" qualifiers="const" > + <return type="String"> + </return> + <description> + </description> + </method> <method name="search" qualifiers="const" > <return type="IntArray"> </return> @@ -25765,6 +29231,48 @@ Search from end to begining. </constant> </constants> + <theme_items> + <theme_item name="line_spacing" type="int"> + </theme_item> + <theme_item name="completion_lines" type="int"> + </theme_item> + <theme_item name="completion_max_width" type="int"> + </theme_item> + <theme_item name="completion_scroll_width" type="int"> + </theme_item> + <theme_item name="symbol_color" type="Color"> + </theme_item> + <theme_item name="cursor_color" type="Color"> + </theme_item> + <theme_item name="selection_color" type="Color"> + </theme_item> + <theme_item name="completion_existing" type="Color"> + </theme_item> + <theme_item name="breakpoint_color" type="Color"> + </theme_item> + <theme_item name="font_color_selected" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="completion_scroll_color" type="Color"> + </theme_item> + <theme_item name="current_line_color" type="Color"> + </theme_item> + <theme_item name="mark_color" type="Color"> + </theme_item> + <theme_item name="tab" type="Texture"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + <theme_item name="completion_selected" type="StyleBox"> + </theme_item> + <theme_item name="completion" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="Texture" inherits="Resource" category="Core"> <brief_description> @@ -25868,12 +29376,16 @@ <constant name="FLAG_FILTER" value="4"> Turn on magnifying filter. </constant> - <constant name="FLAG_VIDEO_SURFACE" value="16"> + <constant name="FLAG_VIDEO_SURFACE" value="4096"> Texture is a video surface </constant> <constant name="FLAGS_DEFAULT" value="7"> Default flags </constant> + <constant name="FLAG_ANISOTROPIC_FILTER" value="8"> + </constant> + <constant name="FLAG_CONVERT_TO_LINEAR" value="16"> + </constant> </constants> </class> <class name="TextureButton" inherits="BaseButton" category="Core"> @@ -26393,15 +29905,51 @@ Return the current tileset. </description> </method> + <method name="set_mode" > + <argument index="0" name="mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_half_offset" > + <argument index="0" name="half_offset" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_half_offset" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_custom_transform" > + <argument index="0" name="custom_transform" type="Matrix32"> + </argument> + <description> + </description> + </method> + <method name="get_custom_transform" qualifiers="const" > + <return type="Matrix32"> + </return> + <description> + </description> + </method> <method name="set_cell_size" > - <argument index="0" name="size" type="int"> + <argument index="0" name="size" type="Vector2"> </argument> <description> Set the cell size. </description> </method> <method name="get_cell_size" qualifiers="const" > - <return type="int"> + <return type="Vector2"> </return> <description> Return the cell size. @@ -26449,6 +29997,42 @@ Return true if tiles are to be centered in y coordinate (by default this is false and they are drawn from upper left cell corner). </description> </method> + <method name="set_collision_layer_mask" > + <argument index="0" name="mask" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_collision_layer_mask" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_collision_friction" > + <argument index="0" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_collision_friction" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_collision_bounce" > + <argument index="0" name="value" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_collision_bounce" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> <method name="set_cell" > <argument index="0" name="x" type="int"> </argument> @@ -26502,11 +30086,47 @@ Clear all cells. </description> </method> + <method name="map_to_world" qualifiers="const" > + <return type="Vector2"> + </return> + <argument index="0" name="mappos" type="Vector2"> + </argument> + <argument index="1" name="ignore_half_ofs" type="bool" default="false"> + </argument> + <description> + </description> + </method> + <method name="world_to_map" qualifiers="const" > + <return type="Vector2"> + </return> + <argument index="0" name="worldpos" type="Vector2"> + </argument> + <description> + </description> + </method> </methods> + <signals> + <signal name="settings_changed"> + <description> + </description> + </signal> + </signals> <constants> <constant name="INVALID_CELL" value="-1"> Returned when a cell doesn't exist. </constant> + <constant name="MODE_SQUARE" value="0"> + </constant> + <constant name="MODE_ISOMETRIC" value="1"> + </constant> + <constant name="MODE_CUSTOM" value="2"> + </constant> + <constant name="HALF_OFFSET_X" value="0"> + </constant> + <constant name="HALF_OFFSET_Y" value="1"> + </constant> + <constant name="HALF_OFFSET_DISABLED" value="2"> + </constant> </constants> </class> <class name="TileSet" inherits="Resource" category="Core"> @@ -26690,14 +30310,14 @@ </description> <methods> <method name="set_wait_time" > - <argument index="0" name="time_sec" type="real"> + <argument index="0" name="time_sec" type="float"> </argument> <description> Set wait time. When the time is over, it will emit timeout signal. </description> </method> <method name="get_wait_time" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the wait time. When the time is over, it will emit timeout signal. @@ -26742,7 +30362,7 @@ </description> </method> <method name="get_time_left" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> Return the time left for timeout if the timer is active. @@ -26845,11 +30465,11 @@ </method> </methods> <signals> - <signal name="pressed"> + <signal name="released"> <description> </description> </signal> - <signal name="released"> + <signal name="pressed"> <description> </description> </signal> @@ -26899,7 +30519,7 @@ </return> <argument index="0" name="axis" type="Vector3"> </argument> - <argument index="1" name="phi" type="real"> + <argument index="1" name="phi" type="float"> </argument> <description> </description> @@ -27040,6 +30660,12 @@ Return all the messages (keys). </description> </method> + <method name="get_message_count" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> </methods> <constants> </constants> @@ -27083,6 +30709,10 @@ <description> </description> </method> + <method name="clear" > + <description> + </description> + </method> </methods> <constants> </constants> @@ -27310,6 +30940,66 @@ <constant name="SELECT_MULTI" value="2"> </constant> </constants> + <theme_items> + <theme_item name="item_margin" type="int"> + </theme_item> + <theme_item name="vseparation" type="int"> + </theme_item> + <theme_item name="guide_width" type="int"> + </theme_item> + <theme_item name="hseparation" type="int"> + </theme_item> + <theme_item name="button_margin" type="int"> + </theme_item> + <theme_item name="title_button_color" type="Color"> + </theme_item> + <theme_item name="guide_color" type="Color"> + </theme_item> + <theme_item name="cursor_color" type="Color"> + </theme_item> + <theme_item name="selection_color" type="Color"> + </theme_item> + <theme_item name="font_color_selected" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="arrow" type="Texture"> + </theme_item> + <theme_item name="updown" type="Texture"> + </theme_item> + <theme_item name="checked" type="Texture"> + </theme_item> + <theme_item name="arrow_collapsed" type="Texture"> + </theme_item> + <theme_item name="select_arrow" type="Texture"> + </theme_item> + <theme_item name="unchecked" type="Texture"> + </theme_item> + <theme_item name="title_button_font" type="Font"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="title_button_normal" type="StyleBox"> + </theme_item> + <theme_item name="cursor" type="StyleBox"> + </theme_item> + <theme_item name="title_button_hover" type="StyleBox"> + </theme_item> + <theme_item name="selected_focus" type="StyleBox"> + </theme_item> + <theme_item name="bg_focus" type="StyleBox"> + </theme_item> + <theme_item name="button_pressed" type="StyleBox"> + </theme_item> + <theme_item name="cursor_unfocused" type="StyleBox"> + </theme_item> + <theme_item name="selected" type="StyleBox"> + </theme_item> + <theme_item name="bg" type="StyleBox"> + </theme_item> + <theme_item name="title_button_pressed" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="TreeItem" inherits="Object" category="Core"> <brief_description> @@ -27416,13 +31106,13 @@ <method name="set_range" > <argument index="0" name="column" type="int"> </argument> - <argument index="1" name="value" type="real"> + <argument index="1" name="value" type="float"> </argument> <description> </description> </method> <method name="get_range" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="column" type="int"> </argument> @@ -27432,11 +31122,11 @@ <method name="set_range_config" > <argument index="0" name="column" type="int"> </argument> - <argument index="1" name="min" type="real"> + <argument index="1" name="min" type="float"> </argument> - <argument index="2" name="max" type="real"> + <argument index="2" name="max" type="float"> </argument> - <argument index="3" name="step" type="real"> + <argument index="3" name="step" type="float"> </argument> <argument index="4" name="expr" type="bool" default="false"> </argument> @@ -27691,6 +31381,368 @@ </constant> </constants> </class> +<class name="Tween" inherits="Node" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="is_active" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_active" > + <argument index="0" name="active" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_repeat" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_repeat" > + <argument index="0" name="repeat" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_speed" > + <argument index="0" name="speed" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_speed" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_tween_process_mode" > + <argument index="0" name="mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_tween_process_mode" qualifiers="const" > + <return type="int"> + </return> + <description> + </description> + </method> + <method name="start" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="reset" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <description> + </description> + </method> + <method name="reset_all" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="stop" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <description> + </description> + </method> + <method name="stop_all" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="resume" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <description> + </description> + </method> + <method name="resume_all" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="remove" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <description> + </description> + </method> + <method name="remove_all" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="seek" > + <return type="bool"> + </return> + <argument index="0" name="time" type="float"> + </argument> + <description> + </description> + </method> + <method name="tell" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="get_runtime" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="interpolate_property" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="property" type="String"> + </argument> + <argument index="2" name="initial_val" type="var"> + </argument> + <argument index="3" name="final_val" type="var"> + </argument> + <argument index="4" name="times_in_sec" type="float"> + </argument> + <argument index="5" name="trans_type" type="int"> + </argument> + <argument index="6" name="ease_type" type="int"> + </argument> + <argument index="7" name="delay" type="float" default="0"> + </argument> + <description> + </description> + </method> + <method name="interpolate_method" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="method" type="String"> + </argument> + <argument index="2" name="initial_val" type="var"> + </argument> + <argument index="3" name="final_val" type="var"> + </argument> + <argument index="4" name="times_in_sec" type="float"> + </argument> + <argument index="5" name="trans_type" type="int"> + </argument> + <argument index="6" name="ease_type" type="int"> + </argument> + <argument index="7" name="delay" type="float" default="0"> + </argument> + <description> + </description> + </method> + <method name="interpolate_callback" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="callback" type="String"> + </argument> + <argument index="2" name="times_in_sec" type="float"> + </argument> + <argument index="3" name="args" type="var" default="NULL"> + </argument> + <description> + </description> + </method> + <method name="follow_property" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="property" type="String"> + </argument> + <argument index="2" name="initial_val" type="var"> + </argument> + <argument index="3" name="target" type="Object"> + </argument> + <argument index="4" name="target_property" type="String"> + </argument> + <argument index="5" name="times_in_sec" type="float"> + </argument> + <argument index="6" name="trans_type" type="int"> + </argument> + <argument index="7" name="ease_type" type="int"> + </argument> + <argument index="8" name="delay" type="float" default="0"> + </argument> + <description> + </description> + </method> + <method name="follow_method" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="method" type="String"> + </argument> + <argument index="2" name="initial_val" type="var"> + </argument> + <argument index="3" name="target" type="Object"> + </argument> + <argument index="4" name="target_method" type="String"> + </argument> + <argument index="5" name="times_in_sec" type="float"> + </argument> + <argument index="6" name="trans_type" type="int"> + </argument> + <argument index="7" name="ease_type" type="int"> + </argument> + <argument index="8" name="delay" type="float" default="0"> + </argument> + <description> + </description> + </method> + <method name="targeting_property" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="property" type="String"> + </argument> + <argument index="2" name="initial" type="Object"> + </argument> + <argument index="3" name="initial_val" type="String"> + </argument> + <argument index="4" name="final_val" type="var"> + </argument> + <argument index="5" name="times_in_sec" type="float"> + </argument> + <argument index="6" name="trans_type" type="int"> + </argument> + <argument index="7" name="ease_type" type="int"> + </argument> + <argument index="8" name="delay" type="float" default="0"> + </argument> + <description> + </description> + </method> + <method name="targeting_method" > + <return type="bool"> + </return> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="method" type="String"> + </argument> + <argument index="2" name="initial" type="Object"> + </argument> + <argument index="3" name="initial_method" type="String"> + </argument> + <argument index="4" name="final_val" type="var"> + </argument> + <argument index="5" name="times_in_sec" type="float"> + </argument> + <argument index="6" name="trans_type" type="int"> + </argument> + <argument index="7" name="ease_type" type="int"> + </argument> + <argument index="8" name="delay" type="float" default="0"> + </argument> + <description> + </description> + </method> + </methods> + <signals> + <signal name="tween_complete"> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <description> + </description> + </signal> + <signal name="tween_step"> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <argument index="2" name="elapsed" type="float"> + </argument> + <argument index="3" name="value" type="Object"> + </argument> + <description> + </description> + </signal> + <signal name="tween_start"> + <argument index="0" name="node" type="Object"> + </argument> + <argument index="1" name="key" type="String"> + </argument> + <description> + </description> + </signal> + </signals> + <constants> + <constant name="TRANS_LINEAR" value="0"> + </constant> + <constant name="TRANS_SINE" value="1"> + </constant> + <constant name="TRANS_QUINT" value="2"> + </constant> + <constant name="TRANS_QUART" value="3"> + </constant> + <constant name="TRANS_QUAD" value="4"> + </constant> + <constant name="TRANS_EXPO" value="5"> + </constant> + <constant name="TRANS_ELASTIC" value="6"> + </constant> + <constant name="TRANS_CUBIC" value="7"> + </constant> + <constant name="TRANS_CIRC" value="8"> + </constant> + <constant name="TRANS_BOUNCE" value="9"> + </constant> + <constant name="TRANS_BACK" value="10"> + </constant> + <constant name="EASE_IN" value="0"> + </constant> + <constant name="EASE_OUT" value="1"> + </constant> + <constant name="EASE_IN_OUT" value="2"> + </constant> + <constant name="EASE_OUT_IN" value="3"> + </constant> + </constants> +</class> <class name="UnshadedMaterial" inherits="Material" category="Core"> <brief_description> </brief_description> @@ -27748,6 +31800,10 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="separation" type="int"> + </theme_item> + </theme_items> </class> <class name="VButtonArray" inherits="ButtonArray" category="Core"> <brief_description> @@ -27760,6 +31816,28 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="button_separator" type="int"> + </theme_item> + <theme_item name="icon_separator" type="int"> + </theme_item> + <theme_item name="font_color_selected" type="Color"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_selected" type="Font"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="hover" type="StyleBox"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="selected" type="StyleBox"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="VScrollBar" inherits="ScrollBar" category="Core"> <brief_description> @@ -27771,6 +31849,24 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="increment_hilite" type="Texture"> + </theme_item> + <theme_item name="decrement_hilite" type="Texture"> + </theme_item> + <theme_item name="increment" type="Texture"> + </theme_item> + <theme_item name="decrement" type="Texture"> + </theme_item> + <theme_item name="grabber_hilite" type="StyleBox"> + </theme_item> + <theme_item name="grabber" type="StyleBox"> + </theme_item> + <theme_item name="scroll_focus" type="StyleBox"> + </theme_item> + <theme_item name="scroll" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="VSeparator" inherits="Separator" category="Core"> <brief_description> @@ -27783,6 +31879,12 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="separation" type="int"> + </theme_item> + <theme_item name="separator" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="VSlider" inherits="Slider" category="Core"> <brief_description> @@ -27795,6 +31897,18 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="tick" type="Texture"> + </theme_item> + <theme_item name="grabber_hilite" type="Texture"> + </theme_item> + <theme_item name="grabber" type="Texture"> + </theme_item> + <theme_item name="grabber_hilite" type="StyleBox"> + </theme_item> + <theme_item name="slider" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="VSplitContainer" inherits="SplitContainer" category="Core"> <brief_description> @@ -27807,6 +31921,16 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="autohide" type="int"> + </theme_item> + <theme_item name="separation" type="int"> + </theme_item> + <theme_item name="grabber" type="Texture"> + </theme_item> + <theme_item name="bg" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="Vector2" category="Built-In Types"> <brief_description> @@ -27816,13 +31940,27 @@ </description> <methods> <method name="angle_to" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="to" type="Vector2"> </argument> <description> </description> </method> + <method name="angle_to_point" > + <return type="float"> + </return> + <argument index="0" name="to" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="atan2" > + <return type="float"> + </return> + <description> + </description> + </method> <method name="cubic_interpolate" > <return type="Vector2"> </return> @@ -27832,13 +31970,13 @@ </argument> <argument index="2" name="post_b" type="Vector2"> </argument> - <argument index="3" name="t" type="real"> + <argument index="3" name="t" type="float"> </argument> <description> </description> </method> <method name="distance_squared_to" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="to" type="Vector2"> </argument> @@ -27846,7 +31984,7 @@ </description> </method> <method name="distance_to" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="to" type="Vector2"> </argument> @@ -27855,7 +31993,7 @@ </description> </method> <method name="dot" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="with" type="Vector2"> </argument> @@ -27877,20 +32015,20 @@ </description> </method> <method name="get_aspect" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="length" > - <return type="real"> + <return type="float"> </return> <description> Returns the length of the vector. </description> </method> <method name="length_squared" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -27900,7 +32038,7 @@ </return> <argument index="0" name="b" type="Vector2"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> Returns the result of the linear interpolation between this vector and "b", by amount "i". @@ -27914,7 +32052,7 @@ </description> </method> <method name="reflect" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="vec" type="Vector2"> </argument> @@ -27924,13 +32062,13 @@ <method name="rotated" > <return type="Vector2"> </return> - <argument index="0" name="phi" type="real"> + <argument index="0" name="phi" type="float"> </argument> <description> </description> </method> <method name="slide" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="vec" type="Vector2"> </argument> @@ -27952,22 +32090,22 @@ </description> </method> <method name="Vector2" > - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> <description> </description> </method> </methods> <members> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> - <member name="width" type="real"> + <member name="width" type="float"> </member> - <member name="height" type="real"> + <member name="height" type="float"> </member> </members> <constants> @@ -28055,14 +32193,14 @@ </argument> <argument index="2" name="post_b" type="Vector3"> </argument> - <argument index="3" name="t" type="real"> + <argument index="3" name="t" type="float"> </argument> <description> Perform a cubic interpolation between vectors a,b,c,d (b is current), by the given amount (i). </description> </method> <method name="distance_squared_to" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="b" type="Vector3"> </argument> @@ -28071,7 +32209,7 @@ </description> </method> <method name="distance_to" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="b" type="Vector3"> </argument> @@ -28080,7 +32218,7 @@ </description> </method> <method name="dot" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="b" type="Vector3"> </argument> @@ -28096,14 +32234,14 @@ </description> </method> <method name="length" > - <return type="real"> + <return type="float"> </return> <description> Return the length of the vector. </description> </method> <method name="length_squared" > - <return type="real"> + <return type="float"> </return> <description> Return the length of the vector, without the square root step. @@ -28114,7 +32252,7 @@ </return> <argument index="0" name="b" type="Vector3"> </argument> - <argument index="1" name="t" type="real"> + <argument index="1" name="t" type="float"> </argument> <description> Linearly interpolates the vector to a given one (b), by the given amount (i) @@ -28139,12 +32277,28 @@ Return a copy of the normalized vector to unit length. This is the same as v / v.length() </description> </method> + <method name="reflect" > + <return type="Vector3"> + </return> + <argument index="0" name="by" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="rotated" > <return type="Vector3"> </return> <argument index="0" name="axis" type="Vector3"> </argument> - <argument index="1" name="phi" type="real"> + <argument index="1" name="phi" type="float"> + </argument> + <description> + </description> + </method> + <method name="slide" > + <return type="Vector3"> + </return> + <argument index="0" name="by" type="Vector3"> </argument> <description> </description> @@ -28152,29 +32306,29 @@ <method name="snapped" > <return type="Vector3"> </return> - <argument index="0" name="by" type="real"> + <argument index="0" name="by" type="float"> </argument> <description> Return a copy of the vector, snapped to the lowest neared multiple. </description> </method> <method name="Vector3" > - <argument index="0" name="x" type="real"> + <argument index="0" name="x" type="float"> </argument> - <argument index="1" name="y" type="real"> + <argument index="1" name="y" type="float"> </argument> - <argument index="2" name="z" type="real"> + <argument index="2" name="z" type="float"> </argument> <description> </description> </method> </methods> <members> - <member name="x" type="real"> + <member name="x" type="float"> </member> - <member name="y" type="real"> + <member name="y" type="float"> </member> - <member name="z" type="real"> + <member name="z" type="float"> </member> </members> <constants> @@ -28236,6 +32390,206 @@ <constants> </constants> </class> +<class name="VehicleBody" inherits="PhysicsBody" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_mass" > + <argument index="0" name="mass" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_mass" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_friction" > + <argument index="0" name="friction" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_friction" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_engine_force" > + <argument index="0" name="engine_force" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_engine_force" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_brake" > + <argument index="0" name="brake" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_brake" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_steering" > + <argument index="0" name="steering" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_steering" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> +<class name="VehicleWheel" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_radius" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_radius" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_suspension_rest_length" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_suspension_rest_length" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_suspension_travel" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_suspension_travel" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_suspension_stiffness" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_suspension_stiffness" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_suspension_max_force" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_suspension_max_force" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_damping_compression" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_damping_compression" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_damping_relaxation" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_damping_relaxation" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_use_as_traction" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_used_as_traction" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_use_as_steering" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_used_as_steering" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_friction_slip" > + <argument index="0" name="length" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_friction_slip" qualifiers="const" > + <return type="float"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="VideoPlayer" inherits="Control" category="Core"> <brief_description> </brief_description> @@ -28281,25 +32635,25 @@ </description> </method> <method name="set_volume" > - <argument index="0" name="volume" type="real"> + <argument index="0" name="volume" type="float"> </argument> <description> </description> </method> <method name="get_volume" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> </method> <method name="set_volume_db" > - <argument index="0" name="db" type="real"> + <argument index="0" name="db" type="float"> </argument> <description> </description> </method> <method name="get_volume_db" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <description> </description> @@ -28310,8 +32664,8 @@ <description> </description> </method> - <method name="get_pos" qualifiers="const" > - <return type="real"> + <method name="get_stream_pos" qualifiers="const" > + <return type="float"> </return> <description> </description> @@ -28344,7 +32698,7 @@ <constants> </constants> </class> -<class name="VideoStream" inherits="AudioStreamResampled" category="Core"> +<class name="VideoStream" inherits="Resource" category="Core"> <brief_description> </brief_description> <description> @@ -28357,8 +32711,8 @@ </description> </method> <method name="pop_frame" > - <return type="Image"> - </return> + <argument index="0" name="arg0" type="Object"> + </argument> <description> </description> </method> @@ -28368,16 +32722,12 @@ <description> </description> </method> - </methods> - <constants> - </constants> -</class> -<class name="VideoStreamTheora" inherits="VideoStream" category="Core"> - <brief_description> - </brief_description> - <description> - </description> - <methods> + <method name="set_audio_track" > + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> </methods> <constants> </constants> @@ -28540,6 +32890,42 @@ <description> </description> </method> + <method name="set_render_target_vflip" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_render_target_vflip" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_render_target_filter" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_render_target_filter" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_render_target_gen_mipmaps" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_render_target_gen_mipmaps" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="set_render_target_update_mode" > <argument index="0" name="mode" type="int"> </argument> @@ -28558,6 +32944,18 @@ <description> </description> </method> + <method name="set_physics_object_picking" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_physics_object_picking" > + <return type="bool"> + </return> + <description> + </description> + </method> <method name="get_viewport" qualifiers="const" > <return type="RID"> </return> @@ -28565,10 +32963,40 @@ Get the viewport RID from the visual server. </description> </method> + <method name="input" > + <argument index="0" name="local_event" type="InputEvent"> + </argument> + <description> + </description> + </method> + <method name="unhandled_input" > + <argument index="0" name="local_event" type="InputEvent"> + </argument> + <description> + </description> + </method> <method name="update_worlds" > <description> </description> </method> + <method name="set_use_own_world" > + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_using_own_world" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="get_camera" qualifiers="const" > + <return type="Camera"> + </return> + <description> + </description> + </method> <method name="set_as_audio_listener" > <argument index="0" name="enable" type="bool"> </argument> @@ -28593,6 +33021,12 @@ <description> </description> </method> + <method name="set_render_target_to_screen_rect" > + <argument index="0" name="arg0" type="Rect2"> + </argument> + <description> + </description> + </method> </methods> <signals> <signal name="size_changed"> @@ -28611,6 +33045,64 @@ </constant> </constants> </class> +<class name="ViewportSprite" inherits="Node2D" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_viewport_path" > + <argument index="0" name="path" type="NodePath"> + </argument> + <description> + </description> + </method> + <method name="get_viewport_path" qualifiers="const" > + <return type="NodePath"> + </return> + <description> + </description> + </method> + <method name="set_centered" > + <argument index="0" name="centered" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_centered" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_offset" > + <argument index="0" name="offset" type="Vector2"> + </argument> + <description> + </description> + </method> + <method name="get_offset" qualifiers="const" > + <return type="Vector2"> + </return> + <description> + </description> + </method> + <method name="set_modulate" > + <argument index="0" name="modulate" type="Color"> + </argument> + <description> + </description> + </method> + <method name="get_modulate" qualifiers="const" > + <return type="Color"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="VisibilityEnabler" inherits="VisibilityNotifier" category="Core"> <brief_description> </brief_description> @@ -28955,13 +33447,13 @@ <method name="material_set_line_width" > <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> <description> </description> </method> <method name="material_get_line_width" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29205,13 +33697,13 @@ </argument> <argument index="1" name="arg1" type="int"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <description> </description> </method> <method name="particles_get_variable" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29225,13 +33717,13 @@ </argument> <argument index="1" name="arg1" type="int"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <description> </description> </method> <method name="particles_get_randomness" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29261,13 +33753,13 @@ </argument> <argument index="1" name="arg1" type="int"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <description> </description> </method> <method name="particles_get_color_phase_pos" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29337,13 +33829,13 @@ </argument> <argument index="1" name="arg1" type="int"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <description> </description> </method> <method name="particles_get_attractor_strength" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29467,13 +33959,13 @@ </argument> <argument index="1" name="arg1" type="int"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <description> </description> </method> <method name="light_get_var" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29587,13 +34079,13 @@ <method name="portal_set_disable_distance" > <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> <description> </description> </method> <method name="portal_get_disable_distance" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> @@ -29625,11 +34117,11 @@ <method name="camera_set_perspective" > <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> - <argument index="3" name="arg3" type="real"> + <argument index="3" name="arg3" type="float"> </argument> <description> </description> @@ -29637,11 +34129,11 @@ <method name="camera_set_orthogonal" > <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> - <argument index="3" name="arg3" type="real"> + <argument index="3" name="arg3" type="float"> </argument> <description> </description> @@ -29865,11 +34357,9 @@ <method name="instances_cull_convex" qualifiers="const" > <return type="Array"> </return> - <argument index="0" name="arg0" type="Vector3"> - </argument> - <argument index="1" name="arg1" type="Vector3"> + <argument index="0" name="arg0" type="Array"> </argument> - <argument index="2" name="arg2" type="RID"> + <argument index="1" name="arg1" type="RID"> </argument> <description> </description> @@ -29953,17 +34443,17 @@ <method name="canvas_item_set_opacity" > <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> <description> </description> </method> <method name="canvas_item_get_opacity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> <description> </description> @@ -29971,17 +34461,17 @@ <method name="canvas_item_set_self_opacity" > <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> <description> </description> </method> <method name="canvas_item_get_self_opacity" qualifiers="const" > - <return type="real"> + <return type="float"> </return> <argument index="0" name="arg0" type="RID"> </argument> - <argument index="1" name="arg1" type="real"> + <argument index="1" name="arg1" type="float"> </argument> <description> </description> @@ -29995,7 +34485,7 @@ </argument> <argument index="3" name="arg3" type="Color"> </argument> - <argument index="4" name="arg4" type="real" default="1"> + <argument index="4" name="arg4" type="float" default="1"> </argument> <description> </description> @@ -30057,7 +34547,7 @@ </argument> <argument index="1" name="arg1" type="Vector2"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <argument index="3" name="arg3" type="Color"> </argument> @@ -30087,7 +34577,7 @@ </description> </method> <method name="cursor_set_rotation" > - <argument index="0" name="arg0" type="real"> + <argument index="0" name="arg0" type="float"> </argument> <argument index="1" name="arg1" type="int"> </argument> @@ -30132,6 +34622,18 @@ <description> </description> </method> + <method name="black_bars_set_images" > + <argument index="0" name="left" type="RID"> + </argument> + <argument index="1" name="top" type="RID"> + </argument> + <argument index="2" name="right" type="RID"> + </argument> + <argument index="3" name="bottom" type="RID"> + </argument> + <description> + </description> + </method> <method name="make_sphere_mesh" > <return type="RID"> </return> @@ -30139,7 +34641,7 @@ </argument> <argument index="1" name="arg1" type="int"> </argument> - <argument index="2" name="arg2" type="real"> + <argument index="2" name="arg2" type="float"> </argument> <description> </description> @@ -30156,6 +34658,10 @@ <description> </description> </method> + <method name="flush" > + <description> + </description> + </method> <method name="free" > <argument index="0" name="arg0" type="RID"> </argument> @@ -30196,7 +34702,7 @@ </constant> <constant name="TEXTURE_FLAG_FILTER" value="4"> </constant> - <constant name="TEXTURE_FLAG_CUBEMAP" value="8"> + <constant name="TEXTURE_FLAG_CUBEMAP" value="2048"> </constant> <constant name="TEXTURE_FLAGS_DEFAULT" value="7"> </constant> @@ -30226,10 +34732,6 @@ </constant> <constant name="MATERIAL_FLAG_ONTOP" value="4"> </constant> - <constant name="MATERIAL_FLAG_WIREFRAME" value="5"> - </constant> - <constant name="MATERIAL_FLAG_BILLBOARD" value="6"> - </constant> <constant name="MATERIAL_FLAG_MAX" value="7"> </constant> <constant name="MATERIAL_BLEND_MODE_MIX" value="0"> @@ -30350,11 +34852,9 @@ </constant> <constant name="LIGHT_SPOT" value="2"> </constant> - <constant name="LIGHT_COLOR_AMBIENT" value="0"> + <constant name="LIGHT_COLOR_DIFFUSE" value="0"> </constant> - <constant name="LIGHT_COLOR_DIFFUSE" value="1"> - </constant> - <constant name="LIGHT_COLOR_SPECULAR" value="2"> + <constant name="LIGHT_COLOR_SPECULAR" value="1"> </constant> <constant name="LIGHT_PARAM_SPOT_ATTENUATION" value="0"> </constant> @@ -30366,7 +34866,7 @@ </constant> <constant name="LIGHT_PARAM_ATTENUATION" value="4"> </constant> - <constant name="LIGHT_PARAM_MAX" value="8"> + <constant name="LIGHT_PARAM_MAX" value="10"> </constant> <constant name="SCENARIO_DEBUG_DISABLED" value="0"> </constant> @@ -30378,15 +34878,15 @@ </constant> <constant name="INSTANCE_MULTIMESH" value="2"> </constant> - <constant name="INSTANCE_PARTICLES" value="3"> + <constant name="INSTANCE_PARTICLES" value="4"> </constant> - <constant name="INSTANCE_LIGHT" value="4"> + <constant name="INSTANCE_LIGHT" value="5"> </constant> - <constant name="INSTANCE_ROOM" value="5"> + <constant name="INSTANCE_ROOM" value="6"> </constant> - <constant name="INSTANCE_PORTAL" value="6"> + <constant name="INSTANCE_PORTAL" value="7"> </constant> - <constant name="INSTANCE_GEOMETRY_MASK" value="14"> + <constant name="INSTANCE_GEOMETRY_MASK" value="30"> </constant> <constant name="INFO_OBJECTS_IN_FRAME" value="0"> </constant> @@ -30442,6 +34942,26 @@ </methods> <constants> </constants> + <theme_items> + <theme_item name="close_h_ofs" type="int"> + </theme_item> + <theme_item name="titlebar_height" type="int"> + </theme_item> + <theme_item name="close_v_ofs" type="int"> + </theme_item> + <theme_item name="title_height" type="int"> + </theme_item> + <theme_item name="title_color" type="Color"> + </theme_item> + <theme_item name="close_hilite" type="Texture"> + </theme_item> + <theme_item name="close" type="Texture"> + </theme_item> + <theme_item name="title_font" type="Font"> + </theme_item> + <theme_item name="panel" type="StyleBox"> + </theme_item> + </theme_items> </class> <class name="World" inherits="Resource" category="Core"> <brief_description> @@ -30677,6 +35197,28 @@ </constant> </constants> </class> +<class name="YSort" inherits="Node2D" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_sort_enabled" > + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_sort_enabled" qualifiers="const" > + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="bool" category="Built-In Types"> <brief_description> Boolean built-in type @@ -30692,7 +35234,7 @@ </description> </method> <method name="bool" > - <argument index="0" name="from" type="real"> + <argument index="0" name="from" type="float"> </argument> <description> </description> @@ -30707,27 +35249,25 @@ <constants> </constants> </class> -<class name="int" category="Built-In Types"> +<class name="float" category="Built-In Types"> <brief_description> - Integer built-in type. </brief_description> <description> - Integer built-in type. </description> <methods> - <method name="int" > + <method name="float" > <argument index="0" name="from" type="bool"> </argument> <description> </description> </method> - <method name="int" > - <argument index="0" name="from" type="real"> + <method name="float" > + <argument index="0" name="from" type="int"> </argument> <description> </description> </method> - <method name="int" > + <method name="float" > <argument index="0" name="from" type="String"> </argument> <description> @@ -30737,27 +35277,27 @@ <constants> </constants> </class> -<class name="real" category="Built-In Types"> +<class name="int" category="Built-In Types"> <brief_description> - Real (float) built-in type. + Integer built-in type. </brief_description> <description> - Real (float) built-in type. + Integer built-in type. </description> <methods> - <method name="real" > + <method name="int" > <argument index="0" name="from" type="bool"> </argument> <description> </description> </method> - <method name="real" > - <argument index="0" name="from" type="int"> + <method name="int" > + <argument index="0" name="from" type="float"> </argument> <description> </description> </method> - <method name="real" > + <method name="int" > <argument index="0" name="from" type="String"> </argument> <description> diff --git a/drivers/SCsub b/drivers/SCsub index bfd35344ea..a1a2191cbc 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -7,9 +7,9 @@ Export('env') SConscript('unix/SCsub');
SConscript('alsa/SCsub');
+SConscript('pulseaudio/SCsub');
SConscript('windows/SCsub');
SConscript('gles2/SCsub');
-SConscript('gles1/SCsub');
SConscript('gl_context/SCsub');
SConscript('openssl/SCsub');
diff --git a/drivers/builtin_openssl2/openssl/md5.h b/drivers/builtin_openssl2/openssl/md5.h index 8f392f0ec6..765be94335 100644 --- a/drivers/builtin_openssl2/openssl/md5.h +++ b/drivers/builtin_openssl2/openssl/md5.h @@ -105,9 +105,9 @@ typedef struct MD5state_st unsigned int num; } MD5_CTX; -#ifdef OPENSSL_FIPS +//#ifdef OPENSSL_FIPS int private_MD5_Init(MD5_CTX *c); -#endif +//#endif //#define MD5_Init _SSL_MD5_Init #define MD5_Final _SSL_MD5_Final diff --git a/drivers/chibi/cp_loader_s3m.cpp b/drivers/chibi/cp_loader_s3m.cpp index c5f0830ae6..8b9871463f 100644 --- a/drivers/chibi/cp_loader_s3m.cpp +++ b/drivers/chibi/cp_loader_s3m.cpp @@ -162,7 +162,7 @@ CPLoader::Error CPLoader_S3M::load_sample(CPSample *p_sample) { p_sample->set_default_volume(def_volume); p_sample->set_name(name); - char scrs[4]; + char scrs[5]; file->get_byte_array((uint8_t*)scrs,4); scrs[4]=0; diff --git a/drivers/etc1/SCsub b/drivers/etc1/SCsub index 152dc3f4d0..251c3ffb86 100644 --- a/drivers/etc1/SCsub +++ b/drivers/etc1/SCsub @@ -6,7 +6,8 @@ etc_sources = [ "etc1/rg_etc1.cpp" ] -env.drivers_sources+=etc_sources +if (env["etc1"] != "no"): + env.drivers_sources+=etc_sources #env.add_source_files(env.drivers_sources, etc_sources) diff --git a/drivers/etc1/rg_etc1.cpp b/drivers/etc1/rg_etc1.cpp index cad9af8830..fd109f003c 100644 --- a/drivers/etc1/rg_etc1.cpp +++ b/drivers/etc1/rg_etc1.cpp @@ -24,6 +24,9 @@ namespace rg_etc1
{
+ inline long labs(long val) {
+ return val < 0 ? -val : val;
+ }
inline int intabs(int val) {
@@ -1913,7 +1916,7 @@ done: for (uint packed_c = 0; packed_c < limit; packed_c++)
{
int v = etc1_decode_value(diff, inten, selector, packed_c);
- uint err = intabs(v - color);
+ uint err = labs(v - static_cast<int>(color));
//printf("err: %d - %u = %u\n",v,color,err);
if (err < best_error)
{
@@ -2367,7 +2370,7 @@ found_perfect_match: int dr = best_results[1].m_block_color_unscaled.r - best_results[0].m_block_color_unscaled.r;
int dg = best_results[1].m_block_color_unscaled.g - best_results[0].m_block_color_unscaled.g;
int db = best_results[1].m_block_color_unscaled.b - best_results[0].m_block_color_unscaled.b;
- RG_ETC1_ASSERT(best_use_color4 || (rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax));
+ RG_ETC1_ASSERT(best_use_color4 || ((rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax)));
if (best_use_color4)
{
diff --git a/drivers/gl_context/context_gl.cpp b/drivers/gl_context/context_gl.cpp index 77a94f9333..82195cc6f6 100644 --- a/drivers/gl_context/context_gl.cpp +++ b/drivers/gl_context/context_gl.cpp @@ -12,7 +12,7 @@ #include "context_gl.h" -#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) || defined(GLES1_ENABLED) +#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) diff --git a/drivers/gl_context/context_gl.h b/drivers/gl_context/context_gl.h index 4c3d863e87..392f8341ae 100644 --- a/drivers/gl_context/context_gl.h +++ b/drivers/gl_context/context_gl.h @@ -29,7 +29,7 @@ #ifndef CONTEXT_GL_H #define CONTEXT_GL_H -#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) || defined(GLES1_ENABLED) +#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) #include "typedefs.h" diff --git a/drivers/gles1/rasterizer_gles1.cpp b/drivers/gles1/rasterizer_gles1.cpp deleted file mode 100644 index 02de063bda..0000000000 --- a/drivers/gles1/rasterizer_gles1.cpp +++ /dev/null @@ -1,5957 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles1.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 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 */ -/* "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. */ -/*************************************************************************/ -#ifdef GLES1_ENABLED - -#include "rasterizer_gles1.h" -#include "os/os.h" -#include "globals.h" -#include <stdio.h> -#include "drivers/gl_context/context_gl.h" -#include "servers/visual/shader_language.h" -#include "servers/visual/particle_system_sw.h" -#include "gl_context/context_gl.h" -#include <string.h> - -_FORCE_INLINE_ static void _gl_load_transform(const Transform& tr) { - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[1][0], - tr.basis.elements[2][0], - 0, - tr.basis.elements[0][1], - tr.basis.elements[1][1], - tr.basis.elements[2][1], - 0, - tr.basis.elements[0][2], - tr.basis.elements[1][2], - tr.basis.elements[2][2], - 0, - tr.origin.x, - tr.origin.y, - tr.origin.z, - 1 - }; - - glLoadMatrixf(matrix); -}; - - -_FORCE_INLINE_ static void _gl_mult_transform(const Transform& tr) { - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.basis.elements[0][0], - tr.basis.elements[1][0], - tr.basis.elements[2][0], - 0, - tr.basis.elements[0][1], - tr.basis.elements[1][1], - tr.basis.elements[2][1], - 0, - tr.basis.elements[0][2], - tr.basis.elements[1][2], - tr.basis.elements[2][2], - 0, - tr.origin.x, - tr.origin.y, - tr.origin.z, - 1 - }; - - glMultMatrixf(matrix); -}; - -_FORCE_INLINE_ static void _gl_mult_transform(const Matrix32& tr) { - - GLfloat matrix[16]={ /* build a 16x16 matrix */ - tr.elements[0][0], - tr.elements[0][1], - 0, - 0, - tr.elements[1][0], - tr.elements[1][1], - 0, - 0, - 0, - 0, - 1, - 0, - tr.elements[2][0], - tr.elements[2][1], - 0, - 1 - }; - - glMultMatrixf(matrix); -}; - - -RasterizerGLES1::FX::FX() { - - bgcolor_active=false; - bgcolor=Color(0,1,0,1); - - skybox_active=false; - - glow_active=false; - glow_passes=4; - glow_attenuation=0.7; - glow_bloom=0.0; - - antialias_active=true; - antialias_tolerance=15; - - ssao_active=true; - ssao_attenuation=0.7; - ssao_radius=0.18; - ssao_max_distance=1.0; - ssao_range_min=0.25; - ssao_range_max=0.48; - ssao_only=false; - - - fog_active=false; - fog_near=5; - fog_far=100; - fog_attenuation=1.0; - fog_color_near=Color(1,1,1,1); - fog_color_far=Color(1,1,1,1); - fog_bg=false; - - toon_active=false; - toon_treshold=0.4; - toon_soft=0.001; - - edge_active=false; - edge_color=Color(0,0,0,1); - edge_size=1.0; - -} - -static const GLenum prim_type[]={GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN}; - -static void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color* p_colors, const Vector3 *p_uvs,const Plane *p_tangents=NULL,int p_instanced=1) { - - ERR_FAIL_COND(!p_vertices); - ERR_FAIL_COND(p_points <1 || p_points>4); - - GLenum type = prim_type[p_points - 1]; - - - //if (!p_colors) { - // glColor4f(1, 1, 1, 1); - //}; - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)p_vertices); - - if (p_normals) { - - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, (GLvoid*)p_normals); - }; - - if (p_colors) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4,GL_FLOAT, 0, p_colors); - }; - - if (p_uvs) { - - glClientActiveTexture(GL_TEXTURE0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(3, GL_FLOAT, 0, p_uvs); - }; - - glDrawArrays( type, 0, p_points); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -}; - -/* TEXTURE API */ -#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE -#define _EXT_ETC1_RGB8_OES 0x8D64 - -/* TEXTURE API */ - -Image RasterizerGLES1::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { - - r_has_alpha_cache=false; - r_compressed=false; - Image image=p_image; - - switch(p_format) { - - case Image::FORMAT_GRAYSCALE: { - r_gl_components=1; - r_gl_format=GL_LUMINANCE; - - } break; - case Image::FORMAT_INTENSITY: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGBA); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - } break; - case Image::FORMAT_GRAYSCALE_ALPHA: { - - //image.convert(Image::FORMAT_RGBA); - r_gl_components=2; - r_gl_format=GL_LUMINANCE_ALPHA; - r_has_alpha_cache=true; - } break; - - case Image::FORMAT_INDEXED: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGB); - r_gl_components=3; - r_gl_format=GL_RGB; - - } break; - - case Image::FORMAT_INDEXED_ALPHA: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGBA); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - - } break; - case Image::FORMAT_RGB: { - - r_gl_components=3; - r_gl_format=GL_RGB; - } break; - case Image::FORMAT_RGBA: { - - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - } break; - case Image::FORMAT_BC1: { - - r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; - r_compressed=true; - - } break; - case Image::FORMAT_BC2: { - r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; - r_has_alpha_cache=true; - r_compressed=true; - - } break; - case Image::FORMAT_BC3: { - - r_gl_components=1; //doesn't matter much - r_gl_format=_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; - r_has_alpha_cache=true; - r_compressed=true; - - } break; - case Image::FORMAT_BC4: { - - r_gl_format=_EXT_COMPRESSED_RED_RGTC1; - r_gl_components=1; //doesn't matter much - r_compressed=true; - - } break; - case Image::FORMAT_BC5: { - - r_gl_format=_EXT_COMPRESSED_RG_RGTC2; - r_gl_components=1; //doesn't matter much - r_compressed=true; - } break; - case Image::FORMAT_PVRTC2: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC2"); - - } else { - - r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC2"); - } - - } break; - case Image::FORMAT_PVRTC2_ALPHA: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC2A"); - - } else { - - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC2A"); - } - - } break; - case Image::FORMAT_PVRTC4: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC4"); - } else { - - r_gl_format=_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC4"); - } - - } break; - case Image::FORMAT_PVRTC4_ALPHA: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - r_gl_components=4; - r_gl_format=GL_RGBA; - r_has_alpha_cache=true; - print_line("Load Compat PVRTC4A"); - - } else { - - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - r_gl_components=1; //doesn't matter much - r_compressed=true; - print_line("Load Normal PVRTC4A"); - } - - } break; - case Image::FORMAT_ETC: { - - if (!pvr_supported) { - - if (!image.empty()) - image.decompress(); - } else { - - r_gl_format=_EXT_ETC1_RGB8_OES; - r_gl_components=1; //doesn't matter much - r_compressed=true; - } - - } break; - case Image::FORMAT_YUV_422: - case Image::FORMAT_YUV_444: { - - if (!image.empty()) - image.convert(Image::FORMAT_RGB); - r_gl_format=GL_RGB; - r_gl_components=3; - - } break; - - default: { - - ERR_FAIL_V(Image()); - } - } - - return image; -} - - -RID RasterizerGLES1::texture_create() { - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture,RID()); - glGenTextures(1, &texture->tex_id); - texture->active=false; - texture->total_data_size=0; - - return texture_owner.make_rid( texture ); - -} - -void RasterizerGLES1::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { - - bool has_alpha_cache; - int components; - GLenum format; - bool compressed; - - int po2_width = nearest_power_of_2(p_width); - int po2_height = nearest_power_of_2(p_height); - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - texture->width=p_width; - texture->height=p_height; - texture->format=p_format; - texture->flags=p_flags; - texture->target = /*(p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP :*/ GL_TEXTURE_2D; - - bool scale_textures = (!npo2_textures_available || p_format&VS::TEXTURE_FLAG_MIPMAPS); - - - if (scale_textures) { - texture->alloc_width = po2_width; - texture->alloc_height = po2_height; - } else { - - texture->alloc_width = texture->width; - texture->alloc_height = texture->height; - }; - - _get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed); - - texture->gl_components_cache=components; - texture->gl_format_cache=format; - texture->format_has_alpha=has_alpha_cache; - texture->compressed=compressed; - texture->data_size=0; - - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - - - - if (compressed) { - - glTexParameteri( texture->target, GL_GENERATE_MIPMAP, GL_FALSE ); - } else { - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) { - glTexParameteri( texture->target, GL_GENERATE_MIPMAP, GL_TRUE ); - } else { - glTexParameteri( texture->target, GL_GENERATE_MIPMAP, GL_FALSE ); - } - - } - - - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - - if (texture->flags&VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // raw Filtering - - } - bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT) { - - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } else { - - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - } - - texture->active=true; -} - -void RasterizerGLES1::texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->format != p_image.get_format() ); - - int components; - GLenum format; - bool alpha; - bool compressed; - - if (keep_copies && !(texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && !(use_reload_hooks && texture->reloader)) { - texture->image[p_cube_side]=p_image; - } - - - Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,components,alpha,compressed); - if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) { - - img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - }; - - - GLenum blit_target = /*(texture->target == GL_TEXTURE_CUBE_MAP)?_cube_side_enum[p_cube_side]:*/GL_TEXTURE_2D; - - texture->data_size=img.get_data().size(); - DVector<uint8_t>::Read read = img.get_data().read(); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - int mipmaps=(texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1; - - int w=img.get_width(); - int h=img.get_height(); - - int tsize=0; - for(int i=0;i<mipmaps;i++) { - - int size,ofs; - img.get_mipmap_offset_and_size(i,ofs,size); - - if (texture->compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] ); - - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -// glTexImage2D(blit_target, i, format==GL_RGB?GL_RGB8:format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); - glTexImage2D(blit_target, i, format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); - //glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] ); - } - tsize+=size; - - w = MAX(1,w>>1); - h = MAX(1,h>>1); - - } - - _rinfo.texture_mem-=texture->total_data_size; - texture->total_data_size=tsize; - _rinfo.texture_mem+=texture->total_data_size; - - printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem); - - - if (mipmaps==1 && texture->flags&VS::TEXTURE_FLAG_MIPMAPS) { - glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); - - } else { - glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE ); - - } - - if (mipmaps>1) { - - //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmaps-1 ); - assumed to have all, always - } - - //texture_set_flags(p_texture,texture->flags); - - -} - -Image RasterizerGLES1::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - ERR_FAIL_COND_V(!texture->active,Image()); - - return texture->image[p_cube_side]; -#if 0 - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - ERR_FAIL_COND_V(!texture->active,Image()); - ERR_FAIL_COND_V(texture->data_size==0,Image()); - - DVector<uint8_t> data; - GLenum format,type=GL_UNSIGNED_BYTE; - Image::Format fmt; - int pixelsize=0; - int pixelshift=0; - int minw=1,minh=1; - bool compressed=false; - - fmt=texture->format; - - switch(texture->format) { - - case Image::FORMAT_GRAYSCALE: { - - format=GL_LUMINANCE; - type=GL_UNSIGNED_BYTE; - data.resize(texture->alloc_width*texture->alloc_height); - pixelsize=1; - - } break; - case Image::FORMAT_INTENSITY: { - return Image(); - } break; - case Image::FORMAT_GRAYSCALE_ALPHA: { - - format=GL_LUMINANCE_ALPHA; - type=GL_UNSIGNED_BYTE; - pixelsize=2; - - } break; - case Image::FORMAT_RGB: { - format=GL_RGB; - type=GL_UNSIGNED_BYTE; - pixelsize=3; - } break; - case Image::FORMAT_RGBA: { - - format=GL_RGBA; - type=GL_UNSIGNED_BYTE; - pixelsize=4; - } break; - case Image::FORMAT_INDEXED: { - - format=GL_RGB; - type=GL_UNSIGNED_BYTE; - fmt=Image::FORMAT_RGB; - pixelsize=3; - } break; - case Image::FORMAT_INDEXED_ALPHA: { - - format=GL_RGBA; - type=GL_UNSIGNED_BYTE; - fmt=Image::FORMAT_RGBA; - pixelsize=4; - - } break; - case Image::FORMAT_BC1: { - - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - compressed=true; - pixelshift=1; - minw=minh=4; - - } break; - case Image::FORMAT_BC2: { - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - compressed=true; - minw=minh=4; - - } break; - case Image::FORMAT_BC3: { - - pixelsize=1; //doesn't matter much - format=GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - compressed=true; - minw=minh=4; - - } break; - case Image::FORMAT_BC4: { - - format=GL_COMPRESSED_RED_RGTC1; - pixelsize=1; //doesn't matter much - compressed=true; - pixelshift=1; - minw=minh=4; - - } break; - case Image::FORMAT_BC5: { - - format=GL_COMPRESSED_RG_RGTC2; - pixelsize=1; //doesn't matter much - compressed=true; - minw=minh=4; - - } break; - - default:{} - } - - data.resize(texture->data_size); - DVector<uint8_t>::Write wb = data.write(); - - glActiveTexture(GL_TEXTURE0); - int ofs=0; - glBindTexture(texture->target,texture->tex_id); - - int w=texture->alloc_width; - int h=texture->alloc_height; - for(int i=0;i<texture->mipmaps+1;i++) { - - if (compressed) { - - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glGetCompressedTexImage(texture->target,i,&wb[ofs]); - - } else { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glGetTexImage(texture->target,i,format,type,&wb[ofs]); - } - - int size = (w*h*pixelsize)>>pixelshift; - ofs+=size; - - w=MAX(minw,w>>1); - h=MAX(minh,h>>1); - - } - - - wb=DVector<uint8_t>::Write(); - - Image img(texture->alloc_width,texture->alloc_height,texture->mipmaps,fmt,data); - - if (texture->format<Image::FORMAT_INDEXED && (texture->alloc_width!=texture->width || texture->alloc_height!=texture->height)) - img.resize(texture->width,texture->height); - - return img; -#endif -} - -void RasterizerGLES1::texture_set_flags(RID p_texture,uint32_t p_flags) { - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; - texture->flags=p_flags|cube; // can't remove a cube from being a cube - - bool force_clamp_to_edge = !(p_flags&VS::TEXTURE_FLAG_MIPMAPS) && (nearest_power_of_2(texture->alloc_height)!=texture->alloc_height || nearest_power_of_2(texture->alloc_width)!=texture->alloc_width); - - if (!force_clamp_to_edge && texture->flags&VS::TEXTURE_FLAG_REPEAT) { - - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } else { - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameterf( texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - - } - - - if (texture->flags&VS::TEXTURE_FLAG_FILTER) { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS) - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering - - } else { - - glTexParameteri(texture->target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // nearest - } -} -uint32_t RasterizerGLES1::texture_get_flags(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->flags; - -} -Image::Format RasterizerGLES1::texture_get_format(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image::FORMAT_GRAYSCALE); - - return texture->format; -} -uint32_t RasterizerGLES1::texture_get_width(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->width; -} -uint32_t RasterizerGLES1::texture_get_height(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->height; -} - -bool RasterizerGLES1::texture_has_alpha(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return false; - -} - -void RasterizerGLES1::texture_set_size_override(RID p_texture,int p_width, int p_height) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - - ERR_FAIL_COND(p_width<=0 || p_width>4096); - ERR_FAIL_COND(p_height<=0 || p_height>4096); - //real texture size is in alloc width and height - texture->width=p_width; - texture->height=p_height; - -} - -void RasterizerGLES1::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - - texture->reloader=p_owner; - texture->reloader_func=p_function; - if (use_reload_hooks && p_owner && keep_copies) { - - for(int i=0;i<6;i++) - texture->image[i]=Image(); - } - - -} - -/* SHADER API */ - -/* SHADER API */ - -RID RasterizerGLES1::shader_create(VS::ShaderMode p_mode) { - - Shader *shader = memnew( Shader ); - shader->mode=p_mode; - shader->valid=false; - shader->has_alpha=false; - shader->fragment_line=0; - shader->vertex_line=0; - shader->light_line=0; - RID rid = shader_owner.make_rid(shader); - shader_set_mode(rid,p_mode); -// _shader_make_dirty(shader); - - return rid; - -} - - - -void RasterizerGLES1::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { - - ERR_FAIL_INDEX(p_mode,3); - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); -// if (shader->custom_code_id && p_mode==shader->mode) -// return; - - shader->mode=p_mode; - -} -VS::ShaderMode RasterizerGLES1::shader_get_mode(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,VS::SHADER_MATERIAL); - return shader->mode; -} - - - -void RasterizerGLES1::shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs,int p_fragment_ofs,int p_light_ofs) { - - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - -#ifdef DEBUG_ENABLED - if (shader->vertex_code==p_vertex && shader->fragment_code==p_fragment && shader->light_code==p_light) - return; -#endif - shader->fragment_code=p_fragment; - shader->vertex_code=p_vertex; - shader->light_code=p_light; - shader->fragment_line=p_fragment_ofs; - shader->vertex_line=p_vertex_ofs; - shader->light_line=p_light_ofs; - -} - -String RasterizerGLES1::shader_get_vertex_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->vertex_code; - -} - -String RasterizerGLES1::shader_get_fragment_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->fragment_code; - -} - -String RasterizerGLES1::shader_get_light_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->light_code; - -} - -void RasterizerGLES1::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); -#if 0 - - if (shader->dirty_list.in_list()) - _update_shader(shader); // ok should be not anymore dirty - - - Map<int,StringName> order; - - - for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { - - - order[E->get().order]=E->key(); - } - - - for(Map<int,StringName>::Element *E=order.front();E;E=E->next()) { - - PropertyInfo pi; - ShaderLanguage::Uniform &u=shader->uniforms[E->get()]; - pi.name=E->get(); - switch(u.type) { - - case ShaderLanguage::TYPE_VOID: - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_FLOAT: - case ShaderLanguage::TYPE_VEC2: - case ShaderLanguage::TYPE_VEC3: - case ShaderLanguage::TYPE_MAT3: - case ShaderLanguage::TYPE_MAT4: - case ShaderLanguage::TYPE_VEC4: - pi.type=u.default_value.get_type(); - break; - case ShaderLanguage::TYPE_TEXTURE: - pi.type=Variant::_RID; - pi.hint=PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string="Texture"; - break; - case ShaderLanguage::TYPE_CUBEMAP: - pi.type=Variant::_RID; - pi.hint=PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string="Texture"; - break; - }; - - p_param_list->push_back(pi); - - } -#endif - -} - -/* COMMON MATERIAL API */ - - -RID RasterizerGLES1::material_create() { - - return material_owner.make_rid( memnew( Material ) ); -} - -void RasterizerGLES1::material_set_shader(RID p_material, RID p_shader) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->shader=p_shader; - -} - -RID RasterizerGLES1::material_get_shader(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,RID()); - return material->shader; -} - -#if 0 - -void RasterizerGLES1::_material_check_alpha(Material *p_material) { - - p_material->has_alpha=false; - Color diffuse=p_material->parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE]; - if (diffuse.a<0.98) { - - p_material->has_alpha=true; - return; - } - - if (p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE].is_valid()) { - - Texture *tex = texture_owner.get(p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE]); - if (!tex) - return; - if (tex->has_alpha) { - - p_material->has_alpha=true; - return; - } - } -} - -#endif -void RasterizerGLES1::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type()==Variant::NIL) - material->shader_params.erase(p_param); - else - material->shader_params[p_param]=p_value; -} -Variant RasterizerGLES1::material_get_param(RID p_material, const StringName& p_param) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,Variant()); - - if (material->shader_params.has(p_param)) - return material->shader_params[p_param]; - else - return Variant(); -} - - -void RasterizerGLES1::material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX); - material->flags[p_flag]=p_enabled; - -} -bool RasterizerGLES1::material_get_flag(RID p_material,VS::MaterialFlag p_flag) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,false); - ERR_FAIL_INDEX_V(p_flag,VS::MATERIAL_FLAG_MAX,false); - return material->flags[p_flag]; - - -} - -void RasterizerGLES1::material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->depth_draw_mode=p_mode; -} - -VS::MaterialDepthDrawMode RasterizerGLES1::material_get_depth_draw_mode(RID p_material) const{ - - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_DEPTH_DRAW_ALWAYS); - return material->depth_draw_mode; -} - - -void RasterizerGLES1::material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->blend_mode=p_mode; - -} -VS::MaterialBlendMode RasterizerGLES1::material_get_blend_mode(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_BLEND_MODE_ADD); - return material->blend_mode; -} - -void RasterizerGLES1::material_set_line_width(RID p_material,float p_line_width) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->line_width=p_line_width; - -} -float RasterizerGLES1::material_get_line_width(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,0); - - return material->line_width; -} - -/* FIXED MATERIAL */ - - -RID RasterizerGLES1::fixed_material_create() { - - return material_create(); -} - -void RasterizerGLES1::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_flag, 3); - m->fixed_flags[p_flag]=p_enabled; -} - -bool RasterizerGLES1::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m,false); - ERR_FAIL_INDEX_V(p_flag,VS::FIXED_MATERIAL_FLAG_MAX, false); - return m->fixed_flags[p_flag]; -} - -void RasterizerGLES1::fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX); - - m->parameters[p_parameter] = p_value; - -} - -Variant RasterizerGLES1::fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, Variant()); - ERR_FAIL_INDEX_V(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX, Variant()); - - return m->parameters[p_parameter]; -} - -void RasterizerGLES1::fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX); - - m->textures[p_parameter] = p_texture; - -} -RID RasterizerGLES1::fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, RID()); - ERR_FAIL_INDEX_V(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX, Variant()); - - return m->textures[p_parameter]; -} - - -void RasterizerGLES1::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - ERR_FAIL_INDEX(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX); - ERR_FAIL_INDEX(p_mode,4); - - m->texcoord_mode[p_parameter] = p_mode; -} - -VS::FixedMaterialTexCoordMode RasterizerGLES1::fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, VS::FIXED_MATERIAL_TEXCOORD_UV); - ERR_FAIL_INDEX_V(p_parameter, VisualServer::FIXED_MATERIAL_PARAM_MAX, VS::FIXED_MATERIAL_TEXCOORD_UV); - - return m->texcoord_mode[p_parameter]; // for now -} - -void RasterizerGLES1::fixed_material_set_uv_transform(RID p_material,const Transform& p_transform) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - - m->uv_transform = p_transform; -} - -Transform RasterizerGLES1::fixed_material_get_uv_transform(RID p_material) const { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, Transform()); - - return m->uv_transform; -} - -void RasterizerGLES1::fixed_material_set_point_size(RID p_material,float p_size) { - - Material *m=material_owner.get( p_material ); - ERR_FAIL_COND(!m); - m->point_size=p_size; - -} -float RasterizerGLES1::fixed_material_get_point_size(RID p_material) const { - - const Material *m=material_owner.get( p_material ); - ERR_FAIL_COND_V(!m, 0); - return m->point_size; -} - - -/* MESH API */ - - -RID RasterizerGLES1::mesh_create() { - - - return mesh_owner.make_rid( memnew( Mesh ) ); -} - - - -void RasterizerGLES1::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); - ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); - - uint32_t format=0; - - // validation - int index_array_len=0; - int array_len=0; - - for(int i=0;i<p_arrays.size();i++) { - - if (p_arrays[i].get_type()==Variant::NIL) - continue; - - format|=(1<<i); - - if (i==VS::ARRAY_VERTEX) { - - array_len=Vector3Array(p_arrays[i]).size(); - ERR_FAIL_COND(array_len==0); - } else if (i==VS::ARRAY_INDEX) { - - index_array_len=IntArray(p_arrays[i]).size(); - } - } - - ERR_FAIL_COND((format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory - - - Surface *surface = memnew( Surface ); - ERR_FAIL_COND( !surface ); - - bool use_VBO=true; //glGenBuffersARB!=NULL; // TODO detect if it's in there - if (format&VS::ARRAY_FORMAT_WEIGHTS || mesh->morph_target_count>0) { - - use_VBO=false; - } - - surface->packed=pack_arrays && use_VBO; - - int total_elem_size=0; - - for (int i=0;i<VS::ARRAY_MAX;i++) { - - - Surface::ArrayData&ad=surface->array[i]; - ad.size=0; - ad.ofs=0; - int elem_size=0; - int elem_count=0; - bool valid_local=true; - GLenum datatype; - bool normalize=false; - bool bind=false; - - if (!(format&(1<<i))) // no array - continue; - - - switch(i) { - - case VS::ARRAY_VERTEX: { - - if (surface->packed) { - elem_size=3*sizeof(int16_t); // vertex - datatype=GL_SHORT; - normalize=true; - - } else { - elem_size=3*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=3; - - } break; - case VS::ARRAY_NORMAL: { - - if (surface->packed) { - elem_size=3*sizeof(int8_t); // vertex - datatype=GL_BYTE; - normalize=true; - } else { - elem_size=3*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=3; - } break; - case VS::ARRAY_TANGENT: { - if (surface->packed) { - elem_size=4*sizeof(int8_t); // vertex - datatype=GL_BYTE; - normalize=true; - } else { - elem_size=4*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=4; - - } break; - case VS::ARRAY_COLOR: { - - elem_size=4*sizeof(uint8_t); /* RGBA */ - datatype=GL_UNSIGNED_BYTE; - elem_count=4; - bind=true; - normalize=true; - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - if (surface->packed) { - elem_size=2*sizeof(int16_t); // vertex - datatype=GL_SHORT; - normalize=true; - } else { - elem_size=2*sizeof(GLfloat); // vertex - datatype=GL_FLOAT; - } - bind=true; - elem_count=2; - - } break; - case VS::ARRAY_WEIGHTS: { - - elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLfloat); - elem_count=VS::ARRAY_WEIGHTS_SIZE; - valid_local=false; - datatype=GL_FLOAT; - - } break; - case VS::ARRAY_BONES: { - - elem_size=VS::ARRAY_WEIGHTS_SIZE*sizeof(GLuint); - elem_count=VS::ARRAY_WEIGHTS_SIZE; - valid_local=false; - datatype=GL_FLOAT; - - - } break; - case VS::ARRAY_INDEX: { - - if (index_array_len<=0) { - ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); - break; - } - /* determine wether using 16 or 32 bits indices */ - elem_size=2; - datatype=GL_UNSIGNED_SHORT; - -/* - if (use_VBO) { - - glGenBuffers(1,&surface->index_id); - ERR_FAIL_COND(surface->index_id==0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_len*elem_size,NULL,GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - } else { - surface->index_array_local = (uint8_t*)memalloc(index_array_len*elem_size); - }; -*/ - surface->index_array_len=index_array_len; // only way it can exist - ad.ofs=0; - ad.size=elem_size; - - - continue; - } break; - default: { - ERR_FAIL( ); - } - } - - ad.ofs=total_elem_size; - ad.size=elem_size; - ad.datatype=datatype; - ad.normalize=normalize; - ad.bind=bind; - ad.count=elem_count; - total_elem_size+=elem_size; - if (valid_local) { - surface->local_stride+=elem_size; - surface->morph_format|=(1<<i); - } - - - } - - surface->stride=total_elem_size; - surface->array_len=array_len; - surface->format=format; - surface->primitive=p_primitive; - surface->configured_format=0; - if (keep_copies) { - surface->data=p_arrays; - surface->morph_data=p_blend_shapes; - } - - uint8_t *array_ptr=NULL; - uint8_t *index_array_ptr=NULL; - DVector<uint8_t> array_pre_vbo; - DVector<uint8_t>::Write vaw; - DVector<uint8_t> index_array_pre_vbo; - DVector<uint8_t>::Write iaw; - - /* create pointers */ - if (use_VBO) { - - array_pre_vbo.resize(surface->array_len*surface->stride); - vaw = array_pre_vbo.write(); - array_ptr=vaw.ptr(); - - if (surface->index_array_len) { - - index_array_pre_vbo.resize(surface->index_array_len*surface->array[VS::ARRAY_INDEX].size); - iaw = index_array_pre_vbo.write(); - index_array_ptr=iaw.ptr(); - } - } else { - - surface->array_local = (uint8_t*)memalloc(surface->array_len*surface->stride); - array_ptr=(uint8_t*)surface->array_local; - if (surface->index_array_len) { - surface->index_array_local = (uint8_t*)memalloc(index_array_len*surface->array[VS::ARRAY_INDEX].size); - index_array_ptr=(uint8_t*)surface->index_array_local; - } - } - - - - _surface_set_arrays(surface,array_ptr,index_array_ptr,p_arrays,true); - - - /* create buffers!! */ - if (use_VBO) { - glGenBuffers(1,&surface->vertex_id); - ERR_FAIL_COND(surface->vertex_id==0); - glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - glBufferData(GL_ARRAY_BUFFER,surface->array_len*surface->stride,array_ptr,GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER,0); //unbind - if (surface->index_array_len) { - - glGenBuffers(1,&surface->index_id); - ERR_FAIL_COND(surface->index_id==0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER,index_array_len*surface->array[VS::ARRAY_INDEX].size,index_array_ptr,GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - - } - } - - mesh->surfaces.push_back(surface); - -} - -Error RasterizerGLES1::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,uint8_t *p_index_mem,const Array& p_arrays,bool p_main) { - - uint32_t stride = p_main ? p_surface->stride : p_surface->local_stride; - - for(int ai=0;ai<VS::ARRAY_MAX;ai++) { - if (ai>=p_arrays.size()) - break; - if (p_arrays[ai].get_type()==Variant::NIL) - continue; - Surface::ArrayData &a=p_surface->array[ai]; - - switch(ai) { - - - case VS::ARRAY_VERTEX: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<Vector3> array = p_arrays[ai]; - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector<Vector3>::Read read = array.read(); - const Vector3* src=read.ptr(); - - // setting vertices means regenerating the AABB - AABB aabb; - - float scale=1; - float max=0; - - - for (int i=0;i<p_surface->array_len;i++) { - - - GLfloat vector[3]={ src[i].x, src[i].y, src[i].z }; - - copymem(&p_mem[a.ofs+i*stride], vector, a.size); - - if (i==0) { - - aabb=AABB(src[i],Vector3()); - } else { - - aabb.expand_to( src[i] ); - } - } - - if (p_main) { - p_surface->aabb=aabb; - p_surface->vertex_scale=scale; - } - - - } break; - case VS::ARRAY_NORMAL: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<Vector3> array = p_arrays[ai]; - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector<Vector3>::Read read = array.read(); - const Vector3* src=read.ptr(); - - // setting vertices means regenerating the AABB - - for (int i=0;i<p_surface->array_len;i++) { - - - GLfloat vector[3]={ src[i].x, src[i].y, src[i].z }; - copymem(&p_mem[a.ofs+i*stride], vector, a.size); - - } - - - } break; - case VS::ARRAY_TANGENT: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<real_t> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len*4, ERR_INVALID_PARAMETER ); - - - DVector<real_t>::Read read = array.read(); - const real_t* src = read.ptr(); - - for (int i=0;i<p_surface->array_len;i++) { - - GLfloat xyzw[4]={ - src[i*4+0], - src[i*4+1], - src[i*4+2], - src[i*4+3] - }; - - copymem(&p_mem[a.ofs+i*stride], xyzw, a.size); - - } - - } break; - case VS::ARRAY_COLOR: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::COLOR_ARRAY, ERR_INVALID_PARAMETER ); - - - DVector<Color> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len, ERR_INVALID_PARAMETER ); - - - DVector<Color>::Read read = array.read(); - const Color* src = read.ptr(); - bool alpha=false; - - for (int i=0;i<p_surface->array_len;i++) { - - if (src[i].a<0.98) // tolerate alpha a bit, for crappy exporters - alpha=true; - - uint8_t colors[4]; - - for(int j=0;j<4;j++) { - - colors[j]=CLAMP( int((src[i][j])*255.0), 0,255 ); - } - - copymem(&p_mem[a.ofs+i*stride], colors, a.size); - - } - - if (p_main) - p_surface->has_alpha=alpha; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::VECTOR2_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<Vector2> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len , ERR_INVALID_PARAMETER); - - DVector<Vector2>::Read read = array.read(); - - const Vector2 * src=read.ptr(); - float scale=1.0; - - - for (int i=0;i<p_surface->array_len;i++) { - - GLfloat uv[2]={ src[i].x , src[i].y }; - - copymem(&p_mem[a.ofs+i*stride], uv, a.size); - - } - - if (p_main) { - - if (ai==VS::ARRAY_TEX_UV) { - - p_surface->uv_scale=scale; - } - if (ai==VS::ARRAY_TEX_UV2) { - - p_surface->uv2_scale=scale; - } - } - - } break; - case VS::ARRAY_BONES: - case VS::ARRAY_WEIGHTS: { - - - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<real_t> array = p_arrays[ai]; - - ERR_FAIL_COND_V( array.size() != p_surface->array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); - - - DVector<real_t>::Read read = array.read(); - - const real_t * src = read.ptr(); - - p_surface->max_bone=0; - - for (int i=0;i<p_surface->array_len;i++) { - - GLfloat data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j]; - if (ai==VS::ARRAY_BONES) { - - p_surface->max_bone=MAX(data[j],p_surface->max_bone); - } - } - - copymem(&p_mem[a.ofs+i*stride], data, a.size); - - - } - - } break; - case VS::ARRAY_INDEX: { - - ERR_FAIL_COND_V( p_surface->index_array_len<=0, ERR_INVALID_DATA ); - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER ); - - DVector<int> indices = p_arrays[ai]; - ERR_FAIL_COND_V( indices.size() == 0, ERR_INVALID_PARAMETER ); - ERR_FAIL_COND_V( indices.size() != p_surface->index_array_len, ERR_INVALID_PARAMETER ); - - /* determine wether using 16 or 32 bits indices */ - - DVector<int>::Read read = indices.read(); - const int *src=read.ptr(); - - for (int i=0;i<p_surface->index_array_len;i++) { - - - if (a.size==2) { - uint16_t v=src[i]; - - copymem(&p_index_mem[i*a.size], &v, a.size); - } else { - uint32_t v=src[i]; - - copymem(&p_index_mem[i*a.size], &v, a.size); - } - } - - - } break; - - - default: { ERR_FAIL_V(ERR_INVALID_PARAMETER);} - } - - p_surface->configured_format|=(1<<ai); - } - - return OK; -} - - - -void RasterizerGLES1::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { - - ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?"); - ERR_FAIL_V(); -} - -Array RasterizerGLES1::mesh_get_surface_arrays(RID p_mesh,int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->data; - - -} -Array RasterizerGLES1::mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->morph_data; - -} - - -void RasterizerGLES1::mesh_set_morph_target_count(RID p_mesh,int p_amount) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_COND( mesh->surfaces.size()!=0 ); - - mesh->morph_target_count=p_amount; - -} - -int RasterizerGLES1::mesh_get_morph_target_count(RID p_mesh) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->morph_target_count; - -} - -void RasterizerGLES1::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode) { - - ERR_FAIL_INDEX(p_mode,2); - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->morph_target_mode=p_mode; - -} - -VS::MorphTargetMode RasterizerGLES1::mesh_get_morph_target_mode(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED); - - return mesh->morph_target_mode; - -} - - - -void RasterizerGLES1::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND( !surface); - - if (surface->material_owned && surface->material.is_valid()) - free(surface->material); - - surface->material_owned=p_owned; - - surface->material=p_material; -} - -RID RasterizerGLES1::mesh_surface_get_material(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,RID()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, RID() ); - - return surface->material; -} - -int RasterizerGLES1::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - return surface->array_len; -} -int RasterizerGLES1::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - return surface->index_array_len; -} -uint32_t RasterizerGLES1::mesh_surface_get_format(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, 0 ); - - return surface->format; -} -VS::PrimitiveType RasterizerGLES1::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_POINTS); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_POINTS ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, VS::PRIMITIVE_POINTS ); - - return surface->primitive; -} - -void RasterizerGLES1::mesh_remove_surface(RID p_mesh,int p_index) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_index, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_index]; - ERR_FAIL_COND( !surface); - - if (mesh->morph_target_count) { - for(int i=0;i<mesh->morph_target_count;i++) - memfree(surface->morph_targets_local[i].array); - memfree( surface->morph_targets_local ); - } - - memdelete( mesh->surfaces[p_index] ); - mesh->surfaces.remove(p_index); - -} -int RasterizerGLES1::mesh_get_surface_count(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->surfaces.size(); -} - -AABB RasterizerGLES1::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - if (mesh->custom_aabb!=AABB()) - return mesh->custom_aabb; - - AABB aabb; - - for (int i=0;i<mesh->surfaces.size();i++) { - - if (i==0) - aabb=mesh->surfaces[i]->aabb; - else - aabb.merge_with(mesh->surfaces[i]->aabb); - } - - return aabb; -} - -void RasterizerGLES1::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->custom_aabb=p_aabb; - -} - -AABB RasterizerGLES1::mesh_get_custom_aabb(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - return mesh->custom_aabb; -} - - -/* MULTIMESH API */ - -RID RasterizerGLES1::multimesh_create() { - - return multimesh_owner.make_rid( memnew( MultiMesh )); -} - -void RasterizerGLES1::multimesh_set_instance_count(RID p_multimesh,int p_count) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->elements.clear(); // make sure to delete everything, so it "fails" in all implementations - multimesh->elements.resize(p_count); - -} -int RasterizerGLES1::multimesh_get_instance_count(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - - return multimesh->elements.size(); -} - -void RasterizerGLES1::multimesh_set_mesh(RID p_multimesh,RID p_mesh) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->mesh=p_mesh; - -} -void RasterizerGLES1::multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->aabb=p_aabb; -} -void RasterizerGLES1::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - MultiMesh::Element &e=multimesh->elements[p_index]; - - e.matrix[0]=p_transform.basis.elements[0][0]; - e.matrix[1]=p_transform.basis.elements[1][0]; - e.matrix[2]=p_transform.basis.elements[2][0]; - e.matrix[3]=0; - e.matrix[4]=p_transform.basis.elements[0][1]; - e.matrix[5]=p_transform.basis.elements[1][1]; - e.matrix[6]=p_transform.basis.elements[2][1]; - e.matrix[7]=0; - e.matrix[8]=p_transform.basis.elements[0][2]; - e.matrix[9]=p_transform.basis.elements[1][2]; - e.matrix[10]=p_transform.basis.elements[2][2]; - e.matrix[11]=0; - e.matrix[12]=p_transform.origin.x; - e.matrix[13]=p_transform.origin.y; - e.matrix[14]=p_transform.origin.z; - e.matrix[15]=1; - -} -void RasterizerGLES1::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh) - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - MultiMesh::Element &e=multimesh->elements[p_index]; - e.color[0]=CLAMP(p_color.r*255,0,255); - e.color[1]=CLAMP(p_color.g*255,0,255); - e.color[2]=CLAMP(p_color.b*255,0,255); - e.color[3]=CLAMP(p_color.a*255,0,255); - - -} - -RID RasterizerGLES1::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,RID()); - - return multimesh->mesh; -} -AABB RasterizerGLES1::multimesh_get_aabb(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,AABB()); - - return multimesh->aabb; -} - -Transform RasterizerGLES1::multimesh_instance_get_transform(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Transform()); - - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Transform()); - MultiMesh::Element &e=multimesh->elements[p_index]; - - Transform tr; - - tr.basis.elements[0][0]=e.matrix[0]; - tr.basis.elements[1][0]=e.matrix[1]; - tr.basis.elements[2][0]=e.matrix[2]; - tr.basis.elements[0][1]=e.matrix[4]; - tr.basis.elements[1][1]=e.matrix[5]; - tr.basis.elements[2][1]=e.matrix[6]; - tr.basis.elements[0][2]=e.matrix[8]; - tr.basis.elements[1][2]=e.matrix[9]; - tr.basis.elements[2][2]=e.matrix[10]; - tr.origin.x=e.matrix[12]; - tr.origin.y=e.matrix[13]; - tr.origin.z=e.matrix[14]; - - return tr; -} -Color RasterizerGLES1::multimesh_instance_get_color(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Color()); - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Color()); - MultiMesh::Element &e=multimesh->elements[p_index]; - Color c; - c.r=e.color[0]/255.0; - c.g=e.color[1]/255.0; - c.b=e.color[2]/255.0; - c.a=e.color[3]/255.0; - - return c; - -} - -void RasterizerGLES1::multimesh_set_visible_instances(RID p_multimesh,int p_visible) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->visible=p_visible; - -} - -int RasterizerGLES1::multimesh_get_visible_instances(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - return multimesh->visible; - -} - -/* IMMEDIATE API */ - - -RID RasterizerGLES1::immediate_create() { - - Immediate *im = memnew( Immediate ); - return immediate_owner.make_rid(im); - -} - -void RasterizerGLES1::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){ - - -} -void RasterizerGLES1::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ - - -} -void RasterizerGLES1::immediate_normal(RID p_immediate,const Vector3& p_normal){ - - -} -void RasterizerGLES1::immediate_tangent(RID p_immediate,const Plane& p_tangent){ - - -} -void RasterizerGLES1::immediate_color(RID p_immediate,const Color& p_color){ - - -} -void RasterizerGLES1::immediate_uv(RID p_immediate,const Vector2& tex_uv){ - - -} -void RasterizerGLES1::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ - - -} - -void RasterizerGLES1::immediate_end(RID p_immediate){ - - -} -void RasterizerGLES1::immediate_clear(RID p_immediate) { - - -} - -AABB RasterizerGLES1::immediate_get_aabb(RID p_immediate) const { - - return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); -} - -void RasterizerGLES1::immediate_set_material(RID p_immediate,RID p_material) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - im->material=p_material; -} - -RID RasterizerGLES1::immediate_get_material(RID p_immediate) const { - - const Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND_V(!im,RID()); - return im->material; - -} - - -/* PARTICLES API */ - -RID RasterizerGLES1::particles_create() { - - Particles *particles = memnew( Particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles_owner.make_rid(particles); -} - -void RasterizerGLES1::particles_set_amount(RID p_particles, int p_amount) { - - ERR_FAIL_COND(p_amount<1); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.amount=p_amount; - -} - -int RasterizerGLES1::particles_get_amount(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.amount; - -} - -void RasterizerGLES1::particles_set_emitting(RID p_particles, bool p_emitting) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.emitting=p_emitting;; - -} -bool RasterizerGLES1::particles_is_emitting(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.emitting; - -} - -void RasterizerGLES1::particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.visibility_aabb=p_visibility; - -} - -void RasterizerGLES1::particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_half_extents=p_half_extents; -} -Vector3 RasterizerGLES1::particles_get_emission_half_extents(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_half_extents; -} - -void RasterizerGLES1::particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_base_velocity=p_base_velocity; -} - -Vector3 RasterizerGLES1::particles_get_emission_base_velocity(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_base_velocity; -} - - -void RasterizerGLES1::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_points=p_points; -} - -DVector<Vector3> RasterizerGLES1::particles_get_emission_points(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,DVector<Vector3>()); - - return particles->data.emission_points; - -} - -void RasterizerGLES1::particles_set_gravity_normal(RID p_particles, const Vector3& p_normal) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.gravity_normal=p_normal; - -} -Vector3 RasterizerGLES1::particles_get_gravity_normal(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.gravity_normal; -} - - -AABB RasterizerGLES1::particles_get_visibility_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; - -} - -void RasterizerGLES1::particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value) { - - ERR_FAIL_INDEX(p_variable,VS::PARTICLE_VAR_MAX); - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_vars[p_variable]=p_value; - -} -float RasterizerGLES1::particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_vars[p_variable]; -} - -void RasterizerGLES1::particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_randomness[p_variable]=p_randomness; - -} -float RasterizerGLES1::particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_randomness[p_variable]; - -} - -void RasterizerGLES1::particles_set_color_phases(RID p_particles, int p_phases) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_phases<0 || p_phases>VS::MAX_PARTICLE_COLOR_PHASES ); - particles->data.color_phase_count=p_phases; - -} -int RasterizerGLES1::particles_get_color_phases(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phase_count; -} - - -void RasterizerGLES1::particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - if (p_pos<0.0) - p_pos=0.0; - if (p_pos>1.0) - p_pos=1.0; - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].pos=p_pos; - -} -float RasterizerGLES1::particles_get_color_phase_pos(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1.0); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phases[p_phase].pos; - -} - -void RasterizerGLES1::particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].color=p_color; - - //update alpha - particles->has_alpha=false; - for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) { - if (particles->data.color_phases[i].color.a<0.99) - particles->has_alpha=true; - } - -} - -Color RasterizerGLES1::particles_get_color_phase_color(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color()); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Color()); - return particles->data.color_phases[p_phase].color; - -} - -void RasterizerGLES1::particles_set_attractors(RID p_particles, int p_attractors) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_attractors<0 || p_attractors>VisualServer::MAX_PARTICLE_ATTRACTORS ); - particles->data.attractor_count=p_attractors; - -} -int RasterizerGLES1::particles_get_attractors(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.attractor_count; -} - -void RasterizerGLES1::particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].pos=p_pos;; -} -Vector3 RasterizerGLES1::particles_get_attractor_pos(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,Vector3()); - return particles->data.attractors[p_attractor].pos; -} - -void RasterizerGLES1::particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].force=p_force; -} - -float RasterizerGLES1::particles_get_attractor_strength(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,0); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,0); - return particles->data.attractors[p_attractor].force; -} - -void RasterizerGLES1::particles_set_material(RID p_particles, RID p_material,bool p_owned) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - if (particles->material_owned && particles->material.is_valid()) - free(particles->material); - - particles->material_owned=p_owned; - - particles->material=p_material; - -} -RID RasterizerGLES1::particles_get_material(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles->material; - -} - -void RasterizerGLES1::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.local_coordinates=p_enable; - -} - -bool RasterizerGLES1::particles_is_using_local_coordinates(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.local_coordinates; -} -bool RasterizerGLES1::particles_has_height_from_velocity(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.height_from_velocity; -} - -void RasterizerGLES1::particles_set_height_from_velocity(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.height_from_velocity=p_enable; - -} - -AABB RasterizerGLES1::particles_get_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; -} - -/* SKELETON API */ - -RID RasterizerGLES1::skeleton_create() { - - Skeleton *skeleton = memnew( Skeleton ); - ERR_FAIL_COND_V(!skeleton,RID()); - return skeleton_owner.make_rid( skeleton ); -} -void RasterizerGLES1::skeleton_resize(RID p_skeleton,int p_bones) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - if (p_bones == skeleton->bones.size()) { - return; - }; - - skeleton->bones.resize(p_bones); - -} -int RasterizerGLES1::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, -1); - return skeleton->bones.size(); -} -void RasterizerGLES1::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX( p_bone, skeleton->bones.size() ); - - skeleton->bones[p_bone] = p_transform; -} - -Transform RasterizerGLES1::skeleton_bone_get_transform(RID p_skeleton,int p_bone) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V( p_bone, skeleton->bones.size(), Transform() ); - - // something - return skeleton->bones[p_bone]; -} - - -/* LIGHT API */ - -RID RasterizerGLES1::light_create(VS::LightType p_type) { - - Light *light = memnew( Light ); - light->type=p_type; - return light_owner.make_rid(light); -} - -VS::LightType RasterizerGLES1::light_get_type(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI); - return light->type; -} - -void RasterizerGLES1::light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_type, 3 ); - light->colors[p_type]=p_color; -} -Color RasterizerGLES1::light_get_color(RID p_light,VS::LightColor p_type) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, Color()); - ERR_FAIL_INDEX_V( p_type, 3, Color() ); - return light->colors[p_type]; -} - -void RasterizerGLES1::light_set_shadow(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->shadow_enabled=p_enabled; -} - -bool RasterizerGLES1::light_has_shadow(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->shadow_enabled; -} - -void RasterizerGLES1::light_set_volumetric(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->volumetric_enabled=p_enabled; - -} -bool RasterizerGLES1::light_is_volumetric(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->volumetric_enabled; -} - -void RasterizerGLES1::light_set_projector(RID p_light,RID p_texture) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->projector=p_texture; -} -RID RasterizerGLES1::light_get_projector(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,RID()); - return light->projector; -} - -void RasterizerGLES1::light_set_var(RID p_light, VS::LightParam p_var, float p_value) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_var, VS::LIGHT_PARAM_MAX ); - - light->vars[p_var]=p_value; -} -float RasterizerGLES1::light_get_var(RID p_light, VS::LightParam p_var) const { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,0); - - ERR_FAIL_INDEX_V( p_var, VS::LIGHT_PARAM_MAX,0 ); - - return light->vars[p_var]; -} - -void RasterizerGLES1::light_set_operator(RID p_light,VS::LightOp p_op) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - - -}; - -VS::LightOp RasterizerGLES1::light_get_operator(RID p_light) const { - - return VS::LightOp(0); -}; - -void RasterizerGLES1::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { - - -} - -VS::LightOmniShadowMode RasterizerGLES1::light_omni_get_shadow_mode(RID p_light) const{ - - return VS::LightOmniShadowMode(0); -} - -void RasterizerGLES1::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { - - -} - -VS::LightDirectionalShadowMode RasterizerGLES1::light_directional_get_shadow_mode(RID p_light) const { - - return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; -} - -void RasterizerGLES1::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { - - -} - -float RasterizerGLES1::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { - - return 0; -} - - -AABB RasterizerGLES1::light_get_aabb(RID p_light) const { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,AABB()); - - switch( light->type ) { - - case VS::LIGHT_SPOT: { - - float len=light->vars[VS::LIGHT_PARAM_RADIUS]; - float size=Math::tan(Math::deg2rad(light->vars[VS::LIGHT_PARAM_SPOT_ANGLE]))*len; - return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) ); - } break; - case VS::LIGHT_OMNI: { - - float r = light->vars[VS::LIGHT_PARAM_RADIUS]; - return AABB( -Vector3(r,r,r), Vector3(r,r,r)*2 ); - } break; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - } break; - default: {} - } - - ERR_FAIL_V( AABB() ); -} - - -RID RasterizerGLES1::light_instance_create(RID p_light) { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light, RID()); - - LightInstance *light_instance = memnew( LightInstance ); - - light_instance->light=p_light; - light_instance->base=light; - light_instance->last_pass=0; - - return light_instance_owner.make_rid( light_instance ); -} -void RasterizerGLES1::light_instance_set_transform(RID p_light_instance,const Transform& p_transform) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - lighti->transform=p_transform; - -} - -bool RasterizerGLES1::light_instance_has_shadow(RID p_light_instance) const { - - return false; - - /* - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND_V(!lighti, false); - - if (!lighti->base->shadow_enabled) - return false; - - if (lighti->base->type==VS::LIGHT_DIRECTIONAL) { - if (lighti->shadow_pass!=scene_pass) - return false; - - } else { - if (lighti->shadow_pass!=frame) - return false; - }*/ - - - - //return !lighti->shadow_buffers.empty(); - -} - - -bool RasterizerGLES1::light_instance_assign_shadow(RID p_light_instance) { - - return false; - -} - - -Rasterizer::ShadowType RasterizerGLES1::light_instance_get_shadow_type(RID p_light_instance) const { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND_V(!lighti,Rasterizer::SHADOW_NONE); - - switch(lighti->base->type) { - - case VS::LIGHT_DIRECTIONAL: return SHADOW_PSM; break; - case VS::LIGHT_OMNI: return SHADOW_DUAL_PARABOLOID; break; - case VS::LIGHT_SPOT: return SHADOW_SIMPLE; break; - } - - return Rasterizer::SHADOW_NONE; -} - -Rasterizer::ShadowType RasterizerGLES1::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { - - return SHADOW_NONE; -} -void RasterizerGLES1::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - -} - -int RasterizerGLES1::light_instance_get_shadow_passes(RID p_light_instance) const { - - return 0; -} - -bool RasterizerGLES1::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { - - return false; -} - -void RasterizerGLES1::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - - ERR_FAIL_COND(lighti->base->type!=VS::LIGHT_DIRECTIONAL); - ERR_FAIL_INDEX(p_index,1); - - lighti->custom_projection=p_camera; - lighti->custom_transform=p_transform; - -} -void RasterizerGLES1::shadow_clear_near() { - - -} - -bool RasterizerGLES1::shadow_allocate_near(RID p_light) { - - return false; -} - -bool RasterizerGLES1::shadow_allocate_far(RID p_light) { - - return false; -} - -/* PARTICLES INSTANCE */ - -RID RasterizerGLES1::particles_instance_create(RID p_particles) { - - ERR_FAIL_COND_V(!particles_owner.owns(p_particles),RID()); - ParticlesInstance *particles_instance = memnew( ParticlesInstance ); - ERR_FAIL_COND_V(!particles_instance, RID() ); - particles_instance->particles=p_particles; - return particles_instance_owner.make_rid(particles_instance); -} - -void RasterizerGLES1::particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform) { - - ParticlesInstance *particles_instance=particles_instance_owner.get(p_particles_instance); - ERR_FAIL_COND(!particles_instance); - particles_instance->transform=p_transform; -} - - -/* RENDER API */ -/* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - -RID RasterizerGLES1::viewport_data_create() { - - return RID(); -} - -RID RasterizerGLES1::render_target_create(){ - - return RID(); - -} -void RasterizerGLES1::render_target_set_size(RID p_render_target, int p_width, int p_height){ - - -} -RID RasterizerGLES1::render_target_get_texture(RID p_render_target) const{ - - return RID(); - -} -bool RasterizerGLES1::render_target_renedered_in_frame(RID p_render_target){ - - return false; -} - - -void RasterizerGLES1::begin_frame() { - - - window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height ); - //print_line("begin frame - winsize: "+window_size); - - double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec - time/=1000.0; // make secs - time_delta=time-last_time; - last_time=time; - frame++; - clear_viewport(Color(1,0,0.5)); - - _rinfo.vertex_count=0; - _rinfo.object_count=0; - _rinfo.mat_change_count=0; - _rinfo.shader_change_count=0; - - -// material_shader.set_uniform_default(MaterialShaderGLES1::SCREENZ_SCALE, Math::fmod(time, 3600.0)); - /* nehe ?*/ - -// glClearColor(0,0,1,1); -// glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. -} - -void RasterizerGLES1::capture_viewport(Image* r_capture) { - - -} - - -void RasterizerGLES1::clear_viewport(const Color& p_color) { - - glScissor( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - glEnable(GL_SCISSOR_TEST); - glClearColor(p_color.r,p_color.g,p_color.b,p_color.a); - glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. - glDisable(GL_SCISSOR_TEST); - -}; - -void RasterizerGLES1::set_viewport(const VS::ViewportRect& p_viewport) { - - - - viewport=p_viewport; - //print_line("viewport: "+itos(p_viewport.x)+","+itos(p_viewport.y)+","+itos(p_viewport.width)+","+itos(p_viewport.height)); - - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); -} - -void RasterizerGLES1::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { - - -} - - -void RasterizerGLES1::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) { - - - opaque_render_list.clear(); - alpha_render_list.clear(); - light_instance_count=0; - scene_fx = NULL; // p_env.is_valid() ? fx_owner.get(p_env) : NULL; - scene_pass++; - last_light_id=0; - directional_light_count=0; - - - //set state - - glCullFace(GL_FRONT); - cull_front=true; -}; - -void RasterizerGLES1::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { - -} - -void RasterizerGLES1::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { - - camera_transform=p_world; - camera_transform_inverse=camera_transform.inverse(); - camera_projection=p_projection; - camera_plane = Plane( camera_transform.origin, camera_transform.basis.get_axis(2) ); - camera_z_near=camera_projection.get_z_near(); - camera_z_far=camera_projection.get_z_far(); - camera_projection.get_viewport_size(camera_vp_size.x,camera_vp_size.y); -} - -void RasterizerGLES1::add_light( RID p_light_instance ) { - -#define LIGHT_FADE_TRESHOLD 0.05 - - ERR_FAIL_COND( light_instance_count >= MAX_SCENE_LIGHTS ); - - LightInstance *li = light_instance_owner.get(p_light_instance); - ERR_FAIL_COND(!li); - - - /* make light hash */ - - // actually, not really a hash, but helps to sort the lights - // and avoid recompiling redudant shader versions - - - li->last_pass=scene_pass; - li->sort_key=light_instance_count; - - switch(li->base->type) { - - case VisualServer::LIGHT_DIRECTIONAL: { - - li->light_vector = camera_transform_inverse.basis.xform(li->transform.basis.get_axis(2)).normalized(); - if (directional_light_count<MAX_HW_LIGHTS) { - - directional_lights[directional_light_count++]=li; - } - - } break; - case VisualServer::LIGHT_OMNI: { - - float radius = li->base->vars[VisualServer::LIGHT_PARAM_RADIUS]; - if (radius==0) - radius=0.0001; - li->linear_att=(1/LIGHT_FADE_TRESHOLD)/radius; - li->light_vector = camera_transform_inverse.xform(li->transform.origin); - - } break; - case VisualServer::LIGHT_SPOT: { - - float radius = li->base->vars[VisualServer::LIGHT_PARAM_RADIUS]; - if (radius==0) - radius=0.0001; - li->linear_att=(1/LIGHT_FADE_TRESHOLD)/radius; - li->light_vector = camera_transform_inverse.xform(li->transform.origin); - li->spot_vector = -camera_transform_inverse.basis.xform(li->transform.basis.get_axis(2)).normalized(); - //li->sort_key|=LIGHT_SPOT_BIT; // this way, omnis go first, spots go last and less shader versions are generated - - /* - if (li->base->projector.is_valid()) { - - float far = li->base->vars[ VS::LIGHT_VAR_RADIUS ]; - ERR_FAIL_COND( far<=0 ); - float near= far/200.0; - if (near<0.05) - near=0.05; - - float angle = li->base->vars[ VS::LIGHT_VAR_SPOT_ANGLE ]; - - //CameraMatrix proj; - //proj.set_perspective( angle*2.0, 1.0, near, far ); - - //Transform modelview=Transform(camera_transform_inverse * li->transform).inverse(); - //li->projector_mtx= proj * modelview; - - }*/ - } break; - } - - light_instances[light_instance_count++]=li; - -} - -void RasterizerGLES1::_add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner) { - - Material *m=NULL; - RID m_src=p_instance->material_override.is_valid() ? p_instance->material_override : p_geometry->material; - - if (m_src) - m=material_owner.get( m_src ); - - if (!m) { - m=material_owner.get( default_material ); - } - - ERR_FAIL_COND(!m); - - - if (m->last_pass!=frame) { - - m->last_pass=frame; - } - - - LightInstance *lights[RenderList::MAX_LIGHTS]; - int light_count=0; - - RenderList *render_list=&opaque_render_list; - if (m->fixed_flags[VS::FIXED_MATERIAL_FLAG_USE_ALPHA] || m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX) { - render_list = &alpha_render_list; - }; - - if (!m->flags[VS::MATERIAL_FLAG_UNSHADED]) { - - int lis = p_instance->light_instances.size(); - - for(int i=0;i<lis;i++) { - if (light_count>=RenderList::MAX_LIGHTS) - break; - - LightInstance *li=light_instance_owner.get( p_instance->light_instances[i] ); - - if (!li || li->last_pass!=scene_pass) //lit by light not in visible scene - continue; - lights[light_count++]=li; - } - } - - RenderList::Element *e = render_list->add_element(); - - e->geometry=p_geometry; -// e->geometry_cmp=p_geometry_cmp; - e->material=m; - e->instance=p_instance; - //e->depth=camera_plane.distance_to(p_world->origin); - e->depth=camera_transform.origin.distance_to(p_instance->transform.origin); - e->owner=p_owner; - if (p_instance->skeleton.is_valid()) - e->skeleton=skeleton_owner.get(p_instance->skeleton); - else - e->skeleton=NULL; - e->mirror=p_instance->mirror; - if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) - e->mirror=!e->mirror; - - e->light_key=0; - e->light_count=0; - - - if (!shadow) { - - - if (m->flags[VS::MATERIAL_FLAG_UNSHADED]) { - - - e->light_key--; //special key for all the shadeless people - } else if (light_count) { - - for(int i=0;i<light_count;i++) { - - e->lights[i]=lights[i]->sort_key; - } - - e->light_count=light_count; - int poslight_count=light_count; - if (poslight_count>1) { - SortArray<uint16_t> light_sort; - light_sort.sort(&e->lights[0],poslight_count); //generate an equal sort key - } - } - - } - -} - - -void RasterizerGLES1::add_mesh( const RID& p_mesh, const InstanceData *p_data) { - - Mesh *mesh = mesh_owner.get(p_mesh); - ERR_FAIL_COND(!mesh); - - int ssize = mesh->surfaces.size(); - - for (int i=0;i<ssize;i++) { - - Surface *s = mesh->surfaces[i]; - _add_geometry(s,p_data,s,NULL); - } - - mesh->last_pass=frame; - -} - -void RasterizerGLES1::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){ - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (!multimesh->mesh.is_valid()) - return; - if (multimesh->elements.empty()) - return; - - Mesh *mesh = mesh_owner.get(multimesh->mesh); - ERR_FAIL_COND(!mesh); - - int surf_count = mesh->surfaces.size(); - if (multimesh->last_pass!=scene_pass) { - - multimesh->cache_surfaces.resize(surf_count); - for(int i=0;i<surf_count;i++) { - - multimesh->cache_surfaces[i].material=mesh->surfaces[i]->material; - multimesh->cache_surfaces[i].has_alpha=mesh->surfaces[i]->has_alpha; - multimesh->cache_surfaces[i].surface=mesh->surfaces[i]; - } - - multimesh->last_pass=scene_pass; - } - - for(int i=0;i<surf_count;i++) { - - _add_geometry(&multimesh->cache_surfaces[i],p_data,multimesh->cache_surfaces[i].surface,multimesh); - } - - -} - -void RasterizerGLES1::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ - - //print_line("adding particles"); - ParticlesInstance *particles_instance = particles_instance_owner.get(p_particle_instance); - ERR_FAIL_COND(!particles_instance); - Particles *p=particles_owner.get( particles_instance->particles ); - ERR_FAIL_COND(!p); - - _add_geometry(p,p_data,p,particles_instance); - -} - - -void RasterizerGLES1::_set_cull(bool p_front,bool p_reverse_cull) { - - bool front = p_front; - if (p_reverse_cull) - front=!front; - - if (front!=cull_front) { - - glCullFace(front?GL_FRONT:GL_BACK); - cull_front=front; - } -} - - -void RasterizerGLES1::_setup_fixed_material(const Geometry *p_geometry,const Material *p_material) { - - if (!shadow) { - - ///ambient @TODO offer global ambient group option - - //GLenum side = use_shaders?GL_FRONT:GL_FRONT_AND_BACK; - GLenum side = GL_FRONT_AND_BACK; - - - ///diffuse - Color diffuse_color=p_material->parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE]; - float diffuse_rgba[4]={ - diffuse_color.r, - diffuse_color.g, - diffuse_color.b, - diffuse_color.a - }; - - //color array overrides this - glColor4f( diffuse_rgba[0],diffuse_rgba[1],diffuse_rgba[2],diffuse_rgba[3]); - last_color=diffuse_color; - glMaterialfv(side,GL_AMBIENT,diffuse_rgba); - glMaterialfv(side,GL_DIFFUSE,diffuse_rgba); - //specular - - const Color specular_color=p_material->parameters[VS::FIXED_MATERIAL_PARAM_SPECULAR]; - float specular_rgba[4]={ - specular_color.r, - specular_color.g, - specular_color.b, - 1.0 - }; - - glMaterialfv(side,GL_SPECULAR,specular_rgba); - - const Color emission=p_material->parameters[VS::FIXED_MATERIAL_PARAM_EMISSION]; - - - float emission_rgba[4]={ - emission.r, - emission.g, - emission.b, - 1.0 //p_material->parameters[VS::FIXED_MATERIAL_PARAM_DETAIL_MIX] - }; - - glMaterialfv(side,GL_EMISSION,emission_rgba); - - glMaterialf(side,GL_SHININESS,p_material->parameters[VS::FIXED_MATERIAL_PARAM_SPECULAR_EXP]); - - Plane sparams=p_material->parameters[VS::FIXED_MATERIAL_PARAM_SHADE_PARAM]; - //depth test? - - - } - - - if (p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE].is_valid()) { - - Texture *texture = texture_owner.get( p_material->textures[VS::FIXED_MATERIAL_PARAM_DIFFUSE] ); - ERR_FAIL_COND(!texture); - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - } else { - - glDisable(GL_TEXTURE_2D); - } - -} - -void RasterizerGLES1::_setup_material(const Geometry *p_geometry,const Material *p_material) { - - if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) - glDisable(GL_CULL_FACE); - else { - glEnable(GL_CULL_FACE); - } - -/* if (p_material->flags[VS::MATERIAL_FLAG_WIREFRAME]) - glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - else - glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);*/ - - if (p_material->line_width > 0) - glLineWidth(p_material->line_width); - - if (!shadow) { - - - if (blend_mode!=p_material->blend_mode) { - switch(p_material->blend_mode) { - - - case VS::MATERIAL_BLEND_MODE_MIX: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - case VS::MATERIAL_BLEND_MODE_ADD: { - - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - //glBlendEquation(GL_FUNC_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - - } - blend_mode=p_material->blend_mode; - } - - if (lighting!=!p_material->flags[VS::MATERIAL_FLAG_UNSHADED]) { - if (p_material->flags[VS::MATERIAL_FLAG_UNSHADED]) { - glDisable(GL_LIGHTING); - } else { - glEnable(GL_LIGHTING); - } - lighting=!p_material->flags[VS::MATERIAL_FLAG_UNSHADED]; - } - - } - - bool current_depth_write=p_material->depth_draw_mode!=VS::MATERIAL_DEPTH_DRAW_ALWAYS; //broken - bool current_depth_test=!p_material->flags[VS::MATERIAL_FLAG_ONTOP]; - - - _setup_fixed_material(p_geometry,p_material); - - if (current_depth_write!=depth_write) { - - depth_write=current_depth_write; - glDepthMask(depth_write); - } - - if (current_depth_test!=depth_test) { - - depth_test=current_depth_test; - if (depth_test) - glEnable(GL_DEPTH_TEST); - else - glDisable(GL_DEPTH_TEST); - } -} -/* -static const MaterialShaderGLES1::Conditionals _gl_light_version[4][3]={ - {MaterialShaderGLES1::LIGHT_0_DIRECTIONAL,MaterialShaderGLES1::LIGHT_0_OMNI,MaterialShaderGLES1::LIGHT_0_SPOT}, - {MaterialShaderGLES1::LIGHT_1_DIRECTIONAL,MaterialShaderGLES1::LIGHT_1_OMNI,MaterialShaderGLES1::LIGHT_1_SPOT}, - {MaterialShaderGLES1::LIGHT_2_DIRECTIONAL,MaterialShaderGLES1::LIGHT_2_OMNI,MaterialShaderGLES1::LIGHT_2_SPOT}, - {MaterialShaderGLES1::LIGHT_3_DIRECTIONAL,MaterialShaderGLES1::LIGHT_3_OMNI,MaterialShaderGLES1::LIGHT_3_SPOT} -}; - -static const MaterialShaderGLES1::Conditionals _gl_light_shadow[4]={ - MaterialShaderGLES1::LIGHT_0_SHADOW, - MaterialShaderGLES1::LIGHT_1_SHADOW, - MaterialShaderGLES1::LIGHT_2_SHADOW, - MaterialShaderGLES1::LIGHT_3_SHADOW -}; -*/ - - -void RasterizerGLES1::_setup_light(LightInstance* p_instance, int p_idx) { - - Light* ld = p_instance->base; - -// material_shader.set_conditional(MaterialShaderGLES1::LIGHT_0_DIRECTIONAL, true); - - //material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_DIFFUSE, ld->colors[VS::LIGHT_COLOR_DIFFUSE]); - //material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_SPECULAR, ld->colors[VS::LIGHT_COLOR_SPECULAR]); - //material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_AMBIENT, ld->colors[VS::LIGHT_COLOR_AMBIENT]); - - GLenum glid = GL_LIGHT0+p_idx; - - Color diff_color = ld->colors[VS::LIGHT_COLOR_DIFFUSE]; - float emult = ld->vars[VS::LIGHT_PARAM_ENERGY]; - - if (ld->type!=VS::LIGHT_DIRECTIONAL) - emult*=4.0; - - GLfloat diffuse_sdark[4]={ - diff_color.r*emult, - diff_color.g*emult, - diff_color.b*emult, - 1.0 - }; - - glLightfv(glid , GL_DIFFUSE, diffuse_sdark); - - Color amb_color = Color(0,0,0); - GLfloat amb_stexsize[4]={ - amb_color.r, - amb_color.g, - amb_color.b, - 1.0 - }; - - glLightfv(glid , GL_AMBIENT, amb_stexsize ); - - Color spec_color = ld->colors[VS::LIGHT_COLOR_SPECULAR]; - GLfloat spec_op[4]={ - spec_color.r, - spec_color.g, - spec_color.b, - 1.0 - }; - - glLightfv(glid , GL_SPECULAR, spec_op ); - - switch(ld->type) { - - case VS::LIGHT_DIRECTIONAL: { - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glLightf(glid,GL_CONSTANT_ATTENUATION, 1); - glLightf(glid,GL_LINEAR_ATTENUATION, 0); - glLightf(glid,GL_QUADRATIC_ATTENUATION,0); // energy - - float lightdir[4]={ - p_instance->light_vector.x, - p_instance->light_vector.y, - p_instance->light_vector.z, - 0.0 - }; - - glLightfv(glid,GL_POSITION,lightdir); //at modelview - glLightf(glid,GL_SPOT_CUTOFF,180.0); - glLightf(glid,GL_SPOT_EXPONENT, 0); - - float sdir[4]={ - 0, - 0, - -1, - 0 - }; - - glLightfv(glid,GL_SPOT_DIRECTION,sdir); //at modelview - -// material_shader.set_uniform_default(MaterialShaderGLES1::LIGHT_0_DIRECTION, p_instance->light_vector); - glPopMatrix(); - - } break; - - case VS::LIGHT_OMNI: { - - - glLightf(glid,GL_SPOT_CUTOFF,180.0); - glLightf(glid,GL_SPOT_EXPONENT, 0); - - - glLightf(glid,GL_CONSTANT_ATTENUATION, 0); - glLightf(glid,GL_LINEAR_ATTENUATION, p_instance->linear_att); - glLightf(glid,GL_QUADRATIC_ATTENUATION, 0); // wut? - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - float lightpos[4]={ - p_instance->light_vector.x, - p_instance->light_vector.y, - p_instance->light_vector.z, - 1.0 - }; - - glLightfv(glid,GL_POSITION,lightpos); //at modelview - - glPopMatrix(); - - - } break; - case VS::LIGHT_SPOT: { - - glLightf(glid,GL_SPOT_CUTOFF, ld->vars[VS::LIGHT_PARAM_SPOT_ANGLE]); - glLightf(glid,GL_SPOT_EXPONENT, ld->vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]); - - - glLightf(glid,GL_CONSTANT_ATTENUATION, 0); - glLightf(glid,GL_LINEAR_ATTENUATION, p_instance->linear_att); - glLightf(glid,GL_QUADRATIC_ATTENUATION, 0); // wut? - - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - float lightpos[4]={ - p_instance->light_vector.x, - p_instance->light_vector.y, - p_instance->light_vector.z, - 1.0 - }; - - glLightfv(glid,GL_POSITION,lightpos); //at modelview - - float lightdir[4]={ - p_instance->spot_vector.x, - p_instance->spot_vector.y, - p_instance->spot_vector.z, - 1.0 - }; - - glLightfv(glid,GL_SPOT_DIRECTION,lightdir); //at modelview - - glPopMatrix(); - - - - } break; - - default: break; - } -}; - - - - - -void RasterizerGLES1::_setup_lights(const uint16_t * p_lights,int p_light_count) { - - if (shadow) - return; - - - - for (int i=directional_light_count; i<MAX_HW_LIGHTS; i++) { - - if (i<(directional_light_count+p_light_count)) { - - - glEnable(GL_LIGHT0 + i); - _setup_light(light_instances[p_lights[i]], i); - - } else { - glDisable(GL_LIGHT0 + i); - - } - } - -} - - - -static const GLenum gl_client_states[] = { - - GL_VERTEX_ARRAY, - GL_NORMAL_ARRAY, - 0, // ARRAY_TANGENT - 0,//GL_COLOR_ARRAY, - GL_TEXTURE_COORD_ARRAY, // ARRAY_TEX_UV - 0,//GL_TEXTURE_COORD_ARRAY, // ARRAY_TEX_UV2 - 0, // ARRAY_BONES - 0, // ARRAY_WEIGHTS -}; - -static const int gl_texcoord_index[VS::ARRAY_MAX-1] = { - - -1, - -1, - -1, // ARRAY_TANGENT - -1, - 0, // ARRAY_TEX_UV - -1,//1, // ARRAY_TEX_UV2 - -1, // ARRAY_BONES - -1, // ARRAY_WEIGHTS -}; - - -Error RasterizerGLES1::_setup_geometry(const Geometry *p_geometry, const Material* p_material, const Skeleton *p_skeleton,const float *p_morphs) { - - - switch(p_geometry->type) { - - case Geometry::GEOMETRY_MULTISURFACE: - case Geometry::GEOMETRY_SURFACE: { - - - - const Surface *surf=NULL; - if (p_geometry->type==Geometry::GEOMETRY_SURFACE) - surf=static_cast<const Surface*>(p_geometry); - else if (p_geometry->type==Geometry::GEOMETRY_MULTISURFACE) - surf=static_cast<const MultiMeshSurface*>(p_geometry)->surface; - - - if (surf->format != surf->configured_format) { - if (OS::get_singleton()->is_stdout_verbose()) { - - print_line("has format: "+itos(surf->format)); - print_line("configured format: "+itos(surf->configured_format)); - } - ERR_EXPLAIN("Missing arrays (not set) in surface"); - } - ERR_FAIL_COND_V( surf->format != surf->configured_format, ERR_UNCONFIGURED ); - uint8_t *base=0; - int stride=surf->stride; - bool use_VBO = (surf->array_local==0); - _setup_geometry_vinfo=surf->array_len; - - bool skeleton_valid = p_skeleton && (surf->format&VS::ARRAY_FORMAT_BONES) && (surf->format&VS::ARRAY_FORMAT_WEIGHTS) && !p_skeleton->bones.empty() && p_skeleton->bones.size() > surf->max_bone; - - - - if (!use_VBO) { - - base = surf->array_local; - glBindBuffer(GL_ARRAY_BUFFER, 0); - bool can_copy_to_local=surf->local_stride * surf->array_len <= skinned_buffer_size; - if (!can_copy_to_local) - skeleton_valid=false; - - /* compute morphs */ - - if (p_morphs && surf->morph_target_count && can_copy_to_local) { - - base = skinned_buffer; - stride=surf->local_stride; - - //copy all first - float coef=1.0; - - for(int i=0;i<surf->morph_target_count;i++) { - if (surf->mesh->morph_target_mode==VS::MORPH_MODE_NORMALIZED) - coef-=p_morphs[i]; - ERR_FAIL_COND_V( surf->morph_format != surf->morph_targets_local[i].configured_format, ERR_INVALID_DATA ); - - } - - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - int ofs = ad.ofs; - int src_stride=surf->stride; - int dst_stride=surf->local_stride; - int count = surf->array_len; - - switch(i) { - - case VS::ARRAY_VERTEX: - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: - { - - for(int k=0;k<count;k++) { - - const float *src = (const float*)&surf->array_local[ofs+k*src_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]= src[0]*coef; - dst[1]= src[1]*coef; - dst[2]= src[2]*coef; - } break; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - for(int k=0;k<count;k++) { - - const float *src = (const float*)&surf->array_local[ofs+k*src_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]= src[0]*coef; - dst[1]= src[1]*coef; - } break; - - } break; - } - } - - - for(int j=0;j<surf->morph_target_count;j++) { - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - - int ofs = ad.ofs; - int dst_stride=surf->local_stride; - int count = surf->array_len; - const uint8_t *morph=surf->morph_targets_local[j].array; - float w = p_morphs[j]; - - switch(i) { - - case VS::ARRAY_VERTEX: - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: - { - - for(int k=0;k<count;k++) { - - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]+= src_morph[0]*w; - dst[1]+= src_morph[1]*w; - dst[2]+= src_morph[2]*w; - } break; - - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - for(int k=0;k<count;k++) { - - const float *src_morph = (const float*)&morph[ofs+k*dst_stride]; - float *dst = (float*)&base[ofs+k*dst_stride]; - - dst[0]+= src_morph[0]*w; - dst[1]+= src_morph[1]*w; - } break; - - } break; - } - } - } - - } else if (skeleton_valid) { - - base = skinned_buffer; - //copy stuff and get it ready for the skeleton - - int len = surf->array_len; - int src_stride = surf->stride; - int dst_stride = surf->stride - ( surf->array[VS::ARRAY_BONES].size + surf->array[VS::ARRAY_WEIGHTS].size ); - - for(int i=0;i<len;i++) { - const uint8_t *src = &surf->array_local[i*src_stride]; - uint8_t *dst = &base[i*dst_stride]; - memcpy(dst,src,dst_stride); - } - - - stride=dst_stride; - } - - - if (skeleton_valid) { - //transform stuff - - const uint8_t *src_weights=&surf->array_local[surf->array[VS::ARRAY_WEIGHTS].ofs]; - const uint8_t *src_bones=&surf->array_local[surf->array[VS::ARRAY_BONES].ofs]; - int src_stride = surf->stride; - int count = surf->array_len; - const Transform *skeleton = &p_skeleton->bones[0]; - - for(int i=0;i<VS::ARRAY_MAX-1;i++) { - - const Surface::ArrayData& ad=surf->array[i]; - if (ad.size==0) - continue; - - int ofs = ad.ofs; - - - switch(i) { - - case VS::ARRAY_VERTEX: { - for(int k=0;k<count;k++) { - - float *ptr= (float*)&base[ofs+k*stride]; - const GLfloat* weights = reinterpret_cast<const GLfloat*>(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast<const GLfloat*>(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - - float w = weights[j]; - if (w==0) - break; - - //print_line("accum "+itos(i)+" += "+rtos(Math::ftoi(bones[j]))+" * "+skeleton[ Math::ftoi(bones[j]) ]+" * "+rtos(w)); - dst+=skeleton[ Math::fast_ftoi(bones[j]) ].xform(src) * w; - } - - ptr[0]=dst.x; - ptr[1]=dst.y; - ptr[2]=dst.z; - - } break; - - } break; - case VS::ARRAY_NORMAL: - case VS::ARRAY_TANGENT: { - for(int k=0;k<count;k++) { - - float *ptr= (float*)&base[ofs+k*stride]; - const GLfloat* weights = reinterpret_cast<const GLfloat*>(&src_weights[k*src_stride]); - const GLfloat *bones = reinterpret_cast<const GLfloat*>(&src_bones[k*src_stride]); - - Vector3 src( ptr[0], ptr[1], ptr[2] ); - Vector3 dst; - for(int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { - - float w = weights[j]; - if (w==0) - break; - - //print_line("accum "+itos(i)+" += "+rtos(Math::ftoi(bones[j]))+" * "+skeleton[ Math::ftoi(bones[j]) ]+" * "+rtos(w)); - dst+=skeleton[ Math::fast_ftoi(bones[j]) ].basis.xform(src) * w; - } - - ptr[0]=dst.x; - ptr[1]=dst.y; - ptr[2]=dst.z; - - } break; - - } break; - } - } - - } - - } else { - - glBindBuffer(GL_ARRAY_BUFFER, surf->vertex_id); - }; - - - for (int i=0;i<(VS::ARRAY_MAX-1);i++) { - - const Surface::ArrayData& ad=surf->array[i]; - -// if (!gl_texcoord_shader[i]) -// continue; - - if (ad.size==0 || i==VS::ARRAY_BONES || i==VS::ARRAY_WEIGHTS || gl_client_states[i]==0 ) { - - if (gl_texcoord_index[i] != -1) { - glClientActiveTexture(GL_TEXTURE0+gl_texcoord_index[i]); - } - - if (gl_client_states[i] != 0) - glDisableClientState(gl_client_states[i]); - - if (i == VS::ARRAY_COLOR) { - glColor4f(last_color.r,last_color.g,last_color.b,last_color.a); - }; - continue; // this one is disabled. - } - - if (gl_texcoord_index[i] != -1) { - glClientActiveTexture(GL_TEXTURE0+gl_texcoord_index[i]); - } - - glEnableClientState(gl_client_states[i]); - - switch (i) { - - case VS::ARRAY_VERTEX: { - - glVertexPointer(3,ad.datatype,stride,&base[ad.ofs]); - - } break; /* fallthrough to normal */ - case VS::ARRAY_NORMAL: { - - glNormalPointer(ad.datatype,stride,&base[ad.ofs]); - } break; - case VS::ARRAY_COLOR: { - glColorPointer(4,ad.datatype,stride,&base[ad.ofs]); - } break; - case VS::ARRAY_TEX_UV: - case VS::ARRAY_TEX_UV2: { - - glTexCoordPointer(2,ad.datatype,stride,&base[ad.ofs]); - } break; - case VS::ARRAY_TANGENT: { - - //glVertexAttribPointer(i, 4, use_VBO?GL_BYTE:GL_FLOAT, use_VBO?GL_TRUE:GL_FALSE, stride, &base[ad.ofs]); - - } break; - case VS::ARRAY_BONES: - case VS::ARRAY_WEIGHTS: { - - //do none - //glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, surf->stride, &base[ad.ofs]); - - } break; - case VS::ARRAY_INDEX: - ERR_PRINT("Bug"); - break; - }; - } - - - } break; - - default: break; - - }; - - return OK; -}; - -static const GLenum gl_primitive[]={ - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_LINE_LOOP, - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN -}; - -static const GLenum gl_poly_primitive[4]={ - GL_POINTS, - GL_LINES, - GL_TRIANGLES, - //GL_QUADS - -}; - - -void RasterizerGLES1::_render(const Geometry *p_geometry,const Material *p_material, const Skeleton* p_skeleton, const GeometryOwner *p_owner) { - - - _rinfo.object_count++; - - switch(p_geometry->type) { - - case Geometry::GEOMETRY_SURFACE: { - - Surface *s = (Surface*)p_geometry; - - _rinfo.vertex_count+=s->array_len; - - if (s->packed && s->array_local==0) { - - float sc = (1.0/32767.0)*s->vertex_scale; - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glScalef(sc,sc,sc); - if (s->format&VS::ARRAY_FORMAT_TEX_UV) { - float uvs=(1.0/32767.0)*s->uv_scale; - //glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glScalef(uvs,uvs,uvs); - } - - - } - - - if (s->index_array_len>0) { - - if (s->index_array_local) { - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT, s->index_array_local); - - } else { - // print_line("indices: "+itos(s->index_array_local) ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); - glDrawElements(gl_primitive[s->primitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT,0); - } - - - } else { - - glDrawArrays(gl_primitive[s->primitive],0,s->array_len); - - }; - - if (s->packed && s->array_local==0) { - if (s->format&VS::ARRAY_FORMAT_TEX_UV) { - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - } - glPopMatrix(); - }; - } break; - - case Geometry::GEOMETRY_MULTISURFACE: { - - Surface *s = static_cast<const MultiMeshSurface*>(p_geometry)->surface; - const MultiMesh *mm = static_cast<const MultiMesh*>(p_owner); - int element_count=mm->elements.size(); - - if (element_count==0) - return; - - const MultiMesh::Element *elements=&mm->elements[0]; - - _rinfo.vertex_count+=s->array_len*element_count; - - - if (s->index_array_len>0) { - - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); - for(int i=0;i<element_count;i++) { - //glUniformMatrix4fv(material_shader.get_uniform_location(MaterialShaderGLES1::INSTANCE_TRANSFORM), 1, false, elements[i].matrix); - glDrawElements(gl_primitive[s->primitive],s->index_array_len, (s->array_len>(1<<16))?GL_UNSIGNED_SHORT:GL_UNSIGNED_SHORT,0); - } - - - } else { - - for(int i=0;i<element_count;i++) { -// glUniformMatrix4fv(material_shader.get_uniform_location(MaterialShaderGLES1::INSTANCE_TRANSFORM), 1, false, elements[i].matrix); - glDrawArrays(gl_primitive[s->primitive],0,s->array_len); - } - - - }; - } break; - case Geometry::GEOMETRY_PARTICLES: { - - - //print_line("particulinas"); - const Particles *particles = static_cast<const Particles*>( p_geometry ); - ERR_FAIL_COND(!p_owner); - ParticlesInstance *particles_instance = (ParticlesInstance*)p_owner; - - ParticleSystemProcessSW &pp = particles_instance->particles_process; - float td = time_delta; //MIN(time_delta,1.0/10.0); - pp.process(&particles->data,particles_instance->transform,td); - ERR_EXPLAIN("A parameter in the particle system is not correct."); - ERR_FAIL_COND(!pp.valid); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - glBindBuffer(GL_ARRAY_BUFFER,0); - - - Transform camera; - if (shadow) - camera=shadow->transform; - else - camera=camera_transform; - - particle_draw_info.prepare(&particles->data,&pp,particles_instance->transform,camera); - - _rinfo.vertex_count+=4*particles->data.amount; - - { - static const Vector3 points[4]={ - Vector3(-1.0,1.0,0), - Vector3(1.0,1.0,0), - Vector3(1.0,-1.0,0), - Vector3(-1.0,-1.0,0) - }; - static const Vector3 uvs[4]={ - Vector3(0.0,0.0,0.0), - Vector3(1.0,0.0,0.0), - Vector3(1.0,1.0,0.0), - Vector3(0,1.0,0.0) - }; - static const Vector3 normals[4]={ - Vector3(0,0,1), - Vector3(0,0,1), - Vector3(0,0,1), - Vector3(0,0,1) - }; - - static const Plane tangents[4]={ - Plane(Vector3(1,0,0),0), - Plane(Vector3(1,0,0),0), - Plane(Vector3(1,0,0),0), - Plane(Vector3(1,0,0),0) - }; - - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - _gl_load_transform(camera_transform_inverse); - for(int i=0;i<particles->data.amount;i++) { - - ParticleSystemDrawInfoSW::ParticleDrawInfo &pinfo=*particle_draw_info.draw_info_order[i]; - if (!pinfo.data->active) - continue; - glPushMatrix(); - _gl_mult_transform(pinfo.transform); - - glColor4f(pinfo.color.r*last_color.r,pinfo.color.g*last_color.g,pinfo.color.b*last_color.b,pinfo.color.a*last_color.a); - _draw_primitive(4,points,normals,NULL,uvs,tangents); - glPopMatrix(); - - } - glPopMatrix(); - - } - - } break; - default: break; - }; - -}; - -void RasterizerGLES1::_setup_shader_params(const Material *p_material) { -#if 0 - int idx=0; - int tex_idx=0; - - for(Map<StringName,Variant>::Element *E=p_material->shader_cache->params.front();E;E=E->next(),idx++) { - - Variant v; // - v = E->get(); - const Map<StringName,Variant>::Element *F=p_material->shader_params.find(E->key()); - if (F) - v=F->get(); - - switch(v.get_type() ) { - case Variant::OBJECT: - case Variant::_RID: { - - RID tex=v; - if (!tex.is_valid()) - break; - - Texture *texture = texture_owner.get(tex); - if (!texture) - break; - glUniform1i( material_shader.get_custom_uniform_location(idx), tex_idx); - glActiveTexture(tex_idx); - glBindTexture(texture->target,texture->tex_id); - - } break; - case Variant::COLOR: { - - Color c=v; - material_shader.set_custom_uniform(idx,Vector3(c.r,c.g,c.b)); - } break; - default: { - - material_shader.set_custom_uniform(idx,v); - } break; - } - - } -#endif - -} - -void RasterizerGLES1::_render_list_forward(RenderList *p_render_list,bool p_reverse_cull) { - - const Material *prev_material=NULL; - uint64_t prev_light_key=0; - const Skeleton *prev_skeleton=NULL; - const Geometry *prev_geometry=NULL; - - Geometry::Type prev_geometry_type=Geometry::GEOMETRY_INVALID; - - for (int i=0;i<p_render_list->element_count;i++) { - - RenderList::Element *e = p_render_list->elements[i]; - const Material *material = e->material; - uint64_t light_key = e->light_key; - const Skeleton *skeleton = e->skeleton; - const Geometry *geometry = e->geometry; - - if (material!=prev_material || geometry->type!=prev_geometry_type) { - _setup_material(e->geometry,material); - _rinfo.mat_change_count++; - //_setup_material_overrides(e->material,NULL,material_overrides); - //_setup_material_skeleton(material,skeleton); - } else { - - if (prev_skeleton!=skeleton) { - //_setup_material_skeleton(material,skeleton); - }; - } - - - if (geometry!=prev_geometry || geometry->type!=prev_geometry_type || prev_skeleton!=skeleton) { - - _setup_geometry(geometry, material,e->skeleton,e->instance->morph_values.ptr()); - }; - - if (i==0 || light_key!=prev_light_key) - _setup_lights(e->lights,e->light_count); - - _set_cull(e->mirror,p_reverse_cull); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glPushMatrix(); - - - if (e->instance->billboard || e->instance->depth_scale) { - - Transform xf=e->instance->transform; - if (e->instance->depth_scale) { - - if (camera_projection.matrix[3][3]) { - //orthogonal matrix, try to do about the same - //with viewport size - //real_t w = Math::abs( 1.0/(2.0*(p_projection.matrix[0][0])) ); - real_t h = Math::abs( 1.0/(2.0*camera_projection.matrix[1][1]) ); - float sc = (h*2.0); //consistent with Y-fov - xf.basis.scale( Vector3(sc,sc,sc)); - } else { - //just scale by depth - real_t sc = -camera_plane.distance_to(xf.origin); - xf.basis.scale( Vector3(sc,sc,sc)); - } - } - - if (e->instance->billboard) { - - Vector3 scale = xf.basis.get_scale(); - xf.set_look_at(xf.origin,xf.origin+camera_transform.get_basis().get_axis(2),camera_transform.get_basis().get_axis(1)); - xf.basis.scale(scale); - } - _gl_mult_transform(xf); // for fixed pipeline - - } else { - _gl_mult_transform(e->instance->transform); // for fixed pipeline - } - - - - //bool changed_shader = material_shader.bind(); - //if ( changed_shader && material->shader_cache && !material->shader_cache->params.empty()) - // _setup_shader_params(material); - - _render(geometry, material, skeleton,e->owner); - - - - prev_material=material; - prev_skeleton=skeleton; - prev_geometry=geometry; - prev_light_key=e->light_key; - prev_geometry_type=geometry->type; - } - - - -}; - - - -void RasterizerGLES1::end_scene() { - - glEnable(GL_BLEND); - glDepthMask(GL_TRUE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - depth_write=true; - depth_test=true; - - if (scene_fx && scene_fx->skybox_active) { - - //skybox - } else if (scene_fx && scene_fx->bgcolor_active) { - - glClearColor(scene_fx->bgcolor.r,scene_fx->bgcolor.g,scene_fx->bgcolor.b,1.0); - - } else { - - glClearColor(0.3,0.3,0.3,1.0); - } -#ifdef GLES_OVER_GL - //glClearDepth(1.0); -#else - //glClearDepthf(1.0); -#endif - - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - if (scene_fx && scene_fx->fog_active) { - - /* - glEnable(GL_FOG); - glFogf(GL_FOG_MODE,GL_LINEAR); - glFogf(GL_FOG_DENSITY,scene_fx->fog_attenuation); - glFogf(GL_FOG_START,scene_fx->fog_near); - glFogf(GL_FOG_END,scene_fx->fog_far); - glFogfv(GL_FOG_COLOR,scene_fx->fog_color_far.components); - glLightfv(GL_LIGHT5,GL_DIFFUSE,scene_fx->fog_color_near.components); - - material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,true); - */ - } - - - - for(int i=0;i<directional_light_count;i++) { - - glEnable(GL_LIGHT0+i); - _setup_light(directional_lights[i],i); - } - - opaque_render_list.sort_mat_light(); - - //material_shader.set_uniform_camera(MaterialShaderGLES1::PROJECTION_MATRIX, camera_projection); - - /* - printf("setting projection to "); - for (int i=0; i<16; i++) { - printf("%f, ", ((float*)camera_projection.matrix)[i]); - }; - printf("\n"); - - print_line(String("setting camera to ")+camera_transform_inverse); - */ -// material_shader.set_uniform_default(MaterialShaderGLES1::CAMERA_INVERSE, camera_transform_inverse); - - //projection - //glEnable(GL_RESCALE_NORMAL); - glEnable(GL_NORMALIZE); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(&camera_projection.matrix[0][0]); - //modelview (fixedpipie) - glMatrixMode(GL_MODELVIEW); - _gl_load_transform(camera_transform_inverse); - glPushMatrix(); - - glDisable(GL_BLEND); - - blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - lighting=true; - glEnable(GL_LIGHTING); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - _render_list_forward(&opaque_render_list); - - - alpha_render_list.sort_z(); - glEnable(GL_BLEND); - - _render_list_forward(&alpha_render_list); - - glPopMatrix(); - - -// material_shader.set_conditional( MaterialShaderGLES1::USE_FOG,false); - - _debug_shadows(); -} -void RasterizerGLES1::end_shadow_map() { -#if 0 - ERR_FAIL_COND(!shadow); - ERR_FAIL_INDEX(shadow_pass,shadow->shadow_buffers.size()); - - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - - - ShadowBuffer *sb = shadow->shadow_buffers[shadow_pass]; - - ERR_FAIL_COND(!sb); - - glBindFramebuffer(GL_FRAMEBUFFER, sb->fbo); - glViewport(0, 0, sb->size, sb->size); - - glColorMask(0, 0, 0, 0); - - glEnable(GL_POLYGON_OFFSET_FILL); - //glPolygonOffset(4,8); - glPolygonOffset( 4.0f, 4096.0f); - glPolygonOffset( 8.0f, 16.0f); - - glClearDepth(1.0f); - glClear(GL_DEPTH_BUFFER_BIT); - CameraMatrix cm; - float z_near,z_far; - Transform light_transform; - - float dp_direction=0.0; - bool flip_facing=false; - - switch(shadow->base->type) { - - case VS::LIGHT_DIRECTIONAL: { - - cm = shadow->custom_projection; - light_transform=shadow->custom_transform; - z_near=cm.get_z_near(); - z_far=cm.get_z_far(); - - } break; - case VS::LIGHT_OMNI: { - - material_shader.set_conditional(MaterialShaderGLES1::USE_DUAL_PARABOLOID,true); - dp_direction = shadow_pass?1.0:0.0; - flip_facing = (shadow_pass == 1); - light_transform=shadow->transform; - z_near=0; - z_far=shadow->base->vars[ VS::LIGHT_VAR_RADIUS ]; - } break; - case VS::LIGHT_SPOT: { - - float far = shadow->base->vars[ VS::LIGHT_VAR_RADIUS ]; - ERR_FAIL_COND( far<=0 ); - float near= far/200.0; - if (near<0.05) - near=0.05; - - float angle = shadow->base->vars[ VS::LIGHT_VAR_SPOT_ANGLE ]; - - cm.set_perspective( angle*2.0, 1.0, near, far ); - shadow->projection=cm; // cache - light_transform=shadow->transform; - z_near=cm.get_z_near(); - z_far=cm.get_z_far(); - - } break; - } - - Transform light_transform_inverse = light_transform.inverse(); - - opaque_render_list.sort_mat(); - - glLightf(GL_LIGHT5,GL_LINEAR_ATTENUATION,z_near); - glLightf(GL_LIGHT5,GL_QUADRATIC_ATTENUATION,z_far); - glLightf(GL_LIGHT5,GL_CONSTANT_ATTENUATION,dp_direction); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(&cm.matrix[0][0]); - glMatrixMode(GL_MODELVIEW); - _gl_load_transform(light_transform_inverse); - glPushMatrix(); - - for(int i=0;i<4;i++) { - for(int j=0;j<3;j++) { - - material_shader.set_conditional(_gl_light_version[i][j],false); //start false by default - } - material_shader.set_conditional(_gl_light_shadow[i],false); - } - - _render_list_forward(&opaque_render_list,flip_facing); - - material_shader.set_conditional(MaterialShaderGLES1::USE_DUAL_PARABOLOID,false); - glViewport( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height ); - if (framebuffer.active) - glBindFramebufferEXT(GL_FRAMEBUFFER,framebuffer.fbo); - else - glBindFramebufferEXT(GL_FRAMEBUFFER,0); - - glDisable(GL_POLYGON_OFFSET_FILL); - - glColorMask(1, 1, 1, 1); - shadow=NULL; -#endif -} - -void RasterizerGLES1::_debug_draw_shadow(ShadowBuffer *p_buffer, const Rect2& p_rect) { - -/* - - Transform modelview; - modelview.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); - modelview.scale( Vector3( 2.0f / viewport.width, -2.0f / viewport.height, 1.0f ) ); - modelview.translate(p_rect.pos.x, p_rect.pos.y, 0); - material_shader.set_uniform_default(MaterialShaderGLES1::MODELVIEW_TRANSFORM, *e->transform); - glBindTexture(GL_TEXTURE_2D,p_buffer->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - - Vector3 coords[4]= { - Vector3(p_rect.pos.x, p_rect.pos.y, 0 ), - Vector3(p_rect.pos.x+p_rect.size.width, - p_rect.pos.y, 0 ), - Vector3(p_rect.pos.x+p_rect.size.width, - p_rect.pos.y+p_rect.size.height, 0 ), - Vector3(p_rect.pos.x, - p_rect.pos.y+p_rect.size.height, 0 ) - }; - - Vector3 texcoords[4]={ - Vector3( 0.0f,0.0f, 0), - Vector3( 1.0f,0.0f, 0), - Vector3( 1.0f, 1.0f, 0), - Vector3( 0.0f, 1.0f, 0), - }; - - _draw_primitive(4,coords,0,0,texcoords); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); -*/ -} - -void RasterizerGLES1::_debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs) { - - -// Size2 debug_size(128,128); - Size2 debug_size(512,512); - - for (int i=0;i<p_shadows.size();i++) { - - ShadowBuffer *sb=&p_shadows[i]; - - if (!sb->owner) - continue; - - if (sb->owner->base->type==VS::LIGHT_DIRECTIONAL) { - - if (sb->owner->shadow_pass!=scene_pass-1) - continue; - } else { - - if (sb->owner->shadow_pass!=frame) - continue; - } - _debug_draw_shadow(sb, Rect2( ofs, debug_size )); - ofs.x+=debug_size.x; - if ( (ofs.x+debug_size.x) > viewport.width ) { - - ofs.x=0; - ofs.y+=debug_size.y; - } - } - -} - - -void RasterizerGLES1::_debug_shadows() { - - return; -#if 0 - canvas_begin(); - glUseProgram(0); - glDisable(GL_BLEND); - Size2 ofs; - - /* - for(int i=0;i<16;i++) { - glActiveTexture(GL_TEXTURE0+i); - //glDisable(GL_TEXTURE_2D); - } - glActiveTexture(GL_TEXTURE0); - //glEnable(GL_TEXTURE_2D); - */ - - - _debug_draw_shadows_type(near_shadow_buffers,ofs); - _debug_draw_shadows_type(far_shadow_buffers,ofs); -#endif -} - -void RasterizerGLES1::end_frame() { - - /* - if (framebuffer.active) { - - canvas_begin(); //resets stuff and goes back to fixedpipe - glBindFramebuffer(GL_FRAMEBUFFER,0); - - //copy to main bufferz - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D,framebuffer.color); - glBegin(GL_QUADS); - glTexCoord2f(0,0); - glVertex2f(-1,-1); - glTexCoord2f(0,1); - glVertex2f(-1,+1); - glTexCoord2f(1,1); - glVertex2f(+1,+1); - glTexCoord2f(1,0); - glVertex2f(+1,-1); - glEnd(); - - - } - */ - - //print_line("VTX: "+itos(_rinfo.vertex_count)+" OBJ: "+itos(_rinfo.object_count)+" MAT: "+itos(_rinfo.mat_change_count)+" SHD: "+itos(_rinfo.shader_change_count)); - - OS::get_singleton()->swap_buffers(); -} - -/* CANVAS API */ - - -void RasterizerGLES1::reset_state() { - - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind - glBindBuffer(GL_ARRAY_BUFFER,0); - - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glColor4f(1,1,1,1); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); -// glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); - canvas_blend=VS::MATERIAL_BLEND_MODE_MIX; - glLineWidth(1.0); - glDisable(GL_LIGHTING); - -} - -_FORCE_INLINE_ static void _set_glcoloro(const Color& p_color,const float p_opac) { - - glColor4f(p_color.r, p_color.g, p_color.b, p_color.a*p_opac); -} - - -void RasterizerGLES1::canvas_begin() { - - - reset_state(); - canvas_opacity=1.0; - glEnable(GL_BLEND); - - -} - -void RasterizerGLES1::canvas_disable_blending() { - - glDisable(GL_BLEND); -} - -void RasterizerGLES1::canvas_set_opacity(float p_opacity) { - - canvas_opacity = p_opacity; -} - -void RasterizerGLES1::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { - - switch(p_mode) { - - case VS::MATERIAL_BLEND_MODE_MIX: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - case VS::MATERIAL_BLEND_MODE_ADD: { - - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - - } break; - case VS::MATERIAL_BLEND_MODE_SUB: { - - //glBlendEquation(GL_FUNC_SUBTRACT); - glBlendFunc(GL_SRC_ALPHA,GL_ONE); - } break; - case VS::MATERIAL_BLEND_MODE_MUL: { - //glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - } break; - - } - -} - - -void RasterizerGLES1::canvas_begin_rect(const Matrix32& p_transform) { - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glScalef(2.0 / viewport.width, -2.0 / viewport.height, 0); - glTranslatef((-(viewport.width / 2.0)), (-(viewport.height / 2.0)), 0); - _gl_mult_transform(p_transform); - - glPushMatrix(); - -} - -void RasterizerGLES1::canvas_set_clip(bool p_clip, const Rect2& p_rect) { - - if (p_clip) { - - glEnable(GL_SCISSOR_TEST); - // glScissor(viewport.x+p_rect.pos.x,viewport.y+ (viewport.height-(p_rect.pos.y+p_rect.size.height)), - //p_rect.size.width,p_rect.size.height); - //glScissor(p_rect.pos.x,(viewport.height-(p_rect.pos.y+p_rect.size.height)),p_rect.size.width,p_rect.size.height); - glScissor(viewport.x+p_rect.pos.x,viewport.y+ (window_size.y-(p_rect.pos.y+p_rect.size.height)), - p_rect.size.width,p_rect.size.height); - } else { - - glDisable(GL_SCISSOR_TEST); - } - - -} - -void RasterizerGLES1::canvas_end_rect() { - - glPopMatrix(); -} - -void RasterizerGLES1::canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width) { - - glDisable(GL_TEXTURE_2D); - _set_glcoloro( p_color,canvas_opacity ); - - Vector3 verts[2]={ - Vector3(p_from.x,p_from.y,0), - Vector3(p_to.x,p_to.y,0) - }; - Color colors[2]={ - p_color, - p_color - }; - colors[0].a*=canvas_opacity; - colors[1].a*=canvas_opacity; - glLineWidth(p_width); - _draw_primitive(2,verts,0,colors,0); - -} - -static void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_flip_h=false,bool p_flip_v=false ) { - - - Vector3 texcoords[4]= { - Vector3( p_src_region.pos.x/p_tex_size.width, - p_src_region.pos.y/p_tex_size.height, 0), - - Vector3((p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, - p_src_region.pos.y/p_tex_size.height, 0), - - Vector3( (p_src_region.pos.x+p_src_region.size.width)/p_tex_size.width, - (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height, 0), - - Vector3( p_src_region.pos.x/p_tex_size.width, - (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height, 0) - }; - - - if (p_flip_h) { - SWAP( texcoords[0], texcoords[1] ); - SWAP( texcoords[2], texcoords[3] ); - } - if (p_flip_v) { - SWAP( texcoords[1], texcoords[2] ); - SWAP( texcoords[0], texcoords[3] ); - } - - Vector3 coords[4]= { - Vector3( p_rect.pos.x, p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width, p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width, p_rect.pos.y+p_rect.size.height, 0 ), - Vector3( p_rect.pos.x,p_rect.pos.y+p_rect.size.height, 0 ) - }; - - _draw_primitive(4,coords,0,0,texcoords); -} - -static void _draw_quad(const Rect2& p_rect) { - - Vector3 coords[4]= { - Vector3( p_rect.pos.x,p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width,p_rect.pos.y, 0 ), - Vector3( p_rect.pos.x+p_rect.size.width,p_rect.pos.y+p_rect.size.height, 0 ), - Vector3( p_rect.pos.x,p_rect.pos.y+p_rect.size.height, 0 ) - }; - - _draw_primitive(4,coords,0,0,0); - -} - - -void RasterizerGLES1::canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate) { - - _set_glcoloro( p_modulate,canvas_opacity ); - - if ( p_texture.is_valid() ) { - - glEnable(GL_TEXTURE_2D); - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - - if (!(p_flags&CANVAS_RECT_REGION)) { - - Rect2 region = Rect2(0,0,texture->width,texture->height); - _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V); - - } else { - - - _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V ); - - } - } else { - - glDisable(GL_TEXTURE_2D); - _draw_quad( p_rect ); - - } - - -} -void RasterizerGLES1::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) { - - _set_glcoloro( p_modulate,canvas_opacity ); - - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - - - /* CORNERS */ - - _draw_textured_quad( // top left - Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])), - Rect2( Point2(), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // top right - Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])), - Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],0), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])), - Size2( texture->width, texture->height ) ); - - - _draw_textured_quad( // bottom left - Rect2( Point2(p_rect.pos.x,p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])), - Rect2( Point2(0,texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // bottom right - Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])), - Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])), - Size2( texture->width, texture->height ) ); - - Rect2 rect_center( p_rect.pos+Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] )); - - Rect2 src_center( Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( texture->width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], texture->height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] )); - - - _draw_textured_quad( // top - Rect2( Point2(rect_center.pos.x,p_rect.pos.y),Size2(rect_center.size.width,p_margin[MARGIN_TOP])), - Rect2( Point2(p_margin[MARGIN_LEFT],0), Size2(src_center.size.width,p_margin[MARGIN_TOP])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // bottom - Rect2( Point2(rect_center.pos.x,rect_center.pos.y+rect_center.size.height),Size2(rect_center.size.width,p_margin[MARGIN_BOTTOM])), - Rect2( Point2(p_margin[MARGIN_LEFT],src_center.pos.y+src_center.size.height), Size2(src_center.size.width,p_margin[MARGIN_BOTTOM])), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // left - Rect2( Point2(p_rect.pos.x,rect_center.pos.y),Size2(p_margin[MARGIN_LEFT],rect_center.size.height)), - Rect2( Point2(0,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT],src_center.size.height)), - Size2( texture->width, texture->height ) ); - - _draw_textured_quad( // right - Rect2( Point2(rect_center.pos.x+rect_center.size.width,rect_center.pos.y),Size2(p_margin[MARGIN_RIGHT],rect_center.size.height)), - Rect2( Point2(src_center.pos.x+src_center.size.width,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT],src_center.size.height)), - Size2( texture->width, texture->height ) ); - - if (p_draw_center) { - - _draw_textured_quad( - rect_center, - src_center, - Size2( texture->width, texture->height )); - } - -} -void RasterizerGLES1::canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) { - - ERR_FAIL_COND(p_points.size()<1); - Vector3 verts[4]; - Vector3 uvs[4]; - - _set_glcoloro( Color(1,1,1),canvas_opacity ); - - for(int i=0;i<p_points.size();i++) { - - verts[i]=Vector3(p_points[i].x,p_points[i].y,0); - } - - for(int i=0;i<p_uvs.size();i++) { - - uvs[i]=Vector3(p_uvs[i].x,p_uvs[i].y,0); - } - - if (p_texture.is_valid()) { - glEnable(GL_TEXTURE_2D); - Texture *texture = texture_owner.get( p_texture ); - if (texture) { - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - } - } - - glLineWidth(p_width); - _draw_primitive(p_points.size(),&verts[0],NULL,p_colors.size()?&p_colors[0]:NULL,p_uvs.size()?uvs:NULL); - -} - -static const int _max_draw_poly_indices = 8*1024; -static uint16_t _draw_poly_indices[_max_draw_poly_indices]; -static float _verts3[_max_draw_poly_indices]; - -void RasterizerGLES1::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { - - bool do_colors=false; - - //reset_state(); - if (p_singlecolor) { - Color m = *p_colors; - m.a*=canvas_opacity; - glColor4f(m.r, m.g, m.b, m.a); - } else if (!p_colors) { - glColor4f(1, 1, 1, canvas_opacity); - } else - do_colors=true; - - glColor4f(1, 1, 1, 1); - - Texture* texture = NULL; - if (p_texture.is_valid()) { - glEnable(GL_TEXTURE_2D); - texture = texture_owner.get( p_texture ); - if (texture) { - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D,texture->tex_id ); - } - } - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)p_vertices); - if (do_colors) { - - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4,GL_FLOAT, 0, p_colors); - - } else { - glDisableClientState(GL_COLOR_ARRAY); - } - - if (texture && p_uvs) { - - glClientActiveTexture(GL_TEXTURE0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, p_uvs); - - } else { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - - if (p_indices) { - - for (int i=0; i<p_vertex_count; i++) { - _draw_poly_indices[i] = p_indices[i]; - }; - glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, _draw_poly_indices ); - } else { - - glDrawArrays(GL_TRIANGLES,0,p_vertex_count); - } - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - -} - -void RasterizerGLES1::canvas_set_transform(const Matrix32& p_transform) { - - //restore - glPopMatrix(); - glPushMatrix(); - //set - _gl_mult_transform(p_transform); -} - -/* FX */ - -RID RasterizerGLES1::fx_create() { - - FX *fx = memnew( FX ); - ERR_FAIL_COND_V(!fx,RID()); - return fx_owner.make_rid(fx); - -} -void RasterizerGLES1::fx_get_effects(RID p_fx,List<String> *p_effects) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - p_effects->clear(); - p_effects->push_back("bgcolor"); - p_effects->push_back("skybox"); - p_effects->push_back("antialias"); - //p_effects->push_back("hdr"); - p_effects->push_back("glow"); // glow has a bloom parameter, too - p_effects->push_back("ssao"); - p_effects->push_back("fog"); - p_effects->push_back("dof_blur"); - p_effects->push_back("toon"); - p_effects->push_back("edge"); - -} -void RasterizerGLES1::fx_set_active(RID p_fx,const String& p_effect, bool p_active) { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - if (p_effect=="bgcolor") - fx->bgcolor_active=p_active; - else if (p_effect=="skybox") - fx->skybox_active=p_active; - else if (p_effect=="antialias") - fx->antialias_active=p_active; - else if (p_effect=="glow") - fx->glow_active=p_active; - else if (p_effect=="ssao") - fx->ssao_active=p_active; - else if (p_effect=="fog") - fx->fog_active=p_active; -// else if (p_effect=="dof_blur") -// fx->dof_blur_active=p_active; - else if (p_effect=="toon") - fx->toon_active=p_active; - else if (p_effect=="edge") - fx->edge_active=p_active; -} -bool RasterizerGLES1::fx_is_active(RID p_fx,const String& p_effect) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND_V(!fx,false); - - if (p_effect=="bgcolor") - return fx->bgcolor_active; - else if (p_effect=="skybox") - return fx->skybox_active; - else if (p_effect=="antialias") - return fx->antialias_active; - else if (p_effect=="glow") - return fx->glow_active; - else if (p_effect=="ssao") - return fx->ssao_active; - else if (p_effect=="fog") - return fx->fog_active; - //else if (p_effect=="dof_blur") - // return fx->dof_blur_active; - else if (p_effect=="toon") - return fx->toon_active; - else if (p_effect=="edge") - return fx->edge_active; - - return false; -} -void RasterizerGLES1::fx_get_effect_params(RID p_fx,const String& p_effect,List<PropertyInfo> *p_params) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - - if (p_effect=="bgcolor") { - - p_params->push_back( PropertyInfo( Variant::COLOR, "color" ) ); - } else if (p_effect=="skybox") { - p_params->push_back( PropertyInfo( Variant::_RID, "cubemap" ) ); - } else if (p_effect=="antialias") { - - p_params->push_back( PropertyInfo( Variant::REAL, "tolerance", PROPERTY_HINT_RANGE,"1,128,1" ) ); - - } else if (p_effect=="glow") { - - p_params->push_back( PropertyInfo( Variant::INT, "passes", PROPERTY_HINT_RANGE,"1,4,1" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "attenuation", PROPERTY_HINT_RANGE,"0.01,8.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "bloom", PROPERTY_HINT_RANGE,"-1.0,1.0,0.01" ) ); - - } else if (p_effect=="ssao") { - - p_params->push_back( PropertyInfo( Variant::REAL, "radius", PROPERTY_HINT_RANGE,"0.0,16.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "max_distance", PROPERTY_HINT_RANGE,"0.0,256.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "range_max", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "range_min", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "attenuation", PROPERTY_HINT_RANGE,"0.0,8.0,0.01" ) ); - - } else if (p_effect=="fog") { - - p_params->push_back( PropertyInfo( Variant::REAL, "begin", PROPERTY_HINT_RANGE,"0.0,8192,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "end", PROPERTY_HINT_RANGE,"0.0,8192,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "attenuation", PROPERTY_HINT_RANGE,"0.0,8.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::COLOR, "color_begin" ) ); - p_params->push_back( PropertyInfo( Variant::COLOR, "color_end" ) ); - p_params->push_back( PropertyInfo( Variant::BOOL, "fog_bg" ) ); - -// } else if (p_effect=="dof_blur") { -// return fx->dof_blur_active; - } else if (p_effect=="toon") { - p_params->push_back( PropertyInfo( Variant::REAL, "treshold", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); - p_params->push_back( PropertyInfo( Variant::REAL, "soft", PROPERTY_HINT_RANGE,"0.001,1.0,0.001" ) ); - } else if (p_effect=="edge") { - - } -} -Variant RasterizerGLES1::fx_get_effect_param(RID p_fx,const String& p_effect,const String& p_param) const { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND_V(!fx,Variant()); - - if (p_effect=="bgcolor") { - - if (p_param=="color") - return fx->bgcolor; - } else if (p_effect=="skybox") { - if (p_param=="cubemap") - return fx->skybox_cubemap; - } else if (p_effect=="antialias") { - - if (p_param=="tolerance") - return fx->antialias_tolerance; - - } else if (p_effect=="glow") { - - if (p_param=="passes") - return fx->glow_passes; - if (p_param=="attenuation") - return fx->glow_attenuation; - if (p_param=="bloom") - return fx->glow_bloom; - - } else if (p_effect=="ssao") { - - if (p_param=="attenuation") - return fx->ssao_attenuation; - if (p_param=="max_distance") - return fx->ssao_max_distance; - if (p_param=="range_max") - return fx->ssao_range_max; - if (p_param=="range_min") - return fx->ssao_range_min; - if (p_param=="radius") - return fx->ssao_radius; - - } else if (p_effect=="fog") { - - if (p_param=="begin") - return fx->fog_near; - if (p_param=="end") - return fx->fog_far; - if (p_param=="attenuation") - return fx->fog_attenuation; - if (p_param=="color_begin") - return fx->fog_color_near; - if (p_param=="color_end") - return fx->fog_color_far; - if (p_param=="fog_bg") - return fx->fog_bg; -// } else if (p_effect=="dof_blur") { -// return fx->dof_blur_active; - } else if (p_effect=="toon") { - if (p_param=="treshold") - return fx->toon_treshold; - if (p_param=="soft") - return fx->toon_soft; - - } else if (p_effect=="edge") { - - } - return Variant(); -} -void RasterizerGLES1::fx_set_effect_param(RID p_fx,const String& p_effect, const String& p_param, const Variant& p_value) { - - FX *fx = fx_owner.get(p_fx); - ERR_FAIL_COND(!fx); - - if (p_effect=="bgcolor") { - - if (p_param=="color") - fx->bgcolor=p_value; - } else if (p_effect=="skybox") { - if (p_param=="cubemap") - fx->skybox_cubemap=p_value; - - } else if (p_effect=="antialias") { - - if (p_param=="tolerance") - fx->antialias_tolerance=p_value; - - } else if (p_effect=="glow") { - - if (p_param=="passes") - fx->glow_passes=p_value; - if (p_param=="attenuation") - fx->glow_attenuation=p_value; - if (p_param=="bloom") - fx->glow_bloom=p_value; - - } else if (p_effect=="ssao") { - - if (p_param=="attenuation") - fx->ssao_attenuation=p_value; - if (p_param=="radius") - fx->ssao_radius=p_value; - if (p_param=="max_distance") - fx->ssao_max_distance=p_value; - if (p_param=="range_max") - fx->ssao_range_max=p_value; - if (p_param=="range_min") - fx->ssao_range_min=p_value; - - } else if (p_effect=="fog") { - - if (p_param=="begin") - fx->fog_near=p_value; - if (p_param=="end") - fx->fog_far=p_value; - if (p_param=="attenuation") - fx->fog_attenuation=p_value; - if (p_param=="color_begin") - fx->fog_color_near=p_value; - if (p_param=="color_end") - fx->fog_color_far=p_value; - if (p_param=="fog_bg") - fx->fog_bg=p_value; -// } else if (p_effect=="dof_blur") { -// fx->dof_blur_active=p_value; - } else if (p_effect=="toon") { - - if (p_param=="treshold") - fx->toon_treshold=p_value; - if (p_param=="soft") - fx->toon_soft=p_value; - - } else if (p_effect=="edge") { - - } - -} - -/* ENVIRONMENT */ - -RID RasterizerGLES1::environment_create() { - - Environment * env = memnew( Environment ); - return environment_owner.make_rid(env); -} - -void RasterizerGLES1::environment_set_background(RID p_env,VS::EnvironmentBG p_bg) { - - ERR_FAIL_INDEX(p_bg,VS::ENV_BG_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_mode=p_bg; -} - -VS::EnvironmentBG RasterizerGLES1::environment_get_background(RID p_env) const{ - - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,VS::ENV_BG_MAX); - return env->bg_mode; -} - -void RasterizerGLES1::environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_BG_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_param[p_param]=p_value; - -} -Variant RasterizerGLES1::environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_BG_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->bg_param[p_param]; - -} - -void RasterizerGLES1::environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled){ - - ERR_FAIL_INDEX(p_effect,VS::ENV_FX_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_enabled[p_effect]=p_enabled; -} -bool RasterizerGLES1::environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const{ - - ERR_FAIL_INDEX_V(p_effect,VS::ENV_FX_MAX,false); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,false); - return env->fx_enabled[p_effect]; - -} - -void RasterizerGLES1::environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_FX_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_param[p_param]=p_value; -} -Variant RasterizerGLES1::environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_FX_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->fx_param[p_param]; - -} - -/*MISC*/ - -bool RasterizerGLES1::is_texture(const RID& p_rid) const { - - return texture_owner.owns(p_rid); -} -bool RasterizerGLES1::is_material(const RID& p_rid) const { - - return material_owner.owns(p_rid); -} -bool RasterizerGLES1::is_mesh(const RID& p_rid) const { - - return mesh_owner.owns(p_rid); -} - -bool RasterizerGLES1::is_immediate(const RID& p_rid) const { - - return immediate_owner.owns(p_rid); -} - -bool RasterizerGLES1::is_multimesh(const RID& p_rid) const { - - return multimesh_owner.owns(p_rid); -} -bool RasterizerGLES1::is_particles(const RID &p_beam) const { - - return particles_owner.owns(p_beam); -} - -bool RasterizerGLES1::is_light(const RID& p_rid) const { - - return light_owner.owns(p_rid); -} -bool RasterizerGLES1::is_light_instance(const RID& p_rid) const { - - return light_instance_owner.owns(p_rid); -} -bool RasterizerGLES1::is_particles_instance(const RID& p_rid) const { - - return particles_instance_owner.owns(p_rid); -} -bool RasterizerGLES1::is_skeleton(const RID& p_rid) const { - - return skeleton_owner.owns(p_rid); -} -bool RasterizerGLES1::is_environment(const RID& p_rid) const { - - return environment_owner.owns(p_rid); -} -bool RasterizerGLES1::is_fx(const RID& p_rid) const { - - return fx_owner.owns(p_rid); -} -bool RasterizerGLES1::is_shader(const RID& p_rid) const { - - return false; -} - -void RasterizerGLES1::free(const RID& p_rid) { - - if (texture_owner.owns(p_rid)) { - - // delete the texture - Texture *texture = texture_owner.get(p_rid); - - glDeleteTextures( 1,&texture->tex_id ); - _rinfo.texture_mem-=texture->total_data_size; - texture_owner.free(p_rid); - memdelete(texture); - - } else if (shader_owner.owns(p_rid)) { - - // delete the texture - Shader *shader = shader_owner.get(p_rid); - - - - shader_owner.free(p_rid); - memdelete(shader); - - } else if (material_owner.owns(p_rid)) { - - Material *material = material_owner.get( p_rid ); - ERR_FAIL_COND(!material); - - material_owner.free(p_rid); - memdelete(material); - - } else if (mesh_owner.owns(p_rid)) { - - Mesh *mesh = mesh_owner.get(p_rid); - ERR_FAIL_COND(!mesh); - for (int i=0;i<mesh->surfaces.size();i++) { - - Surface *surface = mesh->surfaces[i]; - if (surface->array_local != 0) { - memfree(surface->array_local); - }; - if (surface->index_array_local != 0) { - memfree(surface->index_array_local); - }; - - if (mesh->morph_target_count>0) { - - for(int i=0;i<mesh->morph_target_count;i++) { - - memfree(surface->morph_targets_local[i].array); - } - memfree(surface->morph_targets_local); - surface->morph_targets_local=NULL; - } - - if (surface->vertex_id) - glDeleteBuffers(1,&surface->vertex_id); - if (surface->index_id) - glDeleteBuffers(1,&surface->index_id); - - memdelete( surface ); - }; - - mesh->surfaces.clear(); - - mesh_owner.free(p_rid); - memdelete(mesh); - - } else if (multimesh_owner.owns(p_rid)) { - - MultiMesh *multimesh = multimesh_owner.get(p_rid); - ERR_FAIL_COND(!multimesh); - - multimesh_owner.free(p_rid); - memdelete(multimesh); - - } else if (particles_owner.owns(p_rid)) { - - Particles *particles = particles_owner.get(p_rid); - ERR_FAIL_COND(!particles); - - particles_owner.free(p_rid); - memdelete(particles); - } else if (immediate_owner.owns(p_rid)) { - - Immediate *immediate = immediate_owner.get(p_rid); - ERR_FAIL_COND(!immediate); - - immediate_owner.free(p_rid); - memdelete(immediate); - } else if (particles_instance_owner.owns(p_rid)) { - - ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); - ERR_FAIL_COND(!particles_isntance); - - particles_instance_owner.free(p_rid); - memdelete(particles_isntance); - - } else if (skeleton_owner.owns(p_rid)) { - - Skeleton *skeleton = skeleton_owner.get( p_rid ); - ERR_FAIL_COND(!skeleton) - - skeleton_owner.free(p_rid); - memdelete(skeleton); - - } else if (light_owner.owns(p_rid)) { - - Light *light = light_owner.get( p_rid ); - ERR_FAIL_COND(!light) - - light_owner.free(p_rid); - memdelete(light); - - } else if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.get( p_rid ); - ERR_FAIL_COND(!light_instance); - light_instance->clear_shadow_buffers(); - light_instance_owner.free(p_rid); - memdelete( light_instance ); - - } else if (fx_owner.owns(p_rid)) { - - FX *fx = fx_owner.get( p_rid ); - ERR_FAIL_COND(!fx); - - fx_owner.free(p_rid); - memdelete( fx ); - - } else if (environment_owner.owns(p_rid)) { - - Environment *env = environment_owner.get( p_rid ); - ERR_FAIL_COND(!env); - - environment_owner.free(p_rid); - memdelete( env ); - }; -} - - -void RasterizerGLES1::custom_shade_model_set_shader(int p_model, RID p_shader) { - - -}; - -RID RasterizerGLES1::custom_shade_model_get_shader(int p_model) const { - - return RID(); -}; - -void RasterizerGLES1::custom_shade_model_set_name(int p_model, const String& p_name) { - -}; - -String RasterizerGLES1::custom_shade_model_get_name(int p_model) const { - - return String(); -}; - -void RasterizerGLES1::custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info) { - -}; - -void RasterizerGLES1::custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const { - -}; - - -void RasterizerGLES1::ShadowBuffer::init(int p_size) { - - -#if 0 - size=p_size; - - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &depth); - ERR_FAIL_COND(depth==0); - - /* Setup Depth Texture */ - glBindTexture(GL_TEXTURE_2D, depth); - glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, p_size, p_size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - float border_color[]={1.0f, 1.0f, 1.0f, 1.0f}; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); - - /* Create FBO */ - glGenFramebuffers(1, &fbo); - - ERR_FAIL_COND( fbo==0 ); - - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0); - glDrawBuffer(GL_FALSE); - glReadBuffer(GL_FALSE); - - /* Check FBO creation */ - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); - - ERR_FAIL_COND( status==GL_FRAMEBUFFER_UNSUPPORTED ); - - glBindFramebufferEXT(GL_FRAMEBUFFER, 0); -#endif - -} - -void RasterizerGLES1::_init_shadow_buffers() { - - int near_shadow_size=GLOBAL_DEF("rasterizer/near_shadow_size",512); - int far_shadow_size=GLOBAL_DEF("rasterizer/far_shadow_size",64); - - near_shadow_buffers.resize( GLOBAL_DEF("rasterizer/near_shadow_count",4) ); - far_shadow_buffers.resize( GLOBAL_DEF("rasterizer/far_shadow_count",16) ); - - shadow_near_far_split_size_ratio = GLOBAL_DEF("rasterizer/shadow_near_far_split_size_ratio",0.3); - - for (int i=0;i<near_shadow_buffers.size();i++) { - - near_shadow_buffers[i].init(near_shadow_size ); - } - - for (int i=0;i<far_shadow_buffers.size();i++) { - - far_shadow_buffers[i].init(far_shadow_size); - } - -} - - -void RasterizerGLES1::_update_framebuffer() { - - return; - -#if 0 - bool want_16 = GLOBAL_DEF("rasterizer/support_hdr",true); - int blur_buffer_div=GLOBAL_DEF("rasterizer/blur_buffer_div",4); - bool use_fbo = GLOBAL_DEF("rasterizer/use_fbo",true); - - - if (blur_buffer_div<1) - blur_buffer_div=2; - - - if (use_fbo==framebuffer.active && framebuffer.width==window_size.width && framebuffer.height==window_size.height && framebuffer.buff16==want_16) - return; //nuthin to change - - if (framebuffer.fbo!=0) { - - WARN_PRINT("Resizing the screen multiple times while using to FBOs may decrease performance on some hardware."); - //free the framebuffarz - glDeleteRenderbuffers(1,&framebuffer.fbo); - glDeleteTextures(1,&framebuffer.depth); - glDeleteTextures(1,&framebuffer.color); - for(int i=0;i<2;i++) { - glDeleteRenderbuffers(1,&framebuffer.blur[i].fbo); - glDeleteTextures(1,&framebuffer.blur[i].color); - - } - - framebuffer.fbo=0; - } - - framebuffer.active=use_fbo; - framebuffer.width=window_size.width; - framebuffer.height=window_size.height; - framebuffer.buff16=want_16; - - - if (!use_fbo) - return; - - - glGenFramebuffers(1, &framebuffer.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); - - print_line("generating fbo, id: "+itos(framebuffer.fbo)); - //depth - glGenTextures(1, &framebuffer.depth); - - glBindTexture(GL_TEXTURE_2D, framebuffer.depth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, framebuffer.width, framebuffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, framebuffer.depth, 0); - //color - glGenTextures(1, &framebuffer.color); - glBindTexture(GL_TEXTURE_2D, framebuffer.color); - glTexImage2D(GL_TEXTURE_2D, 0, want_16?GL_RGB16F:GL_RGBA8, framebuffer.width, framebuffer.height, 0, GL_RGBA, want_16?GL_HALF_FLOAT:GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.color, 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - - for(int i=0;i<2;i++) { - - glGenFramebuffers(1, &framebuffer.blur[i].fbo); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.blur[i].fbo); - - glGenTextures(1, &framebuffer.blur[i].color); - glBindTexture(GL_TEXTURE_2D, framebuffer.blur[i].color); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, framebuffer.width/blur_buffer_div, framebuffer.height/blur_buffer_div, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.blur[i].color, 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); -#endif -} - -void RasterizerGLES1::init() { - -#ifdef GLES_OVER_GL - glewInit(); -#endif - - - - - scene_pass=1; - if (ContextGL::get_singleton()) - ContextGL::get_singleton()->make_current(); - - - - Set<String> extensions; - Vector<String> strings = String((const char*)glGetString( GL_EXTENSIONS )).split(" ",false); - for(int i=0;i<strings.size();i++) { - - extensions.insert(strings[i]); -// print_line(strings[i]); - } - - - - GLint tmp = 0; -// glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &tmp); -// print_line("GL_MAX_VERTEX_ATTRIBS "+itos(tmp)); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - //glEnable(GL_TEXTURE_2D); - - default_material=create_default_material(); - - _init_shadow_buffers(); - - shadow=NULL; - shadow_pass=0; - - framebuffer.fbo=0; - framebuffer.width=0; - framebuffer.height=0; - framebuffer.buff16=false; - framebuffer.blur[0].fbo=false; - framebuffer.blur[1].fbo=false; - framebuffer.active=false; - - //do a single initial clear - glClearColor(0,0,0,1); - //glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - skinned_buffer_size = GLOBAL_DEF("rasterizer/skinned_buffer_size",DEFAULT_SKINNED_BUFFER_SIZE); - skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size ); - - glGenTextures(1, &white_tex); - unsigned char whitetexdata[8*8*3]; - for(int i=0;i<8*8*3;i++) { - whitetexdata[i]=255; - } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,white_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,whitetexdata); - - npo2_textures_available=false; - pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc"); - etc_supported=true; - s3tc_supported=false; - _rinfo.texture_mem=0; - - -} - -void RasterizerGLES1::finish() { - - memdelete(skinned_buffer); -} - -int RasterizerGLES1::get_render_info(VS::RenderInfo p_info) { - - switch(p_info) { - - case VS::INFO_OBJECTS_IN_FRAME: { - - return _rinfo.object_count; - } break; - case VS::INFO_VERTICES_IN_FRAME: { - - return _rinfo.vertex_count; - } break; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { - - return _rinfo.mat_change_count; - } break; - case VS::INFO_SHADER_CHANGES_IN_FRAME: { - - return _rinfo.shader_change_count; - } break; - case VS::INFO_USAGE_VIDEO_MEM_TOTAL: { - - return 0; - } break; - case VS::INFO_VIDEO_MEM_USED: { - - return get_render_info(VS::INFO_TEXTURE_MEM_USED)+get_render_info(VS::INFO_VERTEX_MEM_USED); - } break; - case VS::INFO_TEXTURE_MEM_USED: { - - _rinfo.texture_mem; - } break; - case VS::INFO_VERTEX_MEM_USED: { - - return 0; - } break; - } - - return false; -} - -bool RasterizerGLES1::needs_to_draw_next_frame() const { - - return false; -} - -void RasterizerGLES1::reload_vram() { - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glFrontFace(GL_CW); - - //do a single initial clear - glClearColor(0,0,0,1); - //glClearDepth(1.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - -/* - glGenTextures(1, &white_tex); - unsigned char whitetexdata[8*8*3]; - for(int i=0;i<8*8*3;i++) { - whitetexdata[i]=255; - } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,white_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,whitetexdata); - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D,0); - -*/ - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - - List<RID> textures; - texture_owner.get_owned_list(&textures); - keep_copies=false; - for(List<RID>::Element *E=textures.front();E;E=E->next()) { - - RID tid = E->get(); - Texture *t=texture_owner.get(tid); - ERR_CONTINUE(!t); - t->tex_id=0; - t->data_size=0; - glGenTextures(1, &t->tex_id); - t->active=false; - texture_allocate(tid,t->width,t->height,t->format,t->flags); - bool had_image=false; - for(int i=0;i<6;i++) { - if (!t->image[i].empty()) { - texture_set_data(tid,t->image[i],VS::CubeMapSide(i)); - had_image=true; - } - } - - if (!had_image && t->reloader) { - Object *rl = ObjectDB::get_instance(t->reloader); - if (rl) - rl->call(t->reloader_func,tid); - } - } - - keep_copies=true; - - -} - -bool RasterizerGLES1::has_feature(VS::Features p_feature) const { - - switch( p_feature) { - case VS::FEATURE_SHADERS: return false; - case VS::FEATURE_NEEDS_RELOAD_HOOK: return use_reload_hooks; - default: return false; - - } - -} - - -RasterizerGLES1::RasterizerGLES1(bool p_keep_copies,bool p_use_reload_hooks) { - keep_copies=p_keep_copies; - pack_arrays=false; - use_reload_hooks=p_use_reload_hooks; - - frame = 0; -}; - -RasterizerGLES1::~RasterizerGLES1() { - -}; - - -#endif diff --git a/drivers/gles1/rasterizer_gles1.h b/drivers/gles1/rasterizer_gles1.h deleted file mode 100644 index cca953eed0..0000000000 --- a/drivers/gles1/rasterizer_gles1.h +++ /dev/null @@ -1,1242 +0,0 @@ -/*************************************************************************/ -/* rasterizer_gles1.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 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 */ -/* "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 RASTERIZER_GLES1_H -#define RASTERIZER_GLES1_H - -#include "servers/visual/rasterizer.h" - -#ifdef GLES1_ENABLED - -#include "image.h" -#include "rid.h" -#include "servers/visual_server.h" -#include "list.h" -#include "map.h" -#include "camera_matrix.h" -#include "sort.h" - -#include "platform_config.h" -#ifndef GLES1_INCLUDE_H -#include <GLES/gl.h> -#else -#include GLES1_INCLUDE_H -#endif - - - -#include "servers/visual/particle_system_sw.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class RasterizerGLES1 : public Rasterizer { - - enum { - - MAX_SCENE_LIGHTS=2048, - LIGHT_SPOT_BIT=0x80, - DEFAULT_SKINNED_BUFFER_SIZE = 1024 * 1024, // 10k vertices - MAX_HW_LIGHTS = 1, - }; - - - uint8_t *skinned_buffer; - int skinned_buffer_size; - bool pvr_supported; - bool s3tc_supported; - bool etc_supported; - bool npo2_textures_available; - bool pack_arrays; - bool use_reload_hooks; - - Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed); - - - struct Texture { - - uint32_t flags; - int width,height; - int alloc_width, alloc_height; - Image::Format format; - - GLenum target; - GLenum gl_format_cache; - int gl_components_cache; - int data_size; //original data size, useful for retrieving back - bool format_has_alpha; - bool compressed; - bool disallow_mipmaps; - int total_data_size; - - Image image[6]; - - bool active; - GLuint tex_id; - - ObjectID reloader; - StringName reloader_func; - - Texture() { - - flags=width=height=0; - tex_id=0; - data_size=0; - format=Image::FORMAT_GRAYSCALE; - gl_components_cache=0; - format_has_alpha=false; - active=false; - disallow_mipmaps=false; -// gen_mipmap=true; - compressed=false; - total_data_size=0; - } - - ~Texture() { - - if (tex_id!=0) { - - glDeleteTextures(1,&tex_id); - } - } - }; - - mutable RID_Owner<Texture> texture_owner; - - struct Shader { - - String vertex_code; - String fragment_code; - String light_code; - VS::ShaderMode mode; - Map<StringName,Variant> params; - int fragment_line; - int vertex_line; - int light_line; - bool valid; - bool has_alpha; - bool use_world_transform; - - }; - - mutable RID_Owner<Shader> shader_owner; - - - struct Material { - - bool fixed_flags[VS::FIXED_MATERIAL_FLAG_MAX]; - bool flags[VS::MATERIAL_FLAG_MAX]; - Variant parameters[VisualServer::FIXED_MATERIAL_PARAM_MAX]; - RID textures[VisualServer::FIXED_MATERIAL_PARAM_MAX]; - - VS::MaterialDepthDrawMode depth_draw_mode; - - Transform uv_transform; - VS::FixedMaterialTexCoordMode texcoord_mode[VisualServer::FIXED_MATERIAL_PARAM_MAX]; - - VS::MaterialBlendMode blend_mode; - - float line_width; - float point_size; - bool has_alpha; - - RID shader; // shader material - uint64_t last_pass; - - Map<StringName,Variant> shader_params; - - - Material() { - - - for(int i=0;i<VS::FIXED_MATERIAL_FLAG_MAX;i++) - flags[i]=false; - - for(int i=0;i<VS::MATERIAL_FLAG_MAX;i++) - flags[i]=false; - flags[VS::MATERIAL_FLAG_VISIBLE]=true; - - parameters[VS::FIXED_MATERIAL_PARAM_DIFFUSE] = Color(0.8, 0.8, 0.8); - parameters[VS::FIXED_MATERIAL_PARAM_SPECULAR_EXP] = 12; - - for (int i=0; i<VisualServer::FIXED_MATERIAL_PARAM_MAX; i++) { - texcoord_mode[i] = VS::FIXED_MATERIAL_TEXCOORD_UV; - }; - depth_draw_mode=VS::MATERIAL_DEPTH_DRAW_OPAQUE_ONLY; - line_width=1; - has_alpha=false; - blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - last_pass = 0; - point_size = 1.0; - - } - }; - mutable RID_Owner<Material> material_owner; - - void _material_check_alpha(Material *p_material); - - - struct Geometry { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_POLY, - GEOMETRY_PARTICLES, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - bool has_alpha; - bool material_owned; - - Geometry() { has_alpha=false; material_owned = false; } - virtual ~Geometry() {}; - }; - - struct GeometryOwner { - - virtual ~GeometryOwner() {} - }; - - class Mesh; - - struct Surface : public Geometry { - - struct ArrayData { - - uint32_t ofs,size,datatype,count; - bool normalize; - bool bind; - - ArrayData() { ofs=0; size=0; count=0; datatype=0; normalize=0; bind=false;} - }; - - Mesh *mesh; - - Array data; - Array morph_data; - ArrayData array[VS::ARRAY_MAX]; - // support for vertex array objects - GLuint array_object_id; - // support for vertex buffer object - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - // no support for the above, array in localmem. - uint8_t *array_local; - uint8_t *index_array_local; - - bool packed; - - struct MorphTarget { - uint32_t configured_format; - uint8_t *array; - }; - - MorphTarget* morph_targets_local; - int morph_target_count; - AABB aabb; - - int array_len; - int index_array_len; - int max_bone; - - float vertex_scale; - float uv_scale; - float uv2_scale; - - VS::PrimitiveType primitive; - - uint32_t format; - uint32_t configured_format; - - int stride; - int local_stride; - uint32_t morph_format; - - bool active; - - Point2 uv_min; - Point2 uv_max; - - Surface() { - - - array_len=0; - local_stride=0; - morph_format=0; - type=GEOMETRY_SURFACE; - primitive=VS::PRIMITIVE_POINTS; - index_array_len=0; - vertex_scale=1.0; - uv_scale=1.0; - uv2_scale=1.0; - - format=0; - stride=0; - morph_targets_local=0; - morph_target_count=0; - - array_local = index_array_local = 0; - vertex_id = index_id = 0; - - active=false; - packed=false; - } - - ~Surface() { - - } - }; - - - struct Mesh { - - bool active; - Vector<Surface*> surfaces; - int morph_target_count; - VS::MorphTargetMode morph_target_mode; - AABB custom_aabb; - - mutable uint64_t last_pass; - Mesh() { - morph_target_mode=VS::MORPH_MODE_NORMALIZED; - morph_target_count=0; - last_pass=0; - active=false; - } - }; - mutable RID_Owner<Mesh> mesh_owner; - - Error _surface_set_arrays(Surface *p_surface, uint8_t *p_mem,uint8_t *p_index_mem,const Array& p_arrays,bool p_main); - - struct MultiMesh; - - struct MultiMeshSurface : public Geometry { - - Surface *surface; - MultiMeshSurface() { type=GEOMETRY_MULTISURFACE; } - }; - - struct MultiMesh : public GeometryOwner { - - struct Element { - - float matrix[16]; - uint8_t color[4]; - }; - - AABB aabb; - RID mesh; - int visible; - - //IDirect3DVertexBuffer9* instance_buffer; - Vector<Element> elements; - Vector<MultiMeshSurface> cache_surfaces; - mutable uint64_t last_pass; - - MultiMesh() { - - last_pass=0; - visible = -1; - } - }; - - mutable RID_Owner<MultiMesh> multimesh_owner; - - - struct Immediate { - - RID material; - int empty; - }; - - mutable RID_Owner<Immediate> immediate_owner; - - struct Particles : public Geometry { - - ParticleSystemSW data; // software particle system - - Particles() { - type=GEOMETRY_PARTICLES; - - } - }; - - mutable RID_Owner<Particles> particles_owner; - - struct ParticlesInstance : public GeometryOwner { - - RID particles; - - ParticleSystemProcessSW particles_process; - Transform transform; - - ParticlesInstance() { } - }; - - mutable RID_Owner<ParticlesInstance> particles_instance_owner; - ParticleSystemDrawInfoSW particle_draw_info; - - struct Skeleton { - - Vector<Transform> bones; - - }; - - mutable RID_Owner<Skeleton> skeleton_owner; - - - struct Light { - - VS::LightType type; - float vars[VS::LIGHT_PARAM_MAX]; - Color colors[3]; - bool shadow_enabled; - RID projector; - bool volumetric_enabled; - Color volumetric_color; - - - Light() { - - vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]=1; - vars[VS::LIGHT_PARAM_SPOT_ANGLE]=45; - vars[VS::LIGHT_PARAM_ATTENUATION]=1.0; - vars[VS::LIGHT_PARAM_ENERGY]=1.0; - vars[VS::LIGHT_PARAM_RADIUS]=1.0; - vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.05; - - colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1); - colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1); - shadow_enabled=false; - volumetric_enabled=false; - } - }; - - - struct Environment { - - - VS::EnvironmentBG bg_mode; - Variant bg_param[VS::ENV_BG_PARAM_MAX]; - bool fx_enabled[VS::ENV_FX_MAX]; - Variant fx_param[VS::ENV_FX_PARAM_MAX]; - - Environment() { - - bg_mode=VS::ENV_BG_DEFAULT_COLOR; - bg_param[VS::ENV_BG_PARAM_COLOR]=Color(0,0,0); - bg_param[VS::ENV_BG_PARAM_TEXTURE]=RID(); - bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID(); - bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; - - for(int i=0;i<VS::ENV_FX_MAX;i++) - fx_enabled[i]=false; - - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_RANGE]=10.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_WHITE]=1.0; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_TRESHOLD]=0.95; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE]=0.2; - fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE]=8.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED]=0.5; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]=1.0; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_BG]=true; - fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0; - - } - - }; - - mutable RID_Owner<Environment> environment_owner; - - struct ShadowBuffer; - - struct LightInstance { - - struct SplitInfo { - - CameraMatrix camera; - Transform transform; - float near; - float far; - }; - - RID light; - Light *base; - Transform transform; - CameraMatrix projection; - - Transform custom_transform; - CameraMatrix custom_projection; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - uint64_t shadow_pass; - uint64_t last_pass; - uint16_t sort_key; - - Vector<ShadowBuffer*> shadow_buffers; - - void clear_shadow_buffers() { - - for (int i=0;i<shadow_buffers.size();i++) { - - ShadowBuffer *sb=shadow_buffers[i]; - ERR_CONTINUE( sb->owner != this ); - - sb->owner=NULL; - } - - shadow_buffers.clear(); - } - - LightInstance() { shadow_pass=0; last_pass=0; sort_key=0; } - - }; - mutable RID_Owner<Light> light_owner; - mutable RID_Owner<LightInstance> light_instance_owner; - - LightInstance *light_instances[MAX_SCENE_LIGHTS]; - LightInstance *directional_lights[4]; -// LightInstance *directional_light_instances[MAX_SCENE_LIGHTS]; - int light_instance_count; - int directional_light_count; - int last_light_id; - - - struct RenderList { - - enum { - MAX_ELEMENTS=4096, - MAX_LIGHTS=4 - }; - - struct Element { - - - float depth; - const InstanceData *instance; - const Skeleton *skeleton; - union { - uint16_t lights[MAX_HW_LIGHTS]; - uint64_t light_key; - }; - - const Geometry *geometry; - const Material *material; - const GeometryOwner *owner; - uint16_t light_count; - bool mirror; - - - }; - - - Element _elements[MAX_ELEMENTS]; - Element *elements[MAX_ELEMENTS]; - int element_count; - - void clear() { - - element_count=0; - } - - struct SortZ { - - _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - - return A->depth > B->depth; - } - }; - - void sort_z() { - - SortArray<Element*,SortZ> sorter; - sorter.sort(elements,element_count); - } - - - struct SortMat { - - _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - // TODO move to a single uint64 (one comparison) - if (A->material == B->material) { - - return A->light_key < B->light_key; - } else { - - return (A->material < B->material); - } - } - }; - - void sort_mat() { - - SortArray<Element*,SortMat> sorter; - sorter.sort(elements,element_count); - } - - struct SortMatLight { - - _FORCE_INLINE_ bool operator()(const Element* A, const Element* B ) const { - - if (A->material->flags[VS::MATERIAL_FLAG_UNSHADED] == B->material->flags[VS::MATERIAL_FLAG_UNSHADED]) { - - if (A->material == B->material) { - - if (A->geometry == B->geometry) { - - return A->light_key<B->light_key; - } else - return (A->geometry < B->geometry); - } else { - - return (A->material < B->material); - } - } else { - - return (int(A->material->flags[VS::MATERIAL_FLAG_UNSHADED]) < int(B->material->flags[VS::MATERIAL_FLAG_UNSHADED])); - } - } - }; - - void sort_mat_light() { - - SortArray<Element*,SortMatLight> sorter; - sorter.sort(elements,element_count); - } - - _FORCE_INLINE_ Element* add_element() { - - if (element_count>MAX_ELEMENTS) - return NULL; - elements[element_count]=&_elements[element_count]; - return elements[element_count++]; - } - - RenderList() { - - element_count = 0; - for (int i=0;i<MAX_ELEMENTS;i++) - elements[i]=&_elements[i]; // assign elements - } - }; - - RenderList opaque_render_list; - RenderList alpha_render_list; - - RID default_material; - - struct FX { - - bool bgcolor_active; - Color bgcolor; - - bool skybox_active; - RID skybox_cubemap; - - bool antialias_active; - float antialias_tolerance; - - bool glow_active; - int glow_passes; - float glow_attenuation; - float glow_bloom; - - bool ssao_active; - float ssao_attenuation; - float ssao_radius; - float ssao_max_distance; - float ssao_range_max; - float ssao_range_min; - bool ssao_only; - - bool fog_active; - float fog_near; - float fog_far; - float fog_attenuation; - Color fog_color_near; - Color fog_color_far; - bool fog_bg; - - bool toon_active; - float toon_treshold; - float toon_soft; - - bool edge_active; - Color edge_color; - float edge_size; - - FX(); - - }; - mutable RID_Owner<FX> fx_owner; - - - FX *scene_fx; - CameraMatrix camera_projection; - Transform camera_transform; - Transform camera_transform_inverse; - float camera_z_near; - float camera_z_far; - Size2 camera_vp_size; - Color last_color; - - Plane camera_plane; - - bool keep_copies; - - bool depth_write; - bool depth_test; - int blend_mode; - bool lighting; - - _FORCE_INLINE_ void _add_geometry( const Geometry* p_geometry, const InstanceData *p_instance, const Geometry *p_geometry_cmp, const GeometryOwner *p_owner); - - void _render_list_forward(RenderList *p_render_list,bool p_reverse_cull=false); - - void _setup_light(LightInstance* p_instance, int p_idx); - void _setup_lights(const uint16_t * p_lights,int p_light_count); - - _FORCE_INLINE_ void _setup_shader_params(const Material *p_material); - void _setup_fixed_material(const Geometry *p_geometry,const Material *p_material); - void _setup_material(const Geometry *p_geometry,const Material *p_material); - - Error _setup_geometry(const Geometry *p_geometry, const Material* p_material,const Skeleton *p_skeleton, const float *p_morphs); - void _render(const Geometry *p_geometry,const Material *p_material, const Skeleton* p_skeleton, const GeometryOwner *p_owner); - - - /***********/ - /* SHADOWS */ - /***********/ - - struct ShadowBuffer { - - int size; - GLuint fbo; - GLuint depth; - LightInstance *owner; - void init(int p_size); - ShadowBuffer() { size=0; depth=0; owner=NULL; } - }; - - Vector<ShadowBuffer> near_shadow_buffers; - Vector<ShadowBuffer> far_shadow_buffers; - - LightInstance *shadow; - int shadow_pass; - void _init_shadow_buffers(); - - float shadow_near_far_split_size_ratio; - bool _allocate_shadow_buffers(LightInstance *p_instance, Vector<ShadowBuffer>& p_buffers); - void _debug_draw_shadow(ShadowBuffer *p_buffer, const Rect2& p_rect); - void _debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs); - void _debug_shadows(); - void reset_state(); - - /***********/ - /* FBOs */ - /***********/ - - - struct FrameBuffer { - - GLuint fbo; - GLuint color; - GLuint depth; - int width,height; - bool buff16; - bool active; - - struct Blur { - - GLuint fbo; - GLuint color; - } blur[2]; - - } framebuffer; - - void _update_framebuffer(); - void _process_glow_and_bloom(); - - /*********/ - /* FRAME */ - /*********/ - - struct _Rinfo { - - int texture_mem; - int vertex_count; - int object_count; - int mat_change_count; - int shader_change_count; - - } _rinfo; - - GLuint white_tex; - RID canvas_tex; - float canvas_opacity; - VS::MaterialBlendMode canvas_blend; - _FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture); - - - int _setup_geometry_vinfo; - - bool cull_front; - _FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull=false); - - Size2 window_size; - VS::ViewportRect viewport; - double last_time; - double time_delta; - uint64_t frame; - uint64_t scene_pass; - - //void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color* p_colors, const Vector3 *p_uvs,const Plane *p_tangents=NULL,int p_instanced=1); - //void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip=false, bool p_v_flip=false ); - //void _draw_quad(const Rect2& p_rect); - -public: - - /* TEXTURE API */ - - virtual RID texture_create(); - virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const; - virtual void texture_set_flags(RID p_texture,uint32_t p_flags); - virtual uint32_t texture_get_flags(RID p_texture) const; - virtual Image::Format texture_get_format(RID p_texture) const; - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual bool texture_has_alpha(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const; - - /* SHADER API */ - - virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode); - virtual VS::ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0); - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_light_code(RID p_shader) const; - - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - /* COMMON MATERIAL API */ - - virtual RID material_create(); - - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; - - virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant material_get_param(RID p_material, const StringName& p_param) const; - - virtual void material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled); - virtual bool material_get_flag(RID p_material,VS::MaterialFlag p_flag) const; - - virtual void material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode); - virtual VS::MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; - - virtual void material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode); - virtual VS::MaterialBlendMode material_get_blend_mode(RID p_material) const; - - virtual void material_set_line_width(RID p_material,float p_line_width); - virtual float material_get_line_width(RID p_material) const; - - /* FIXED MATERIAL */ - - virtual RID fixed_material_create(); - - virtual void fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const; - - virtual void fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const; - - virtual void fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const; - - virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode); - virtual VS::FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const; - - virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); - virtual Transform fixed_material_get_uv_transform(RID p_material) const; - - virtual void fixed_material_set_point_size(RID p_material,float p_size); - virtual float fixed_material_get_point_size(RID p_material) const; - - /* MESH API */ - - - virtual RID mesh_create(); - - virtual void mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false); - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); - - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; - - virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode); - virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; - virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; - virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; - - virtual void mesh_remove_surface(RID p_mesh,int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh,RID p_skeleton=RID()) const; - - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - /* MULTIMESH API */ - - virtual RID multimesh_create(); - - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; - - virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); - - virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh) const;; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const; - - virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - - /* IMMEDIATE API */ - - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID()); - virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); - virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); - virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); - virtual void immediate_color(RID p_immediate,const Color& p_color); - virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual AABB immediate_get_aabb(RID p_immediate) const; - virtual void immediate_set_material(RID p_immediate,RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; - - - /* PARTICLES API */ - - virtual RID particles_create(); - - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; - - virtual void particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value); - virtual float particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness); - virtual float particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; - - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; - - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const; - - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false); - virtual RID particles_get_material(RID p_particles) const; - - virtual AABB particles_get_aabb(RID p_particles) const; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton,int p_bones); - virtual int skeleton_get_bone_count(RID p_skeleton) const; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); - - - /* LIGHT API */ - - virtual RID light_create(VS::LightType p_type); - virtual VS::LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color); - virtual Color light_get_color(RID p_light,VS::LightColor p_type) const; - - virtual void light_set_shadow(RID p_light,bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; - - virtual void light_set_volumetric(RID p_light,bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; - - virtual void light_set_projector(RID p_light,RID p_texture); - virtual RID light_get_projector(RID p_light) const; - - virtual void light_set_var(RID p_light, VS::LightParam p_var, float p_value); - virtual float light_get_var(RID p_light, VS::LightParam p_var) const; - - virtual void light_set_operator(RID p_light,VS::LightOp p_op); - virtual VS::LightOp light_get_operator(RID p_light) const; - - virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - - virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const; - - virtual AABB light_get_aabb(RID p_poly) const; - - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); - - virtual bool light_instance_has_shadow(RID p_light_instance) const; - virtual bool light_instance_assign_shadow(RID p_light_instance); - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const; - virtual int light_instance_get_shadow_passes(RID p_light_instance) const; - virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const; - virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; } - - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const; - virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - - virtual void shadow_clear_near(); - virtual bool shadow_allocate_near(RID p_light); - virtual bool shadow_allocate_far(RID p_light); - - - /* PARTICLES INSTANCE */ - - virtual RID particles_instance_create(RID p_particles); - virtual void particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform); - - /* VIEWPORT */ - - virtual RID viewport_data_create(); - - virtual RID render_target_create(); - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height); - virtual RID render_target_get_texture(RID p_render_target) const; - virtual bool render_target_renedered_in_frame(RID p_render_target); - - /* RENDER API */ - /* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - virtual void begin_frame(); - - virtual void set_viewport(const VS::ViewportRect& p_viewport); - virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false,bool p_vflip=false); - virtual void clear_viewport(const Color& p_color); - virtual void capture_viewport(Image* r_capture); - - - virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug); - virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection); - - virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls - - - virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data); - virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data); - virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {} - virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data); - - virtual void end_scene(); - virtual void end_shadow_map(); - - virtual void end_frame(); - - /* CANVAS API */ - - virtual void canvas_begin(); - virtual void canvas_disable_blending(); - virtual void canvas_set_opacity(float p_opacity); - virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode); - virtual void canvas_begin_rect(const Matrix32& p_transform); - virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect); - virtual void canvas_end_rect(); - virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width); - virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate); - virtual void canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); - virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width); - virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); - virtual void canvas_set_transform(const Matrix32& p_transform); - - /* FX */ - - virtual RID fx_create(); - virtual void fx_get_effects(RID p_fx,List<String> *p_effects) const; - virtual void fx_set_active(RID p_fx,const String& p_effect, bool p_active); - virtual bool fx_is_active(RID p_fx,const String& p_effect) const; - virtual void fx_get_effect_params(RID p_fx,const String& p_effect,List<PropertyInfo> *p_params) const; - virtual Variant fx_get_effect_param(RID p_fx,const String& p_effect,const String& p_param) const; - virtual void fx_set_effect_param(RID p_fx,const String& p_effect, const String& p_param, const Variant& p_pvalue); - - /* ENVIRONMENT */ - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); - virtual VS::EnvironmentBG environment_get_background(RID p_env) const; - - virtual void environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value); - virtual Variant environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const; - - virtual void environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const; - - virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); - virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; - - - /*MISC*/ - - virtual bool is_texture(const RID& p_rid) const; - virtual bool is_material(const RID& p_rid) const; - virtual bool is_mesh(const RID& p_rid) const; - virtual bool is_multimesh(const RID& p_rid) const; - virtual bool is_immediate(const RID& p_rid) const; - virtual bool is_particles(const RID &p_beam) const; - - virtual bool is_light(const RID& p_rid) const; - virtual bool is_light_instance(const RID& p_rid) const; - virtual bool is_particles_instance(const RID& p_rid) const; - virtual bool is_skeleton(const RID& p_rid) const; - virtual bool is_environment(const RID& p_rid) const; - virtual bool is_fx(const RID& p_rid) const; - virtual bool is_shader(const RID& p_rid) const; - - virtual void free(const RID& p_rid); - - virtual void custom_shade_model_set_shader(int p_model, RID p_shader); - virtual RID custom_shade_model_get_shader(int p_model) const; - virtual void custom_shade_model_set_name(int p_model, const String& p_name); - virtual String custom_shade_model_get_name(int p_model) const; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info); - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const; - - - virtual void init(); - virtual void finish(); - - virtual int get_render_info(VS::RenderInfo p_info); - - void reload_vram(); - - virtual bool needs_to_draw_next_frame() const; - - virtual bool has_feature(VS::Features p_feature) const; - - -#ifdef TOOLS_ENABLED - RasterizerGLES1(bool p_keep_copies=true,bool p_use_reload_hooks=false); -#else - RasterizerGLES1(bool p_keep_copies=false,bool p_use_reload_hooks=false); -#endif - virtual ~RasterizerGLES1(); -}; - -#endif -#endif diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index d596aad4b9..4f486897d1 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -91,6 +91,10 @@ static RasterizerGLES2* _singleton = NULL; +#ifdef GLES_NO_CLIENT_ARRAYS +static float GlobalVertexBuffer[MAX_POLYGON_VERTICES * 8] = {0}; +#endif + static const GLenum prim_type[]={GL_POINTS,GL_LINES,GL_TRIANGLES,GL_TRIANGLE_FAN}; _FORCE_INLINE_ static void _set_color_attrib(const Color& p_color) { @@ -139,11 +143,13 @@ static _FORCE_INLINE_ uint16_t make_half_float(float f) { else if (exp <= 0x38000000) { - // store a denorm half-float value or zero + /*// store a denorm half-float value or zero exp = (0x38000000 - exp) >> 23; mantissa >>= (14 + exp); hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa); + */ + hf=0; //denormals do not work for 3D, convert to zero } else { @@ -360,17 +366,19 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c /* TEXTURE API */ -Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { +Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) { r_has_alpha_cache=false; r_compressed=false; + r_gl_format=0; Image image=p_image; switch(p_format) { case Image::FORMAT_GRAYSCALE: { r_gl_components=1; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE; + r_gl_format=GL_LUMINANCE; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE; } break; case Image::FORMAT_INTENSITY: { @@ -378,14 +386,16 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGBA); r_gl_components=4; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; + r_gl_format=GL_RGBA; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA; r_has_alpha_cache=true; } break; case Image::FORMAT_GRAYSCALE_ALPHA: { //image.convert(Image::FORMAT_RGBA); r_gl_components=2; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA; + r_gl_format=GL_LUMINANCE_ALPHA; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA; r_has_alpha_cache=true; } break; @@ -394,7 +404,8 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGB); r_gl_components=3; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB; + r_gl_format=GL_RGB; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB; } break; @@ -407,14 +418,15 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; @@ -426,14 +438,15 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_EXT; - } else { + r_gl_internal_format=_GL_SRGB_EXT; r_gl_format=GL_RGB; + } else { + r_gl_internal_format=GL_RGB; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; } } break; case Image::FORMAT_RGBA: { @@ -442,14 +455,16 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; r_gl_format=GL_RGBA; + //r_gl_internal_format=GL_RGBA; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; @@ -465,21 +480,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT; r_compressed=true; }; @@ -495,20 +511,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT; r_has_alpha_cache=true; r_compressed=true; @@ -526,20 +543,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { r_gl_components=1; //doesn't matter much - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT; r_has_alpha_cache=true; r_compressed=true; }; @@ -556,20 +574,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT; + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT; r_gl_components=1; //doesn't matter much r_compressed=true; }; @@ -586,19 +605,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; + r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; r_gl_components=1; //doesn't matter much r_compressed=true; }; @@ -614,21 +634,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; @@ -645,22 +666,23 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + r_gl_internal_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; @@ -677,19 +699,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -705,19 +728,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_ALPHA_EXT; - } else { r_gl_format=GL_RGBA; + r_gl_internal_format=_GL_SRGB_ALPHA_EXT; + } else { + r_gl_internal_format=GL_RGBA; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } r_has_alpha_cache=true; } else { - r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -734,21 +758,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) { if (srgb_supported) { - r_gl_format=_GL_SRGB_EXT; - } else { r_gl_format=GL_RGB; + r_gl_internal_format=_GL_SRGB_EXT; + } else { + r_gl_internal_format=GL_RGB; if (!image.empty()) image.srgb_to_linear(); } } else { - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; } - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; } else { - r_gl_format=_EXT_ETC1_RGB8_OES; + r_gl_internal_format=_EXT_ETC1_RGB8_OES; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -762,12 +787,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=3; - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; } else { - r_gl_format=_EXT_ATC_RGB_AMD; + r_gl_internal_format=_EXT_ATC_RGB_AMD; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -781,12 +806,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } else { - r_gl_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD; + r_gl_internal_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -800,12 +825,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For image.decompress(); } r_gl_components=4; - r_gl_format=GL_RGBA; + r_gl_internal_format=GL_RGBA; } else { - r_gl_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD; + r_gl_internal_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD; r_gl_components=1; //doesn't matter much r_compressed=true; } @@ -816,7 +841,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For if (!image.empty()) image.convert(Image::FORMAT_RGB); - r_gl_format=GL_RGB; + r_gl_internal_format=GL_RGB; r_gl_components=3; } break; @@ -827,6 +852,10 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For } } + if (r_gl_format==0) { + r_gl_format=r_gl_internal_format; + } + return image; } @@ -858,6 +887,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I bool has_alpha_cache; int components; GLenum format; + GLenum internal_format; bool compressed; int po2_width = nearest_power_of_2(p_width); @@ -876,7 +906,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->flags=p_flags; texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - _get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed); + _get_gl_image_and_format(Image(),texture->format,texture->flags,format,internal_format,components,has_alpha_cache,compressed); bool scale_textures = !compressed && !(p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags&VS::TEXTURE_FLAG_MIPMAPS); @@ -894,6 +924,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I texture->gl_components_cache=components; texture->gl_format_cache=format; + texture->gl_internal_format_cache=internal_format; texture->format_has_alpha=has_alpha_cache; texture->compressed=compressed; texture->has_alpha=false; //by default it doesn't have alpha unless something with alpha is blitteds @@ -908,7 +939,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I if (p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { //prealloc if video - glTexImage2D(texture->target, 0, format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE,NULL); + glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE,NULL); } texture->active=true; @@ -926,6 +957,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu int components; GLenum format; + GLenum internal_format; bool alpha; bool compressed; @@ -933,7 +965,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu texture->image[p_cube_side]=p_image; } - Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,components,alpha,compressed); + Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,internal_format,components,alpha,compressed); if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) { @@ -943,7 +975,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu - if (img.detect_alpha()==Image::ALPHA_BLEND) { + if (!(texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) { texture->has_alpha=true; } @@ -961,8 +993,14 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + else { + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + } else { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + + } + } if (texture->flags&VS::TEXTURE_FLAG_FILTER) { @@ -999,32 +1037,33 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu int mipmaps= (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && img.get_mipmaps()>0) ? img.get_mipmaps() +1 : 1; - int w=img.get_width(); - int h=img.get_height(); + //int w=img.get_width(); + //int h=img.get_height(); int tsize=0; for(int i=0;i<mipmaps;i++) { int size,ofs; - img.get_mipmap_offset_and_size(i,ofs,size); + int mm_w,mm_h; + img.get_mipmap_offset_size_and_dimensions(i,ofs,size,mm_w,mm_h); if (texture->compressed) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glCompressedTexImage2D( blit_target, i, format,w,h,0,size,&read[ofs] ); + glCompressedTexImage2D( blit_target, i, format,mm_w,mm_h,0,size,&read[ofs] ); } else { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) { - glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] ); + glTexSubImage2D( blit_target, i, 0,0,mm_w, mm_h,format,GL_UNSIGNED_BYTE,&read[ofs] ); } else { - glTexImage2D(blit_target, i, format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); + glTexImage2D(blit_target, i, internal_format, mm_w, mm_h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]); } } tsize+=size; - w = MAX(1,w>>1); - h = MAX(1,h>>1); + //w = MAX(Image::,w>>1); + //h = MAX(1,h>>1); } @@ -1255,8 +1294,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) { if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + else{ + if (texture->flags&VS::TEXTURE_FLAG_FILTER) { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + } else { + glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + + } + } if (texture->flags&VS::TEXTURE_FLAG_FILTER) { @@ -1383,6 +1428,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { material_shader.free_custom_shader(shader->custom_code_id); } break; + case VS::SHADER_CANVAS_ITEM: { + canvas_shader.free_custom_shader(shader->custom_code_id); + } break; } shader->custom_code_id=0; @@ -1394,6 +1442,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { shader->custom_code_id=material_shader.create_custom_shader(); } break; + case VS::SHADER_CANVAS_ITEM: { + shader->custom_code_id=canvas_shader.create_custom_shader(); + } break; } _shader_make_dirty(shader); @@ -1513,6 +1564,48 @@ void RasterizerGLES2::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_ } +void RasterizerGLES2::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); + + if (p_texture.is_valid()) + shader->default_textures[p_name]=p_texture; + else + shader->default_textures.erase(p_name); + + _shader_make_dirty(shader); + +} + +RID RasterizerGLES2::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,RID()); + + const Map<StringName,RID>::Element *E=shader->default_textures.find(p_name); + if (!E) + return RID(); + return E->get(); +} + +Variant RasterizerGLES2::shader_get_default_param(RID p_shader, const StringName& p_name) { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,Variant()); + + //update shader params if necesary + //make sure the shader is compiled and everything + //so the actual parameters can be properly retrieved! + if (shader->dirty_list.in_list()) { + _update_shader(shader); + } + if (shader->valid && shader->uniforms.has(p_name)) + return shader->uniforms[p_name].default_value; + + return Variant(); +} + /* COMMON MATERIAL API */ @@ -1555,6 +1648,7 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par material->shader_version=0; //get default! } else { E->get().value=p_value; + E->get().inuse=true; } } else { @@ -1562,6 +1656,7 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par ud.index=-1; ud.value=p_value; ud.istexture=p_value.get_type()==Variant::_RID; /// cache it being texture + ud.inuse=true; material->shader_params[p_param]=ud; //may be got at some point, or erased } @@ -1593,7 +1688,7 @@ Variant RasterizerGLES2::material_get_param(RID p_material, const StringName& p_ } - if (material->shader_params.has(p_param)) + if (material->shader_params.has(p_param) && material->shader_params[p_param].inuse) return material->shader_params[p_param].value; else return Variant(); @@ -2447,7 +2542,7 @@ Error RasterizerGLES2::_surface_set_arrays(Surface *p_surface, uint8_t *p_mem,ui void RasterizerGLES2::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { ERR_EXPLAIN("OpenGL Rasterizer does not support custom surfaces. Running on wrong platform?"); - ERR_FAIL_V(); + ERR_FAIL(); } Array RasterizerGLES2::mesh_get_surface_arrays(RID p_mesh,int p_surface) const { @@ -3960,8 +4055,16 @@ void RasterizerGLES2::render_target_set_size(RID p_render_target,int p_width,int glGenTextures(1, &rt->color); glBindTexture(GL_TEXTURE_2D, rt->color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + if (rt->texture_ptr->flags&VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); @@ -4030,6 +4133,10 @@ void RasterizerGLES2::begin_frame() { shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter"))); #endif + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5,shadow_filter==SHADOW_FILTER_PCF5); + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13,shadow_filter==SHADOW_FILTER_PCF13); + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); + window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height ); double time = (OS::get_singleton()->get_ticks_usec()/1000); // get msec @@ -4147,6 +4254,9 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { pixels.resize(viewport.width*viewport.height*4); DVector<uint8_t>::Write w = pixels.write(); glPixelStorei(GL_PACK_ALIGNMENT, 4); + +// uint64_t time = OS::get_singleton()->get_ticks_usec(); + if (current_rt) { #ifdef GLEW_ENABLED glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -4156,10 +4266,24 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { // back? glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr()); } - w=DVector<uint8_t>::Write(); + uint32_t *imgptr = (uint32_t*)w.ptr(); + for(int y=0;y<(viewport.height/2);y++) { + + uint32_t *ptr1 = &imgptr[y*viewport.width]; + uint32_t *ptr2 = &imgptr[(viewport.height-y-1)*viewport.width]; + + for(int x=0;x<viewport.width;x++) { + + uint32_t tmp = ptr1[x]; + ptr1[x]=ptr2[x]; + ptr2[x]=tmp; + } + } + + w=DVector<uint8_t>::Write(); r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels); - r_capture->flip_y(); + //r_capture->flip_y(); #endif @@ -4169,7 +4293,7 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { void RasterizerGLES2::clear_viewport(const Color& p_color) { - if (current_rt) { + if (current_rt || using_canvas_bg) { glScissor( 0, 0, viewport.width, viewport.height ); } else { @@ -4177,7 +4301,7 @@ void RasterizerGLES2::clear_viewport(const Color& p_color) { } glEnable(GL_SCISSOR_TEST); - glClearColor(p_color.r,p_color.g,p_color.b,1.0); + glClearColor(p_color.r,p_color.g,p_color.b,p_color.a); glClear(GL_COLOR_BUFFER_BIT); //should not clear if anything else cleared.. glDisable(GL_SCISSOR_TEST); }; @@ -4362,6 +4486,13 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (err) { return; //invalid } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Error err = shader_precompiler.compile(p_shader->vertex_code,ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX,vertex_code,vertex_globals,vertex_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } + } //print_line("compiled vertex: "+vertex_code); @@ -4371,9 +4502,16 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { String fragment_code; String fragment_globals; - Error err = shader_precompiler.compile(p_shader->fragment_code,(p_shader->mode==VS::SHADER_MATERIAL?ShaderLanguage::SHADER_MATERIAL_FRAGMENT:ShaderLanguage::SHADER_POST_PROCESS),fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); - if (err) { - return; //invalid + if (p_shader->mode==VS::SHADER_MATERIAL) { + Error err = shader_precompiler.compile(p_shader->fragment_code,ShaderLanguage::SHADER_MATERIAL_FRAGMENT,fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + Error err = shader_precompiler.compile(p_shader->fragment_code,ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT,fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } } @@ -4386,6 +4524,11 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (err) { return; //invalid } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + Error err = shader_precompiler.compile(p_shader->light_code,(ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT),light_code,light_globals,light_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } } fragment_globals+=light_globals; //both fragment anyway @@ -4446,7 +4589,42 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { } material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); - } else { + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Vector<const char*> enablers; + + if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { + enablers.push_back("#define USE_TIME\n"); + uses_time=true; + } + if (fragment_flags.uses_normal) { + enablers.push_back("#define NORMAL_USED\n"); + } + if (light_flags.uses_light) { + enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); + } + if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) + enablers.push_back("#define ENABLE_VAR1_INTERP\n"); + if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp) + enablers.push_back("#define ENABLE_VAR2_INTERP\n"); + if (fragment_flags.uses_texscreen) { + enablers.push_back("#define ENABLE_TEXSCREEN\n"); + } + if (fragment_flags.uses_screen_uv) { + enablers.push_back("#define ENABLE_SCREEN_UV\n"); + } + if (fragment_flags.uses_texpixel_size) { + enablers.push_back("#define USE_TEXPIXEL_SIZE\n"); + } + if (light_flags.uses_shadow_color) { + enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n"); + } + + if (vertex_flags.uses_worldvec) { + enablers.push_back("#define USE_WORLD_VEC\n"); + } + canvas_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); + //postprocess_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names); } @@ -4457,7 +4635,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { p_shader->has_texscreen=fragment_flags.uses_texscreen; p_shader->has_screen_uv=fragment_flags.uses_screen_uv; p_shader->can_zpass=!fragment_flags.uses_discard && !vertex_flags.vertex_code_writes_vertex; + p_shader->uses_normal=fragment_flags.uses_normal || light_flags.uses_normal; p_shader->uses_time=uses_time; + p_shader->uses_texpixel_size=fragment_flags.uses_texpixel_size; p_shader->version++; } @@ -4604,7 +4784,8 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD if (m->flags[VS::MATERIAL_FLAG_INVERT_FACES]) e->mirror=!e->mirror; - e->light_type=0xFF; // no lights! + //e->light_type=0xFF; // no lights! + e->light_type=3; //light type 3 is no light? e->light=0xFFFF; if (!shadow && !has_blend_alpha && has_alpha && m->depth_draw_mode==VS::MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA) { @@ -4807,31 +4988,58 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ Material::UniformData ud; - bool keep=true; + bool keep=true; //keep material value + + Map<StringName,Material::UniformData>::Element *OLD=old_mparams.find(E->key()); + bool has_old = OLD; + bool old_inuse=has_old && old_mparams[E->key()].inuse; + + ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); - if (!old_mparams.has(E->key())) + if (!has_old || !old_inuse) { keep=false; - else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) { + } + else if (OLD->get().value.get_type()!=E->value().default_value.get_type()) { + + if (OLD->get().value.get_type()==Variant::INT && E->get().type==ShaderLanguage::TYPE_FLOAT) { + //handle common mistake using shaders (feeding ints instead of float) + OLD->get().value=float(OLD->get().value); + keep=true; + } else if (!ud.istexture && E->value().default_value.get_type()!=Variant::NIL) { - if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { + keep=false; + } + //type changed between old and new + /* if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures keep=false; } else if (!old_mparams[E->key()].value.is_num() || !E->value().default_value.get_type()) - keep=false; + keep=false;*/ + + //value is invalid because type differs and default is not null + ; } + if (keep) { ud.value=old_mparams[E->key()].value; + //print_line("KEEP: "+String(E->key())); } else { - ud.value=E->value().default_value; + if (ud.istexture && p_material->shader_cache->default_textures.has(E->key())) + ud.value=p_material->shader_cache->default_textures[E->key()]; + else + ud.value=E->value().default_value; + old_inuse=false; //if reverted to default, obviously did not work + //print_line("NEW: "+String(E->key())+" because: hasold-"+itos(old_mparams.has(E->key()))); //if (old_mparams.has(E->key())) // print_line(" told "+Variant::get_type_name(old_mparams[E->key()].value.get_type())+" tnew "+Variant::get_type_name(E->value().default_value.get_type())); } - ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); + ud.index=idx++; + ud.inuse=old_inuse; mparams[E->key()]=ud; } @@ -4935,8 +5143,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material int texcoord=0; for (Map<StringName,Material::UniformData>::Element *E=p_material->shader_params.front();E;E=E->next()) { + if (E->get().index<0) continue; +// print_line(String(E->key())+": "+E->get().value); if (E->get().istexture) { //clearly a texture.. RID rid = E->get().value; @@ -4946,12 +5156,14 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material Texture *t=NULL; if (rid.is_valid()) { + t=texture_owner.get(rid); - if (!t) + if (!t) { E->get().value=RID(); //nullify, invalid texture + rid=RID(); + } } - glActiveTexture(GL_TEXTURE0+texcoord); glUniform1i(loc,texcoord); //TODO - this could happen automatically on compile... if (t) { @@ -4975,8 +5187,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material } + if (p_material->shader_cache->has_texscreen && framebuffer.active) { material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(0,0,float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_TEX,texcoord); glActiveTexture(GL_TEXTURE0+texcoord); glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); @@ -5108,7 +5322,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { if (li->near_shadow_buffer) { - glActiveTexture(GL_TEXTURE7); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); //if (read_depth_supported) { glBindTexture(GL_TEXTURE_2D,li->near_shadow_buffer->depth); @@ -5119,7 +5333,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size); - material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,max_texture_units-1); if (shadow_filter==SHADOW_FILTER_ESM) material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER])); @@ -5312,13 +5526,15 @@ Error RasterizerGLES2::_setup_geometry(const Geometry *p_geometry, const Materia base = surf->array_local; glBindBuffer(GL_ARRAY_BUFFER, 0); bool can_copy_to_local=surf->local_stride * surf->array_len <= skinned_buffer_size; + if (p_morphs && surf->stride * surf->array_len > skinned_buffer_size) + can_copy_to_local=false; + + if (!can_copy_to_local) skeleton_valid=false; - /* compute morphs */ - if (p_morphs && surf->morph_target_count && can_copy_to_local) { @@ -5739,9 +5955,10 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater float twd=(1.0/mm->tw)*4.0; float thd=1.0/mm->th; float parm[3]={0.0,01.0,(1.0f/mm->tw)}; - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glDisableVertexAttribArray(6); glBindTexture(GL_TEXTURE_2D,mm->tex_id); + material_shader.set_uniform(MaterialShaderGLES2::INSTANCE_MATRICES,GL_TEXTURE0+max_texture_units-2); if (s->index_array_len>0) { @@ -6042,7 +6259,7 @@ void RasterizerGLES2::_setup_skeleton(const Skeleton *p_skeleton) { material_shader.set_conditional(MaterialShaderGLES2::USE_SKELETON,p_skeleton!=NULL); if (p_skeleton && p_skeleton->tex_id) { - glActiveTexture(GL_TEXTURE6); + glActiveTexture(GL_TEXTURE0+max_texture_units-2); glBindTexture(GL_TEXTURE_2D,p_skeleton->tex_id); } @@ -6091,7 +6308,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool stores_glow = !shadow && (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) && !p_alpha_pass; - + float sampled_light_dp_multiplier=1.0; bool prev_blend=false; glDisable(GL_BLEND); @@ -6110,6 +6327,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans bool bind_baked_light_octree=false; bool bind_baked_lightmap=false; bool additive=false; + bool bind_dp_sampler=false; if (!shadow) { @@ -6204,7 +6422,12 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans case VS::MATERIAL_BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } break; case VS::MATERIAL_BLEND_MODE_ADD: { @@ -6215,12 +6438,17 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans } break; case VS::MATERIAL_BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_SUBTRACT); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; case VS::MATERIAL_BLEND_MODE_MUL: { glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } break; @@ -6231,6 +6459,22 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false); material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false); + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,false); + + if (e->instance->sampled_light.is_valid()) { + + SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light); + if (sl) { + + baked_light=NULL; //can't mix + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,true); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); + glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture + sampled_light_dp_multiplier=sl->multiplier; + bind_dp_sampler=true; + } + } + if (!additive && baked_light) { @@ -6241,9 +6485,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex=texture_owner.get(baked_light->octree_texture); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } + if (baked_light->light_texture.is_valid()) { + Texture *texl=texture_owner.get(baked_light->light_texture); + if (texl) { + glActiveTexture(GL_TEXTURE0+max_texture_units-4); + glBindTexture(texl->target,texl->tex_id); //bind the light texture + } + } } } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { @@ -6266,7 +6517,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans Texture *tex = texture_owner.get(texid); if (tex) { - glActiveTexture(GL_TEXTURE5); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); glBindTexture(tex->target,tex->tex_id); //bind the texture } @@ -6342,7 +6593,15 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_SIZE, baked_light->octree_lattice_size); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_DIVIDE, baked_light->octree_lattice_divide); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_STEPS, baked_light->octree_steps); - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,max_texture_units-3); + if (baked_light->light_texture.is_valid()) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-4); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->light_tex_pixel_size); + } else { + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_TEX,max_texture_units-3); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LIGHT_PIX_SIZE,baked_light->octree_tex_pixel_size); + } material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_MULTIPLIER,baked_light->texture_multiplier); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_PIX_SIZE,baked_light->octree_tex_pixel_size); @@ -6351,11 +6610,16 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans if (bind_baked_lightmap && (baked_light!=prev_baked_light || rebind)) { - material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, 5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP, max_texture_units-3); material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_LIGHTMAP_MULTIPLIER, baked_light->lightmap_multiplier); } + if (bind_dp_sampler) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER_MULTIPLIER,sampled_light_dp_multiplier); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_DP_SAMPLER,max_texture_units-3); + } _set_cull(e->mirror,p_reverse_cull); @@ -6364,7 +6628,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_uniform(MaterialShaderGLES2::CAMERA_INVERSE_TRANSFORM, p_view_transform_inverse); material_shader.set_uniform(MaterialShaderGLES2::PROJECTION_TRANSFORM, p_projection); if (skeleton && use_hw_skeleton_xform) { - //material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,6); + material_shader.set_uniform(MaterialShaderGLES2::SKELETON_MATRICES,GL_TEXTURE0+max_texture_units-2); material_shader.set_uniform(MaterialShaderGLES2::SKELTEX_PIXEL_SIZE,skeleton->pixel_size); } if (!shadow) { @@ -6451,7 +6715,12 @@ void RasterizerGLES2::_copy_to_texscreen() { #endif glDisable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); @@ -6683,7 +6952,7 @@ void RasterizerGLES2::_draw_tex_bg() { RID texture; - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { texture=current_env->bg_param[VS::ENV_BG_PARAM_TEXTURE]; } else { texture=current_env->bg_param[VS::ENV_BG_PARAM_CUBEMAP]; @@ -6700,25 +6969,20 @@ void RasterizerGLES2::_draw_tex_bg() { copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,true); - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false); } else { copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,true); } - if (current_env->bg_mode==VS::ENV_BG_CUBEMAP_RGBE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,true); - } else { - copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false); - } copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true); copy_shader.bind(); - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); } else { glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE_CUBE),0); @@ -6745,7 +7009,7 @@ void RasterizerGLES2::_draw_tex_bg() { Vector3( 0, 0, 0) }; - if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) { + if (current_env->bg_mode==VS::ENV_BG_TEXTURE) { //regular texture //adjust aspect @@ -6815,7 +7079,7 @@ void RasterizerGLES2::end_scene() { if (framebuffer.active) { //detect when to use the framebuffer object - if (texscreen_used || framebuffer.scale!=1) { + if (using_canvas_bg || texscreen_used || framebuffer.scale!=1) { use_fb=true; } else if (current_env) { use_fb=false; @@ -6867,6 +7131,7 @@ void RasterizerGLES2::end_scene() { switch(current_env->bg_mode) { + case VS::ENV_BG_CANVAS: case VS::ENV_BG_KEEP: { //copy from framebuffer if framebuffer glClear(GL_DEPTH_BUFFER_BIT); @@ -6879,7 +7144,7 @@ void RasterizerGLES2::end_scene() { bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR]; else bgcolor = Globals::get_singleton()->get("render/default_clear_color"); - bgcolor = _convert_color(bgcolor); + bgcolor = _convert_color(bgcolor); float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0; glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a); _glClearDepth(1.0); @@ -6887,9 +7152,7 @@ void RasterizerGLES2::end_scene() { } break; case VS::ENV_BG_TEXTURE: - case VS::ENV_BG_CUBEMAP: - case VS::ENV_BG_TEXTURE_RGBE: - case VS::ENV_BG_CUBEMAP_RGBE: { + case VS::ENV_BG_CUBEMAP: { glClear(GL_DEPTH_BUFFER_BIT); @@ -6925,7 +7188,12 @@ void RasterizerGLES2::end_scene() { current_depth_mask=true; texscreen_copied=false; glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } glDisable(GL_BLEND); current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; @@ -6942,7 +7210,12 @@ void RasterizerGLES2::end_scene() { } glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } glDisable(GL_BLEND); current_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; material_shader.set_conditional(MaterialShaderGLES2::USE_GLOW,false); @@ -7098,7 +7371,12 @@ void RasterizerGLES2::end_scene() { _debug_shadows(); } // _debug_luminances(); +// _debug_samplers(); + if (using_canvas_bg) { + using_canvas_bg=false; + glColorMask(1,1,1,1); //don't touch alpha + } } void RasterizerGLES2::end_shadow_map() { @@ -7498,6 +7776,38 @@ void RasterizerGLES2::_debug_luminances() { } +void RasterizerGLES2::_debug_samplers() { + canvas_shader.set_conditional(CanvasShaderGLES2::DEBUG_ENCODED_32,false); + canvas_begin(); + glDisable(GL_BLEND); + _set_color_attrib(Color(1,1,1,1)); + canvas_shader.bind(); + + + List<RID> samplers; + sampled_light_owner.get_owned_list(&samplers); + + Size2 debug_size(128,128); + Size2 ofs; + + + for (List<RID>::Element *E=samplers.front();E;E=E->next()) { + + SampledLight *sl=sampled_light_owner.get(E->get()); + + _debug_draw_shadow(sl->texture, Rect2( ofs, debug_size )); + + ofs.x+=debug_size.x/2; + if ( (ofs.x+debug_size.x) > viewport.width ) { + + ofs.x=0; + ofs.y+=debug_size.y; + } + } + + + +} void RasterizerGLES2::_debug_shadows() { canvas_begin(); @@ -7535,8 +7845,26 @@ void RasterizerGLES2::flush_frame() { /* CANVAS API */ +void RasterizerGLES2::begin_canvas_bg() { + + if (framebuffer.active) { + using_canvas_bg=true; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); + glViewport( 0,0,viewport.width , viewport.height ); + } else { + using_canvas_bg=false; + } + +} + void RasterizerGLES2::canvas_begin() { + + if (using_canvas_bg) { + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo); + glColorMask(1,1,1,0); //don't touch alpha + } + glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); @@ -7546,7 +7874,12 @@ void RasterizerGLES2::canvas_begin() { #endif glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } //glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glLineWidth(1.0); glBindBuffer(GL_ARRAY_BUFFER,0); @@ -7560,10 +7893,13 @@ void RasterizerGLES2::canvas_begin() { canvas_tex=RID(); //material_shader.unbind(); canvas_shader.unbind(); + canvas_shader.set_custom_shader(0); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false); canvas_shader.bind(); canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); + canvas_use_modulate=false; _set_color_attrib(Color(1,1,1)); - Transform canvas_transform; + canvas_transform=Transform(); canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); float csy = 1.0; if (current_rt && current_rt_vflip) @@ -7576,7 +7912,10 @@ void RasterizerGLES2::canvas_begin() { canvas_opacity=1.0; canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX; + canvas_texscreen_used=false; + uses_texpixel_size=false; + canvas_last_material=NULL; } @@ -7598,7 +7937,12 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { case VS::MATERIAL_BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } break; case VS::MATERIAL_BLEND_MODE_ADD: { @@ -7609,7 +7953,7 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { } break; case VS::MATERIAL_BLEND_MODE_SUB: { - glBlendEquation(GL_FUNC_SUBTRACT); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; case VS::MATERIAL_BLEND_MODE_MUL: { @@ -7659,7 +8003,7 @@ void RasterizerGLES2::canvas_end_rect() { RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_texture) { - if (p_texture==canvas_tex) { + if (p_texture==canvas_tex && !rebind_texpixel_size) { if (canvas_tex.is_valid()) { Texture*texture=texture_owner.get(p_texture); return texture; @@ -7667,14 +8011,16 @@ RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_tex return NULL; } - + rebind_texpixel_size=false; if (p_texture.is_valid()) { + Texture*texture=texture_owner.get(p_texture); if (!texture) { canvas_tex=RID(); glBindTexture(GL_TEXTURE_2D,white_tex); + return NULL; } @@ -7683,6 +8029,9 @@ RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_tex glBindTexture(GL_TEXTURE_2D,texture->tex_id); canvas_tex=p_texture; + if (uses_texpixel_size) { + canvas_shader.set_uniform(CanvasShaderGLES2::TEXPIXEL_SIZE,Size2(1.0/texture->width,1.0/texture->height)); + } return texture; @@ -7831,7 +8180,7 @@ void RasterizerGLES2::_draw_gui_primitive2(int p_points, const Vector2 *p_vertic _rinfo.ci_draw_commands++; } -void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip, bool p_v_flip ) { +void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip, bool p_v_flip, bool p_transpose ) { Vector2 texcoords[4]= { Vector2( p_src_region.pos.x/p_tex_size.width, @@ -7847,6 +8196,9 @@ void RasterizerGLES2::_draw_textured_quad(const Rect2& p_rect, const Rect2& p_sr (p_src_region.pos.y+p_src_region.size.height)/p_tex_size.height) }; + if (p_transpose) { + SWAP( texcoords[1], texcoords[3] ); + } if (p_h_flip) { SWAP( texcoords[0], texcoords[1] ); SWAP( texcoords[2], texcoords[3] ); @@ -7894,11 +8246,11 @@ void RasterizerGLES2::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R if (!(p_flags&CANVAS_RECT_REGION)) { Rect2 region = Rect2(0,0,texture->width,texture->height); - _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V); + _draw_textured_quad(p_rect,region,region.size,p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE); } else { - _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V ); + _draw_textured_quad(p_rect, p_source, Size2(texture->width,texture->height),p_flags&CANVAS_RECT_FLIP_H,p_flags&CANVAS_RECT_FLIP_V,p_flags&CANVAS_RECT_TRANSPOSE); } } else { @@ -7993,20 +8345,22 @@ void RasterizerGLES2::canvas_draw_primitive(const Vector<Point2>& p_points, cons void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { - bool do_colors=false; + bool do_colors=false; + Color m; + if (p_singlecolor) { + m = *p_colors; + m.a*=canvas_opacity; + _set_color_attrib(m); + } else if (!p_colors) { + m = Color(1, 1, 1, canvas_opacity); + _set_color_attrib(m); + } else + do_colors=true; - if (p_singlecolor) { - Color m = *p_colors; - m.a*=canvas_opacity; - _set_color_attrib(m); - } else if (!p_colors) { - _set_color_attrib( Color(1,1,1,canvas_opacity)); - } else - do_colors=true; + Texture *texture = _bind_canvas_texture(p_texture); - Texture *texture = _bind_canvas_texture(p_texture); - - glEnableVertexAttribArray(VS::ARRAY_VERTEX); +#ifndef GLES_NO_CLIENT_ARRAYS + glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(Vector2), p_vertices ); if (do_colors) { @@ -8025,12 +8379,89 @@ void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indic } if (p_indices) { - +#ifdef GLEW_ENABLED glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); +#else + static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! + ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; i<p_vertex_count; i++) { + _draw_poly_indices[i] = p_indices[i]; + }; + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, _draw_poly_indices ); +#endif } else { glDrawArrays(GL_TRIANGLES,0,p_vertex_count); } + +#else //WebGL specific impl. + glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer); + float *b = GlobalVertexBuffer; + int ofs = 0; + if(p_vertex_count > MAX_POLYGON_VERTICES){ + print_line("Too many vertices to render"); + return; + } + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer( VS::ARRAY_VERTEX, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_vertices[i].x; + b[ofs++]=p_vertices[i].y; + } + + if (p_colors && do_colors) { + + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer( VS::ARRAY_COLOR, 4 ,GL_FLOAT, false, sizeof(float)*4, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_colors[i].r; + b[ofs++]=p_colors[i].g; + b[ofs++]=p_colors[i].b; + b[ofs++]=p_colors[i].a; + } + + } else { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + } + + + if (p_uvs) { + + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer( VS::ARRAY_TEX_UV, 2 ,GL_FLOAT, false, sizeof(float)*2, ((float*)0)+ofs ); + for(int i=0;i<p_vertex_count;i++) { + b[ofs++]=p_uvs[i].x; + b[ofs++]=p_uvs[i].y; + } + + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glBufferSubData(GL_ARRAY_BUFFER,0,ofs*4,&b[0]); + + //bind the indices buffer. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); + + static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! + ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; i<p_vertex_count; i++) { + _draw_poly_indices[i] = p_indices[i]; + //OS::get_singleton()->print("ind: %d ", p_indices[i]); + }; + + //copy the data to GPU. + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, p_vertex_count * sizeof(uint16_t), &_draw_poly_indices[0]); + + //draw the triangles. + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_SHORT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#endif + _rinfo.ci_draw_commands++; }; @@ -8043,6 +8474,1091 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) { //canvas_transform = Variant(p_transform); } +RID RasterizerGLES2::canvas_light_occluder_create() { + + CanvasOccluder *co = memnew( CanvasOccluder ); + co->index_id=0; + co->vertex_id=0; + co->len=0; + + return canvas_occluder_owner.make_rid(co); +} + +void RasterizerGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) { + + CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!co); + + co->lines=p_lines; + + if (p_lines.size()!=co->len) { + + if (co->index_id) + glDeleteBuffers(1,&co->index_id); + if (co->vertex_id) + glDeleteBuffers(1,&co->vertex_id); + + co->index_id=0; + co->vertex_id=0; + co->len=0; + + } + + if (p_lines.size()) { + + + + DVector<float> geometry; + DVector<uint16_t> indices; + int lc = p_lines.size(); + + geometry.resize(lc*6); + indices.resize(lc*3); + + DVector<float>::Write vw=geometry.write(); + DVector<uint16_t>::Write iw=indices.write(); + + + DVector<Vector2>::Read lr=p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for(int i=0;i<lc/2;i++) { + + vw[i*12+0]=lr[i*2+0].x; + vw[i*12+1]=lr[i*2+0].y; + vw[i*12+2]=POLY_HEIGHT; + + vw[i*12+3]=lr[i*2+1].x; + vw[i*12+4]=lr[i*2+1].y; + vw[i*12+5]=POLY_HEIGHT; + + vw[i*12+6]=lr[i*2+1].x; + vw[i*12+7]=lr[i*2+1].y; + vw[i*12+8]=-POLY_HEIGHT; + + vw[i*12+9]=lr[i*2+0].x; + vw[i*12+10]=lr[i*2+0].y; + vw[i*12+11]=-POLY_HEIGHT; + + iw[i*6+0]=i*4+0; + iw[i*6+1]=i*4+1; + iw[i*6+2]=i*4+2; + + iw[i*6+3]=i*4+2; + iw[i*6+4]=i*4+3; + iw[i*6+5]=i*4+0; + + } + + //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush + + + if (!co->vertex_id) { + glGenBuffers(1,&co->vertex_id); + glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id); + glBufferData(GL_ARRAY_BUFFER,lc*6*sizeof(real_t),vw.ptr(),GL_STATIC_DRAW); + } else { + + glBindBuffer(GL_ARRAY_BUFFER,co->vertex_id); + glBufferSubData(GL_ARRAY_BUFFER,0,lc*6*sizeof(real_t),vw.ptr()); + + } + + glBindBuffer(GL_ARRAY_BUFFER,0); //unbind + + if (!co->index_id) { + + glGenBuffers(1,&co->index_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,lc*3*sizeof(uint16_t),iw.ptr(),GL_STATIC_DRAW); + } else { + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,co->index_id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,lc*3*sizeof(uint16_t),iw.ptr()); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //unbind + + co->len=lc; + + } + + + +} + +RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) { + + CanvasLightShadow *cls = memnew( CanvasLightShadow ); + if (p_width>max_texture_size) + p_width=max_texture_size; + + cls->size=p_width; + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &cls->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + // Create a render buffer + glGenRenderbuffers(1, &cls->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, cls->rbo); + + // Create a texture for storing the depth + glGenTextures(1, &cls->depth); + glBindTexture(GL_TEXTURE_2D, cls->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + cls->height=16; + + //print_line("ERROR? "+itos(glGetError())); + if ( read_depth_supported ) { + + // We'll use a depth texture to store the depths in the shadow map + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cls->size, cls->height, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + +#ifdef GLEW_ENABLED + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#endif + + // Attach the depth texture to FBO depth attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, cls->depth, 0); + +#ifdef GLEW_ENABLED + glDrawBuffer(GL_NONE); +#endif + + } else { + // We'll use a RGBA texture into which we pack the depth info + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + // Attach the RGBA texture to FBO color attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, cls->depth, 0); + cls->rgba=cls->depth; + + // Allocate 16-bit depth buffer + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); + + // Attach the render buffer as depth buffer - will be ignored + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, cls->rbo); + + + } + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + //printf("errnum: %x\n",status); +#ifdef GLEW_ENABLED + if (read_depth_supported) { + //glDrawBuffer(GL_BACK); + } +#endif + glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer); + DEBUG_TEST_ERROR("2D Shadow Buffer Init"); + ERR_FAIL_COND_V( status != GL_FRAMEBUFFER_COMPLETE, RID() ); + +#ifdef GLEW_ENABLED + if (read_depth_supported) { + //glDrawBuffer(GL_BACK); + } +#endif + + return canvas_light_shadow_owner.make_rid(cls); +} + +void RasterizerGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_buffer); + ERR_FAIL_COND(!cls); + + + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + if (!use_rgba_shadowmaps) + glColorMask(0, 0, 0, 0); + + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + canvas_shadow_shader.bind(); + + const int vp_height = 10; + + glViewport(0, 0, cls->size,cls->height); + _glClearDepth(1.0f); + glClearColor(1,1,1,1); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + VS::CanvasOccluderPolygonCullMode cull=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + + + for(int i=0;i<4;i++) { + + //make sure it remains orthogonal, makes easy to read angle later + + Transform light; + light.origin[0]=p_light_xform[2][0]; + light.origin[1]=p_light_xform[2][1]; + light.basis[0][0]=p_light_xform[0][0]; + light.basis[0][1]=p_light_xform[1][0]; + light.basis[1][0]=p_light_xform[0][1]; + light.basis[1][1]=p_light_xform[1][1]; + + //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + + /// p_near=1; + CameraMatrix projection; + { + real_t fov = 90; + real_t near = p_near; + real_t far = p_far; + real_t aspect = 1.0; + + real_t ymax = near * Math::tan( Math::deg2rad( fov * 0.5 ) ); + real_t ymin = - ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; + + projection.set_frustum( xmin, xmax, ymin, ymax, near, far ); + } + + Vector3 cam_target=Matrix3(Vector3(0,0,Math_PI*2*(i/4.0))).xform(Vector3(0,1,0)); + projection = projection * CameraMatrix(Transform().looking_at(cam_target,Vector3(0,0,-1)).affine_inverse()); + + //print_line("near: "+rtos(p_near)); + //print_line("far: "+rtos(p_far)); + //projection.set_perspective(60,size/float(vp_height),p_near,p_far); + + // CameraMatrix light_mat = projection * CameraMatrix(camera); + + canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX,projection); + canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX,light); + + if (i==0) + *p_xform_cache=projection; + + glViewport(0, (cls->height/4)*i, cls->size,cls->height/4); + + CanvasLightOccluderInstance *instance=p_occluders; + + while(instance) { + + CanvasOccluder *cc = canvas_occluder_owner.get(instance->polygon_buffer); + if (!cc || cc->len==0 || !(p_light_mask&instance->light_mask)) { + + instance=instance->next; + continue; + } + + canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX,instance->xform_cache); + if (cull!=instance->cull_cache) { + + cull=instance->cull_cache; + switch(cull) { + case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { + + glDisable(GL_CULL_FACE); + + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + } break; + case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + } break; + } + } +/* + if (i==0) { + for(int i=0;i<cc->lines.size();i++) { + Vector2 p = instance->xform_cache.xform(cc->lines.get(i)); + Plane pp(Vector3(p.x,p.y,0),1); + pp.normal = light.xform(pp.normal); + pp = projection.xform4(pp); + print_line(itos(i)+": "+pp.normal/pp.d); + //pp=light_mat.xform4(pp); + //print_line(itos(i)+": "+pp.normal/pp.d); + } + } +*/ + glBindBuffer(GL_ARRAY_BUFFER,cc->vertex_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,cc->index_id); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glDrawElements(GL_TRIANGLES,cc->len*3,GL_UNSIGNED_SHORT,0); + + + instance=instance->next; + } + + + } + + glDisableVertexAttribArray(VS::ARRAY_VERTEX); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + + if (shadow_filter==SHADOW_FILTER_ESM) { + //blur the buffer +#if 0 + //this is ignord, it did not make any difference.. + if (read_depth_supported) { + glDepthFunc(GL_ALWAYS); + } else { + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + } + glDisable(GL_CULL_FACE); + glViewport(0, 0, cls->size,cls->height); + + int passes=1; + CanvasLightShadow *blur = canvas_light_shadow_owner.get(canvas_shadow_blur); + + copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true); + copy_shader.bind(); + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,1); + copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1); + glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0); + + for(int i=0;i<passes;i++) { + + glBindFramebuffer(GL_FRAMEBUFFER, blur->fbo); + glActiveTexture(GL_TEXTURE0); + + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,cls->depth); + else + glBindTexture(GL_TEXTURE_2D,cls->rgba); + + + { + Vector2 src_sb_uv[4]={ + Vector2( 0, 1), + Vector2( 1, 1), + Vector2( 1, 0), + Vector2( 0, 0) + }; + static const Vector2 dst_pos[4]={ + Vector2(-1, 1), + Vector2( 1, 1), + Vector2( 1,-1), + Vector2(-1,-1) + }; + + + + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/cls->size); + _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv); + } + + glActiveTexture(GL_TEXTURE0); + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,blur->depth); + else + glBindTexture(GL_TEXTURE_2D,blur->rgba); + + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + { + float hlimit = float(cls->size) / blur->size; + //hlimit*=2.0; + Vector2 src_sb_uv[4]={ + Vector2( 0, 1), + Vector2( hlimit, 1), + Vector2( hlimit, 0), + Vector2( 0, 0) + }; + static const Vector2 dst_pos[4]={ + Vector2(-1, 1), + Vector2( 1, 1), + Vector2( 1,-1), + Vector2(-1,-1) + }; + + + copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,Vector2(1.0,1.0)/blur->size); + _draw_gui_primitive(4,dst_pos,NULL,src_sb_uv); + } + + } + copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false); + glDepthFunc(GL_LEQUAL); +#endif + } + + glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer); + glColorMask(1, 1, 1, 1); + + + +} + + +void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) { + + CanvasLight* light=p_lights_with_shadow; + + canvas_begin(); //reset + + int h = 10; + int w = viewport.width; + int ofs = h; + + //print_line(" debug lights "); + while(light) { + + // print_line("debug light"); + if (light->shadow_buffer.is_valid()) { + + // print_line("sb is valid"); + CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer); + if (sb) { + glActiveTexture(GL_TEXTURE0); + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,sb->depth); + else + glBindTexture(GL_TEXTURE_2D,sb->rgba); + _draw_textured_quad(Rect2(h,ofs,w-h*2,h),Rect2(0,0,sb->size,10),Size2(sb->size,10),false,false); + ofs+=h*2; + + } + } + + light=light->shadows_next_ptr; + } + +} + +void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) { + + if (p_flip==normal_flip) + return; + normal_flip=p_flip; + canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,normal_flip); +} + + +template<bool use_normalmap> +void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip) { + + int cc=p_item->commands.size(); + CanvasItem::Command **commands = p_item->commands.ptr(); + + + for(int i=0;i<cc;i++) { + + CanvasItem::Command *c=commands[i]; + + switch(c->type) { + case CanvasItem::Command::TYPE_LINE: { + + CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); + canvas_draw_line(line->from,line->to,line->color,line->width); + } break; + case CanvasItem::Command::TYPE_RECT: { + + CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); +// canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); +#if 0 + int flags=0; + + if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { + flags|=Rasterizer::CANVAS_RECT_REGION; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { + flags|=Rasterizer::CANVAS_RECT_TILE; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { + + flags|=Rasterizer::CANVAS_RECT_FLIP_H; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { + + flags|=Rasterizer::CANVAS_RECT_FLIP_V; + } +#else + + int flags=rect->flags; +#endif + if (use_normalmap) + _canvas_normal_set_flip(Vector2((flags&CANVAS_RECT_FLIP_H)?-1:1,(flags&CANVAS_RECT_FLIP_V)?-1:1)); + canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate); + + } break; + case CanvasItem::Command::TYPE_STYLE: { + + CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c); + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); + + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c); + canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width); + } break; + case CanvasItem::Command::TYPE_POLYGON: { + + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c); + canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); + + } break; + + case CanvasItem::Command::TYPE_POLYGON_PTR: { + + if (use_normalmap) + _canvas_normal_set_flip(Vector2(1,1)); + CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c); + canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false); + } break; + case CanvasItem::Command::TYPE_CIRCLE: { + + CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); + static const int numpoints=32; + Vector2 points[numpoints+1]; + points[numpoints]=circle->pos; + int indices[numpoints*3]; + + for(int i=0;i<numpoints;i++) { + + points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; + indices[i*3+0]=i; + indices[i*3+1]=(i+1)%numpoints; + indices[i*3+2]=numpoints; + } + canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); + //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); + } break; + case CanvasItem::Command::TYPE_TRANSFORM: { + + CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); + canvas_set_transform(transform->xform); + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); + canvas_set_blend_mode(bm->blend_mode); + + } break; + case CanvasItem::Command::TYPE_CLIP_IGNORE: { + + CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); + if (current_clip) { + + if (ci->ignore!=reclip) { + if (ci->ignore) { + + glDisable(GL_SCISSOR_TEST); + reclip=true; + } else { + + glEnable(GL_SCISSOR_TEST); + glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + reclip=false; + } + } + } + + + + } break; + } + } + +} + +void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) { + + if (canvas_shader.bind()) + rebind_texpixel_size=true; + + if (material->shader_version!=shader->version) { + //todo optimize uniforms + material->shader_version=shader->version; + } + + if (shader->has_texscreen && framebuffer.active) { + + int x = viewport.x; + int y = window_size.height-(viewport.height+viewport.y); + + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,max_texture_units-1); + glActiveTexture(GL_TEXTURE0+max_texture_units-1); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + if (framebuffer.scale==1 && !canvas_texscreen_used) { +#ifdef GLEW_ENABLED + glReadBuffer(GL_COLOR_ATTACHMENT0); +#endif + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); +// if (current_clip) { +// // print_line(" a clip "); +// } + + canvas_texscreen_used=true; + } + + glActiveTexture(GL_TEXTURE0); + + } + + if (shader->has_screen_uv) { + canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height)); + } + + + uses_texpixel_size=shader->uses_texpixel_size; + +} + +void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* shader) { + + //this can be optimized.. + int tex_id=1; + int idx=0; + for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { + + Map<StringName,Variant>::Element *F=material->shader_param.find(E->key()); + + if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) { + + RID rid; + if (F) { + rid=F->get(); + } + + if (!rid.is_valid()) { + + Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key()); + if (DT) { + rid=DT->get(); + } + } + + if (rid.is_valid()) { + + int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. + + glActiveTexture(GL_TEXTURE0+tex_id); + Texture *t=texture_owner.get(rid); + if (!t) + glBindTexture(GL_TEXTURE_2D,white_tex); + else + glBindTexture(t->target,t->tex_id); + + glUniform1i(loc,tex_id); + tex_id++; + } + } else { + Variant &v=F?F->get():E->get().default_value; + canvas_shader.set_custom_uniform(idx,v); + } + + idx++; + } + + if (tex_id>1) { + glActiveTexture(GL_TEXTURE0); + } + + if (shader->uses_time) { + canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0)); + draw_next_frame=true; + } + //if uses TIME - draw_next_frame=true + + +} + +void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) { + + + CanvasItem *current_clip=NULL; + Shader *shader_cache=NULL; + + bool rebind_shader=true; + + canvas_opacity=1.0; + canvas_use_modulate=p_modulate!=Color(1,1,1,1); + canvas_modulate=p_modulate; + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false); + + + bool reset_modulate=false; + bool prev_distance_field=false; + + while(p_item_list) { + + CanvasItem *ci=p_item_list; + + if (ci->vp_render) { + if (draw_viewport_func) { + draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect); + } + memdelete(ci->vp_render); + ci->vp_render=NULL; + canvas_last_material=NULL; + canvas_use_modulate=p_modulate!=Color(1,1,1,1); + canvas_modulate=p_modulate; + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false); + prev_distance_field=false; + rebind_shader=true; + reset_modulate=true; + + + } + + if (prev_distance_field!=ci->distance_field) { + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,ci->distance_field); + prev_distance_field=ci->distance_field; + rebind_shader=true; + } + + + if (current_clip!=ci->final_clip_owner) { + + current_clip=ci->final_clip_owner; + + //setup clip + if (current_clip) { + + glEnable(GL_SCISSOR_TEST); + glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + } else { + + glDisable(GL_SCISSOR_TEST); + } + } + + if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) { + + Rect2 rect; + int x,y,w,h; + + if (ci->copy_back_buffer->full) { + + x = viewport.x; + y = window_size.height-(viewport.height+viewport.y); + w = viewport.width; + h = viewport.height; + } else { + x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x; + y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y); + w = ci->copy_back_buffer->screen_rect.size.x; + h = ci->copy_back_buffer->screen_rect.size.y; + } + glActiveTexture(GL_TEXTURE0+max_texture_units-1); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + +#ifdef GLEW_ENABLED + glReadBuffer(GL_COLOR_ATTACHMENT0); +#endif + glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,w,h); +// if (current_clip) { +// // print_line(" a clip "); +// } + + canvas_texscreen_used=true; + glActiveTexture(GL_TEXTURE0); + } + + + + + //begin rect + CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci; + CanvasItemMaterial *material = material_owner->material; + + if (material!=canvas_last_material || rebind_shader) { + + Shader *shader = NULL; + if (material && material->shader.is_valid()) { + shader = shader_owner.get(material->shader); + if (shader && !shader->valid) { + shader=NULL; + } + } + + shader_cache=shader; + + if (shader) { + canvas_shader.set_custom_shader(shader->custom_code_id); + _canvas_item_setup_shader_params(material,shader); + } else { + shader_cache=NULL; + canvas_shader.set_custom_shader(0); + canvas_shader.bind(); + uses_texpixel_size=false; + + } + + + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + if (canvas_use_modulate) + reset_modulate=true; + canvas_last_material=material; + rebind_shader=false; + } + + if (material && shader_cache) { + + _canvas_item_setup_shader_uniforms(material,shader_cache); + } + + bool unshaded = material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED; + + if (unshaded) { + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1)); + reset_modulate=true; + } else if (reset_modulate) { + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate); + reset_modulate=false; + } + + + + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + + + bool reclip=false; + + if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { + + switch(ci->blend_mode) { + + case VS::MATERIAL_BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + } break; + case VS::MATERIAL_BLEND_MODE_ADD: { + + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + } break; + case VS::MATERIAL_BLEND_MODE_SUB: { + + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case VS::MATERIAL_BLEND_MODE_MUL: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_DST_COLOR,GL_ZERO); + } break; + case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); + } break; + + } + + canvas_blend_mode=ci->blend_mode; + } + + canvas_opacity = ci->final_opacity; + + + if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT))) + _canvas_item_render_commands<false>(ci,current_clip,reclip); + + if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) { + + CanvasLight *light = p_light; + bool light_used=false; + VS::CanvasLightMode mode=VS::CANVAS_LIGHT_MODE_ADD; + + + while(light) { + + if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) { + + //intersects this light + + if (!light_used || mode!=light->mode) { + + mode=light->mode; + + switch(mode) { + + case VS::CANVAS_LIGHT_MODE_ADD: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + + } break; + case VS::CANVAS_LIGHT_MODE_SUB: { + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBlendFunc(GL_SRC_ALPHA,GL_ONE); + } break; + case VS::CANVAS_LIGHT_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + } break; + } + + } + + if (!light_used) { + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,true); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false); + light_used=true; + normal_flip=Vector2(1,1); + + } + + bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask&light->item_shadow_mask; + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,has_shadow); + + bool light_rebind = canvas_shader.bind(); + + if (light_rebind) { + + if (material && shader_cache) { + _canvas_item_setup_shader_params(material,shader_cache); + _canvas_item_setup_shader_uniforms(material,shader_cache); + } + + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + if (canvas_use_modulate) + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate); + canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1)); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE,1.0/light->shadow_buffer_size); + + + } + + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a)); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse()); + + if (has_shadow) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer); + glActiveTexture(GL_TEXTURE0+max_texture_units-3); + if (read_depth_supported) + glBindTexture(GL_TEXTURE_2D,cls->depth); + else + glBindTexture(GL_TEXTURE_2D,cls->rgba); + + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); + + } + + + glActiveTexture(GL_TEXTURE0+max_texture_units-2); + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2); + Texture *t = texture_owner.get(light->texture); + if (!t) { + glBindTexture(GL_TEXTURE_2D,white_tex); + } else { + + glBindTexture(t->target,t->tex_id); + } + + glActiveTexture(GL_TEXTURE0); + _canvas_item_render_commands<true>(ci,current_clip,reclip); //redraw using light + + } + + light=light->next_ptr; + } + + if (light_used) { + + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,false); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,false); + + canvas_shader.bind(); + + if (material && shader_cache) { + _canvas_item_setup_shader_params(material,shader_cache); + _canvas_item_setup_shader_uniforms(material,shader_cache); + } + + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + if (canvas_use_modulate) + canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate); + + glBlendEquation(GL_FUNC_ADD); + if (current_rt && current_rt_transparent) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + } + + + } + + if (reclip) { + + glEnable(GL_SCISSOR_TEST); + glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)), + current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height); + } + + + + p_item_list=p_item_list->next; + } + + if (current_clip) { + glDisable(GL_SCISSOR_TEST); + } + +} + /* ENVIRONMENT */ RID RasterizerGLES2::environment_create() { @@ -8115,6 +9631,78 @@ Variant RasterizerGLES2::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + + +RID RasterizerGLES2::sampled_light_dp_create(int p_width,int p_height) { + + SampledLight *slight = memnew(SampledLight); + slight->w=p_width; + slight->h=p_height; + slight->multiplier=1.0; + slight->is_float=float_linear_supported; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1,&slight->texture); + glBindTexture(GL_TEXTURE_2D, slight->texture); +// for debug, but glitchy +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + if (slight->is_float) { +#ifdef GLEW_ENABLED + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_FLOAT,NULL); +#endif + } else { + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p_width, p_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + } + + return sampled_light_owner.make_rid(slight); +} + +void RasterizerGLES2::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + SampledLight *slight = sampled_light_owner.get(p_sampled_light); + ERR_FAIL_COND(!slight); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, slight->texture); + + if (slight->is_float) { + +#ifdef GLEW_ENABLED + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#else + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_FLOAT,p_data); +#endif + + } else { + //convert to bytes + uint8_t *tex8 = (uint8_t*)alloca(slight->w*slight->h*4); + const float* src=(const float*)p_data; + + for(int i=0;i<slight->w*slight->h*4;i++) { + + tex8[i]=Math::fast_ftoi(CLAMP(src[i]*255.0,0.0,255.0)); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0,0,0,slight->w, slight->h, GL_RGBA, GL_UNSIGNED_BYTE,p_data); + } + + slight->multiplier=p_multiplier; + +} + /*MISC*/ bool RasterizerGLES2::is_texture(const RID& p_rid) const { @@ -8164,6 +9752,11 @@ bool RasterizerGLES2::is_environment(const RID& p_rid) const { } bool RasterizerGLES2::is_shader(const RID& p_rid) const { + return shader_owner.owns(p_rid); +} + +bool RasterizerGLES2::is_canvas_light_occluder(const RID& p_rid) const { + return false; } @@ -8334,7 +9927,37 @@ void RasterizerGLES2::free(const RID& p_rid) { memdelete(render_target->texture_ptr); render_target_owner.free(p_rid); memdelete( render_target ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + glDeleteTextures(1,&sampled_light->texture); + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + } else if (canvas_occluder_owner.owns(p_rid)) { + + + CanvasOccluder *co = canvas_occluder_owner.get(p_rid); + if (co->index_id) + glDeleteBuffers(1,&co->index_id); + if (co->vertex_id) + glDeleteBuffers(1,&co->vertex_id); + canvas_occluder_owner.free(p_rid); + memdelete(co); + + } else if (canvas_light_shadow_owner.owns(p_rid)) { + + CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid); + glDeleteFramebuffers(1,&cls->fbo); + glDeleteRenderbuffers(1,&cls->rbo); + glDeleteTextures(1,&cls->depth); + //if (!read_depth_supported) { + // glDeleteTextures(1,&cls->rgba); + //} + + canvas_light_shadow_owner.free(p_rid); + memdelete(cls); }; } @@ -8450,7 +10073,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) { //printf("errnum: %x\n",status); #ifdef GLEW_ENABLED if (p_use_depth) { - glDrawBuffer(GL_BACK); + //glDrawBuffer(GL_BACK); } #endif glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -8459,7 +10082,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) { #ifdef GLEW_ENABLED if (p_use_depth) { - glDrawBuffer(GL_BACK); + //glDrawBuffer(GL_BACK); } #endif @@ -8837,6 +10460,62 @@ void RasterizerGLES2::_update_blur_buffer() { } #endif + + +bool RasterizerGLES2::_test_depth_shadow_buffer() { + + + int size=16; + + GLuint fbo; + GLuint rbo; + GLuint depth; + + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Create a render buffer + glGenRenderbuffers(1, &rbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + + // Create a texture for storing the depth + glGenTextures(1, &depth); + glBindTexture(GL_TEXTURE_2D, depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Remove artifact on the edges of the shadowmap + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + + // We'll use a depth texture to store the depths in the shadow map + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + +#ifdef GLEW_ENABLED + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#endif + + // Attach the depth texture to FBO depth attachment point + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, depth, 0); + + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + glDeleteFramebuffers(1,&fbo); + glDeleteRenderbuffers(1,&rbo); + glDeleteTextures(1,&depth); + + return status == GL_FRAMEBUFFER_COMPLETE; + +} + void RasterizerGLES2::init() { #ifdef GLEW_ENABLED @@ -8869,10 +10548,12 @@ void RasterizerGLES2::init() { material_shader.init(); canvas_shader.init(); copy_shader.init(); + canvas_shadow_shader.init(); #ifdef GLEW_ENABLED material_shader.set_conditional(MaterialShaderGLES2::USE_GLES_OVER_GL,true); canvas_shader.set_conditional(CanvasShaderGLES2::USE_GLES_OVER_GL,true); + canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_GLES_OVER_GL,true); copy_shader.set_conditional(CopyShaderGLES2::USE_GLES_OVER_GL,true); #endif @@ -8894,9 +10575,6 @@ void RasterizerGLES2::init() { //glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - skinned_buffer_size = GLOBAL_DEF("rasterizer/skinned_buffer_size",DEFAULT_SKINNED_BUFFER_SIZE); - skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size ); - glGenTextures(1, &white_tex); unsigned char whitetexdata[8*8*3]; for(int i=0;i<8*8*3;i++) { @@ -8910,7 +10588,7 @@ void RasterizerGLES2::init() { #ifdef GLEW_ENABLED - read_depth_supported=true; + pvr_supported=false; etc_supported=false; use_depth24 =true; @@ -8926,6 +10604,13 @@ void RasterizerGLES2::init() { latc_supported=true; s3tc_srgb_supported=true; use_anisotropic_filter=true; + float_linear_supported=true; + float_supported=true; + + read_depth_supported=_test_depth_shadow_buffer(); + use_rgba_shadowmaps=!read_depth_supported; + //print_line("read depth support? "+itos(read_depth_supported)); + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level); anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0))); #ifdef OSX_ENABLED @@ -8970,7 +10655,10 @@ void RasterizerGLES2::init() { GLint vtf; glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,&vtf); - use_hw_skeleton_xform=vtf>0 && extensions.has("GL_OES_texture_float"); + float_supported = extensions.has("GL_OES_texture_float"); + use_hw_skeleton_xform=vtf>0 && float_supported; + float_linear_supported = extensions.has("GL_OES_texture_float_linear"); + //if (extensions.has("GL_QCOM_tiled_rendering")) // use_hw_skeleton_xform=false; GLint mva; @@ -9008,9 +10696,12 @@ void RasterizerGLES2::init() { - + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units); + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_texture_size); //read_depth_supported=false; + canvas_shadow_blur = canvas_light_shadow_buffer_create(max_texture_size); + { //shadowmaps OS::VideoMode vm=OS::get_singleton()->get_video_mode(); @@ -9032,6 +10723,7 @@ void RasterizerGLES2::init() { //material_shader material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps); + canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps); } @@ -9040,6 +10732,7 @@ void RasterizerGLES2::init() { shadow_mat_ptr = material_owner.get(shadow_material); overdraw_material = create_overdraw_debug_material(); copy_shader.set_conditional(CopyShaderGLES2::USE_8BIT_HDR,!use_fp16_fb); + canvas_shader.set_conditional(CanvasShaderGLES2::USE_DEPTH_SHADOWS,read_depth_supported); canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false)); @@ -9053,19 +10746,29 @@ void RasterizerGLES2::init() { glGenBuffers(1,&gui_quad_buffer); glBindBuffer(GL_ARRAY_BUFFER,gui_quad_buffer); - glBufferData(GL_ARRAY_BUFFER,128,NULL,GL_DYNAMIC_DRAW); +#ifdef GLES_NO_CLIENT_ARRAYS //WebGL specific implementation. + glBufferData(GL_ARRAY_BUFFER, 8 * MAX_POLYGON_VERTICES,NULL,GL_DYNAMIC_DRAW); +#else + glBufferData(GL_ARRAY_BUFFER,128,NULL,GL_DYNAMIC_DRAW); +#endif glBindBuffer(GL_ARRAY_BUFFER,0); //unbind +#ifdef GLES_NO_CLIENT_ARRAYS //webgl indices buffer + glGenBuffers(1, &indices_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 16*1024, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// unbind +#endif + using_canvas_bg=false; _update_framebuffer(); DEBUG_TEST_ERROR("Initializing"); } void RasterizerGLES2::finish() { - - memdelete_arr(skinned_buffer); + free(canvas_shadow_blur); } int RasterizerGLES2::get_render_info(VS::RenderInfo p_info) { @@ -9345,10 +11048,29 @@ RasterizerGLES2* RasterizerGLES2::get_singleton() { return _singleton; }; +int RasterizerGLES2::RenderList::max_elements=RenderList::DEFAULT_MAX_ELEMENTS; + RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,bool p_default_fragment_lighting,bool p_use_reload_hooks) { _singleton = this; + RenderList::max_elements=GLOBAL_DEF("rasterizer/max_render_elements",(int)RenderList::DEFAULT_MAX_ELEMENTS); + if (RenderList::max_elements>64000) + RenderList::max_elements=64000; + if (RenderList::max_elements<1024) + RenderList::max_elements=1024; + + opaque_render_list.init(); + alpha_render_list.init(); + + skinned_buffer_size = GLOBAL_DEF("rasterizer/skeleton_buffer_size_kb",DEFAULT_SKINNED_BUFFER_SIZE); + if (skinned_buffer_size<256) + skinned_buffer_size=256; + if (skinned_buffer_size>16384) + skinned_buffer_size=16384; + skinned_buffer_size*=1024; + skinned_buffer = memnew_arr( uint8_t, skinned_buffer_size ); + keep_copies=p_keep_ram_copy; use_reload_hooks=p_use_reload_hooks; pack_arrays=p_compress_arrays; @@ -9392,6 +11114,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo RasterizerGLES2::~RasterizerGLES2() { + memdelete_arr(skinned_buffer); }; diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index dc2e22d240..a694571452 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -31,6 +31,8 @@ #include "servers/visual/rasterizer.h" +#define MAX_POLYGON_VERTICES 4096 //used for WebGL canvas_draw_polygon call. + #ifdef GLES2_ENABLED #include "image.h" @@ -51,6 +53,7 @@ #include "drivers/gles2/shaders/material.glsl.h" #include "drivers/gles2/shaders/canvas.glsl.h" +#include "drivers/gles2/shaders/canvas_shadow.glsl.h" #include "drivers/gles2/shaders/blur.glsl.h" #include "drivers/gles2/shaders/copy.glsl.h" #include "drivers/gles2/shader_compiler_gles2.h" @@ -65,7 +68,7 @@ class RasterizerGLES2 : public Rasterizer { MAX_SCENE_LIGHTS=2048, LIGHT_SPOT_BIT=0x80, - DEFAULT_SKINNED_BUFFER_SIZE = 2048 * 1024, // 10k vertices + DEFAULT_SKINNED_BUFFER_SIZE = 2048, // 10k vertices MAX_HW_LIGHTS = 1, }; @@ -86,6 +89,8 @@ class RasterizerGLES2 : public Rasterizer { bool use_shadow_mapping; bool use_fp16_fb; bool srgb_supported; + bool float_supported; + bool float_linear_supported; ShadowFilterTechnique shadow_filter; @@ -104,7 +109,7 @@ class RasterizerGLES2 : public Rasterizer { Vector<float> skel_default; - Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed); + Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed); class RenderTarget; @@ -117,6 +122,7 @@ class RasterizerGLES2 : public Rasterizer { GLenum target; GLenum gl_format_cache; + GLenum gl_internal_format_cache; int gl_components_cache; int data_size; //original data size, useful for retrieving back bool has_alpha; @@ -188,10 +194,13 @@ class RasterizerGLES2 : public Rasterizer { bool writes_vertex; bool uses_discard; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; Map<StringName,ShaderLanguage::Uniform> uniforms; StringName first_texture; + Map<StringName,RID> default_textures; SelfList<Shader> dirty_list; @@ -210,6 +219,7 @@ class RasterizerGLES2 : public Rasterizer { writes_vertex=false; uses_discard=false; uses_time=false; + uses_normal=false; } @@ -237,8 +247,9 @@ class RasterizerGLES2 : public Rasterizer { struct UniformData { + bool inuse; bool istexture; - Variant value; + Variant value; int index; }; @@ -668,6 +679,7 @@ class RasterizerGLES2 : public Rasterizer { bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; bg_param[VS::ENV_BG_PARAM_SCALE]=1.0; bg_param[VS::ENV_BG_PARAM_GLOW]=0.0; + bg_param[VS::ENV_BG_PARAM_CANVAS_MAX_LAYER]=0; for(int i=0;i<VS::ENV_FX_MAX;i++) fx_enabled[i]=false; @@ -704,6 +716,18 @@ class RasterizerGLES2 : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + + struct SampledLight { + + int w,h; + GLuint texture; + float multiplier; + bool is_float; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + + struct ViewportData { //1x1 fbo+texture for storing previous HDR value @@ -796,25 +820,31 @@ class RasterizerGLES2 : public Rasterizer { bool current_depth_mask; VS::MaterialBlendMode current_blend_mode; bool use_fast_texture_filter; + int max_texture_size; bool fragment_lighting; RID shadow_material; Material *shadow_mat_ptr; + int max_texture_units; GLuint base_framebuffer; GLuint gui_quad_buffer; + GLuint indices_buffer; + struct RenderList { enum { - MAX_ELEMENTS=4096, + DEFAULT_MAX_ELEMENTS=4096, MAX_LIGHTS=4, SORT_FLAG_SKELETON=1, SORT_FLAG_INSTANCING=2, }; + static int max_elements; + struct Element { @@ -847,8 +877,8 @@ class RasterizerGLES2 : public Rasterizer { }; - Element _elements[MAX_ELEMENTS]; - Element *elements[MAX_ELEMENTS]; + Element *_elements; + Element **elements; int element_count; void clear() { @@ -983,17 +1013,28 @@ class RasterizerGLES2 : public Rasterizer { } _FORCE_INLINE_ Element* add_element() { - if (element_count>MAX_ELEMENTS) + if (element_count>=max_elements) return NULL; elements[element_count]=&_elements[element_count]; return elements[element_count++]; } - RenderList() { + void init() { element_count = 0; - for (int i=0;i<MAX_ELEMENTS;i++) + elements=memnew_arr(Element*,max_elements); + _elements=memnew_arr(Element,max_elements); + for (int i=0;i<max_elements;i++) elements[i]=&_elements[i]; // assign elements + + } + + RenderList() { + + } + ~RenderList() { + memdelete_arr(elements); + memdelete_arr(_elements); } }; @@ -1071,6 +1112,8 @@ class RasterizerGLES2 : public Rasterizer { void _debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,Point2& ofs); void _debug_shadows(); void _debug_luminances(); + void _debug_samplers(); + /***********/ @@ -1090,6 +1133,7 @@ class RasterizerGLES2 : public Rasterizer { bool active; int blur_size; + struct Blur { GLuint fbo; @@ -1122,6 +1166,7 @@ class RasterizerGLES2 : public Rasterizer { void _process_glow_and_bloom(); //void _update_blur_buffer(); + /*********/ /* FRAME */ /*********/ @@ -1140,6 +1185,45 @@ class RasterizerGLES2 : public Rasterizer { } _rinfo; + /*******************/ + /* CANVAS OCCLUDER */ + /*******************/ + + + struct CanvasOccluder { + + GLuint vertex_id; // 0 means, unconfigured + GLuint index_id; // 0 means, unconfigured + DVector<Vector2> lines; + int len; + }; + + RID_Owner<CanvasOccluder> canvas_occluder_owner; + + /***********************/ + /* CANVAS LIGHT SHADOW */ + /***********************/ + + + struct CanvasLightShadow { + + int size; + int height; + GLuint fbo; + GLuint rbo; + GLuint depth; + GLuint rgba; //for older devices + + GLuint blur; + + }; + + RID_Owner<CanvasLightShadow> canvas_light_shadow_owner; + + RID canvas_shadow_blur; + + /* ETC */ + RenderTarget *current_rt; bool current_rt_transparent; bool current_rt_vflip; @@ -1149,6 +1233,17 @@ class RasterizerGLES2 : public Rasterizer { GLuint white_tex; RID canvas_tex; float canvas_opacity; + Color canvas_modulate; + bool canvas_use_modulate; + bool uses_texpixel_size; + bool rebind_texpixel_size; + Transform canvas_transform; + CanvasItemMaterial *canvas_last_material; + bool canvas_texscreen_used; + Vector2 normal_flip; + _FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip); + + _FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture); VS::MaterialBlendMode canvas_blend_mode; @@ -1167,6 +1262,7 @@ class RasterizerGLES2 : public Rasterizer { void _process_hdr(); void _draw_tex_bg(); + bool using_canvas_bg; Size2 window_size; VS::ViewportRect viewport; double last_time; @@ -1178,21 +1274,24 @@ class RasterizerGLES2 : public Rasterizer { VS::ScenarioDebugMode current_debug; RID overdraw_material; + mutable MaterialShaderGLES2 material_shader; - CanvasShaderGLES2 canvas_shader; + mutable CanvasShaderGLES2 canvas_shader; BlurShaderGLES2 blur_shader; CopyShaderGLES2 copy_shader; + mutable CanvasShadowShaderGLES2 canvas_shadow_shader; mutable ShaderCompilerGLES2 shader_precompiler; void _draw_primitive(int p_points, const Vector3 *p_vertices, const Vector3 *p_normals, const Color* p_colors, const Vector3 *p_uvs,const Plane *p_tangents=NULL,int p_instanced=1); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_gui_primitive2(int p_points, const Vector2 *p_vertices, const Color* p_colors, const Vector2 *p_uvs, const Vector2 *p_uvs2); - void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip=false, bool p_v_flip=false ); + void _draw_textured_quad(const Rect2& p_rect, const Rect2& p_src_region, const Size2& p_tex_size,bool p_h_flip=false, bool p_v_flip=false, bool p_transpose=false ); void _draw_quad(const Rect2& p_rect); void _copy_screen_quad(); void _copy_to_texscreen(); + bool _test_depth_shadow_buffer(); Vector3 chunk_vertex; Vector3 chunk_normal; @@ -1203,6 +1302,10 @@ class RasterizerGLES2 : public Rasterizer { GLuint tc0_id_cache; GLuint tc0_idx; + template<bool use_normalmap> + _FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip); + _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* p_shader); + _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material,Shader* p_shader); public: /* TEXTURE API */ @@ -1237,6 +1340,10 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); /* COMMON MATERIAL API */ @@ -1499,6 +1606,8 @@ public: /* CANVAS API */ + virtual void begin_canvas_bg(); + virtual void canvas_begin(); virtual void canvas_disable_blending(); @@ -1514,6 +1623,19 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); virtual void canvas_set_transform(const Matrix32& p_transform); + virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light); + virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow); + + /* CANVAS LIGHT SHADOW */ + + //buffer + virtual RID canvas_light_shadow_buffer_create(int p_width); + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache); + + //occluder + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines); + /* ENVIRONMENT */ @@ -1531,6 +1653,9 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier); /*MISC*/ @@ -1548,6 +1673,8 @@ public: virtual bool is_environment(const RID& p_rid) const; virtual bool is_shader(const RID& p_rid) const; + virtual bool is_canvas_light_occluder(const RID& p_rid) const; + virtual void free(const RID& p_rid); virtual void init(); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 50b63e1aa0..69bd269948 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -61,6 +61,7 @@ static String _typestr(SL::DataType p_type) { case SL::TYPE_VEC2: return "vec2"; case SL::TYPE_VEC3: return "vec3"; case SL::TYPE_VEC4: return "vec4"; + case SL::TYPE_MAT2: return "mat2"; case SL::TYPE_MAT3: return "mat3"; case SL::TYPE_MAT4: return "mat4"; case SL::TYPE_TEXTURE: return "sampler2D"; @@ -131,6 +132,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a SL::BlockNode *bnode=(SL::BlockNode*)p_node; //variables + code+="{"ENDL; for(Map<StringName,SL::DataType>::Element *E=bnode->variables.front();E;E=E->next()) { code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";"ENDL; @@ -141,10 +143,12 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";"ENDL; } + code+="}"ENDL; } break; case SL::Node::TYPE_VARIABLE: { SL::VariableNode *vnode=(SL::VariableNode*)p_node; + if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) { if (vnode->name==vname_vertex && p_assign_left) { @@ -171,6 +175,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } + + + if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) { if (vnode->name==vname_discard) { @@ -212,6 +219,58 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } } + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX) { + + if (vnode->name==vname_var1_interp) { + flags->use_var1_interp=true; + } + if (vnode->name==vname_var2_interp) { + flags->use_var2_interp=true; + } + if (vnode->name==vname_world_vec) { + uses_worldvec=true; + } + + } + + + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT) { + + + if (vnode->name==vname_texpixel_size) { + uses_texpixel_size=true; + } + if (vnode->name==vname_normal) { + uses_normal=true; + } + + if (vnode->name==vname_screen_uv) { + uses_screen_uv=true; + } + + if (vnode->name==vname_var1_interp) { + flags->use_var1_interp=true; + } + if (vnode->name==vname_var2_interp) { + flags->use_var2_interp=true; + } + } + + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT) { + + if (vnode->name==vname_light) { + uses_light=true; + } + + if (vnode->name==vname_normal) { + uses_normal=true; + } + + if (vnode->name==vname_shadow) { + uses_shadow_color=true; + } + + } if (vnode->name==vname_time) { uses_time=true; @@ -229,6 +288,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a case SL::TYPE_VEC2: { Vector2 v = cnode->value; code="vec2("+_mknum(v.x)+", "+_mknum(v.y)+")"; } break; case SL::TYPE_VEC3: { Vector3 v = cnode->value; code="vec3("+_mknum(v.x)+", "+_mknum(v.y)+", "+_mknum(v.z)+")"; } break; case SL::TYPE_VEC4: { Plane v = cnode->value; code="vec4("+_mknum(v.normal.x)+", "+_mknum(v.normal.y)+", "+_mknum(v.normal.z)+", "+_mknum(v.d)+")"; } break; + case SL::TYPE_MAT2: { Matrix32 x = cnode->value; code="mat2( vec2("+_mknum(x[0][0])+", "+_mknum(x[0][1])+"), vec2("+_mknum(x[1][0])+", "+_mknum(x[1][1])+"))"; } break; case SL::TYPE_MAT3: { Matrix3 x = cnode->value; code="mat3( vec3("+_mknum(x.get_axis(0).x)+", "+_mknum(x.get_axis(0).y)+", "+_mknum(x.get_axis(0).z)+"), vec3("+_mknum(x.get_axis(1).x)+", "+_mknum(x.get_axis(1).y)+", "+_mknum(x.get_axis(1).z)+"), vec3("+_mknum(x.get_axis(2).x)+", "+_mknum(x.get_axis(2).y)+", "+_mknum(x.get_axis(2).z)+"))"; } break; case SL::TYPE_MAT4: { Transform x = cnode->value; code="mat4( vec4("+_mknum(x.basis.get_axis(0).x)+", "+_mknum(x.basis.get_axis(0).y)+", "+_mknum(x.basis.get_axis(0).z)+",0.0), vec4("+_mknum(x.basis.get_axis(1).x)+", "+_mknum(x.basis.get_axis(1).y)+", "+_mknum(x.basis.get_axis(1).z)+",0.0), vec4("+_mknum(x.basis.get_axis(2).x)+", "+_mknum(x.basis.get_axis(2).y)+", "+_mknum(x.basis.get_axis(2).z)+",0.0), vec4("+_mknum(x.origin.x)+", "+_mknum(x.origin.y)+", "+_mknum(x.origin.z)+",1.0))"; } break; default: code="<error: "+Variant::get_type_name(cnode->value.get_type())+" ("+itos(cnode->datatype)+">"; @@ -260,13 +320,13 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); - code=mul_l+"=(vec4("+mul_l+",1.0,1.0)*("+mul_r+")).xy"; + code=mul_l+"=(vec4("+mul_l+",0.0,1.0)*("+mul_r+")).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); - code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",1.0,1.0)).xy"; + code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",0.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT3) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); @@ -296,11 +356,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { - code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",1.0,1.0)).xyz"; + code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",0.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { - code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",1.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xyz"; + code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",0.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT3 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { @@ -357,7 +417,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } else if (callfunc=="texscreen") { //create the call to sample the screen, and clamp it uses_texscreen=true; - code="(texture2D( texscreen_tex, min(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_mult))).rgb"; + code="(texture2D( texscreen_tex, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_clamp.xy,texscreen_screen_clamp.zw))).rgb"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; } else if (callfunc=="texpos") { @@ -421,6 +481,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a m="[2]"; else if (mnode->name=="w") m="[3]"; + } else if (mnode->basetype==SL::TYPE_MAT2) { + if (mnode->name=="x") + m="[0]"; + else if (mnode->name=="y") + m="[1]"; } else if (mnode->basetype==SL::TYPE_MAT3) { if (mnode->name=="x") @@ -550,7 +615,11 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_light=false; uses_time=false; uses_normalmap=false; + uses_normal=false; + uses_texpixel_size=false; + uses_worldvec=false; vertex_code_writes_vertex=false; + uses_shadow_color=false; uniforms=r_uniforms; flags=&r_flags; r_flags.use_color_interp=false; @@ -560,6 +629,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.use_var1_interp=false; r_flags.use_var2_interp=false; r_flags.uses_normalmap=false; + r_flags.uses_normal=false; String error; int errline,errcol; @@ -582,6 +652,10 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_light=uses_light; r_flags.uses_time=uses_time; r_flags.uses_normalmap=uses_normalmap; + r_flags.uses_normal=uses_normal; + r_flags.uses_texpixel_size=uses_texpixel_size; + r_flags.uses_worldvec=uses_worldvec; + r_flags.uses_shadow_color=uses_shadow_color; r_code_line=code; r_globals_line=global_code; @@ -595,6 +669,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["vec2" ]= "vec2"; replace_table["vec3" ]= "vec3"; replace_table["vec4" ]= "vec4"; + replace_table["mat2" ]= "mat2"; replace_table["mat3" ]= "mat3"; replace_table["mat4" ]= "mat4"; replace_table["texture" ]= "sampler2D"; @@ -638,6 +713,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["cross" ]="cross"; replace_table["normalize"]= "normalize"; replace_table["reflect"]= "reflect"; + replace_table["refract"]= "refract"; replace_table["tex"]= "tex"; replace_table["texa"]= "texa"; replace_table["tex2"]= "tex2"; @@ -676,6 +752,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { //mode_replace_table[1]["POSITION"]="IN_POSITION"; mode_replace_table[1]["NORMAL"]="normal"; mode_replace_table[1]["TANGENT"]="tangent"; + mode_replace_table[1]["POSITION"]="gl_Position"; mode_replace_table[1]["BINORMAL"]="binormal"; mode_replace_table[1]["NORMALMAP"]="normalmap"; mode_replace_table[1]["NORMALMAP_DEPTH"]="normaldepth"; @@ -718,6 +795,52 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[2]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[2]["TIME"]="time"; + mode_replace_table[3]["SRC_VERTEX"]="src_vtx"; + mode_replace_table[3]["VERTEX"]="outvec.xy"; + mode_replace_table[3]["WORLD_VERTEX"]="outvec.xy"; + mode_replace_table[3]["UV"]="uv_interp"; + mode_replace_table[3]["COLOR"]="color_interp"; + mode_replace_table[3]["VAR1"]="var1_interp"; + mode_replace_table[3]["VAR2"]="var2_interp"; + mode_replace_table[3]["POINT_SIZE"]="gl_PointSize"; + mode_replace_table[3]["WORLD_MATRIX"]="modelview_matrix"; + mode_replace_table[3]["PROJECTION_MATRIX"]="projection_matrix"; + mode_replace_table[3]["EXTRA_MATRIX"]="extra_matrix"; + mode_replace_table[3]["TIME"]="time"; + + mode_replace_table[4]["POSITION"]="gl_Position"; + mode_replace_table[4]["NORMAL"]="normal"; + mode_replace_table[4]["UV"]="uv_interp"; + mode_replace_table[4]["SRC_COLOR"]="color_interp"; + mode_replace_table[4]["COLOR"]="color"; + mode_replace_table[4]["TEXTURE"]="texture"; + mode_replace_table[4]["TEXTURE_PIXEL_SIZE"]="texpixel_size"; + mode_replace_table[4]["VAR1"]="var1_interp"; + mode_replace_table[4]["VAR2"]="var2_interp"; + mode_replace_table[4]["SCREEN_UV"]="screen_uv"; + mode_replace_table[4]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[4]["TIME"]="time"; + + mode_replace_table[5]["POSITION"]="gl_Position"; + mode_replace_table[5]["NORMAL"]="normal"; + mode_replace_table[5]["UV"]="uv_interp"; + mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["TEXTURE"]="texture"; + mode_replace_table[5]["TEXTURE_PIXEL_SIZE"]="texpixel_size"; + mode_replace_table[5]["VAR1"]="var1_interp"; + mode_replace_table[5]["VAR2"]="var2_interp"; + mode_replace_table[5]["LIGHT_VEC"]="light_vec"; + mode_replace_table[5]["LIGHT_HEIGHT"]="light_height"; + mode_replace_table[5]["LIGHT_COLOR"]="light"; + mode_replace_table[5]["LIGHT_UV"]="light_uv"; + mode_replace_table[5]["LIGHT"]="light_out"; + mode_replace_table[5]["SHADOW"]="shadow_color"; + mode_replace_table[5]["SCREEN_UV"]="screen_uv"; + mode_replace_table[5]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[5]["TIME"]="time"; + + + //mode_replace_table[2]["SCREEN_POS"]="SCREEN_POS"; //mode_replace_table[2]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE"; @@ -738,5 +861,9 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_light="LIGHT"; vname_time="TIME"; vname_normalmap="NORMALMAP"; + vname_normal="NORMAL"; + vname_texpixel_size="TEXTURE_PIXEL_SIZE"; + vname_world_vec="WORLD_VERTEX"; + vname_shadow="SHADOW"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 5012414c8b..87016fd968 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -51,7 +51,11 @@ private: bool uses_time; bool uses_screen_uv; bool uses_normalmap; + bool uses_normal; + bool uses_texpixel_size; + bool uses_worldvec; bool vertex_code_writes_vertex; + bool uses_shadow_color; Flags *flags; StringName vname_discard; @@ -68,6 +72,10 @@ private: StringName vname_light; StringName vname_time; StringName vname_normalmap; + StringName vname_normal; + StringName vname_texpixel_size; + StringName vname_world_vec; + StringName vname_shadow; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -79,7 +87,7 @@ private: String replace_string(const StringName& p_string); - Map<StringName,StringName> mode_replace_table[3]; + Map<StringName,StringName> mode_replace_table[9]; Map<StringName,StringName> replace_table; public: @@ -101,6 +109,10 @@ public: bool use_var2_interp; bool uses_light; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; + bool uses_worldvec; + bool uses_shadow_color; }; Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL); diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub index c665cf9036..9679223b16 100644 --- a/drivers/gles2/shaders/SCsub +++ b/drivers/gles2/shaders/SCsub @@ -3,6 +3,7 @@ Import('env') if env['BUILDERS'].has_key('GLSL120GLES'): env.GLSL120GLES('material.glsl'); env.GLSL120GLES('canvas.glsl'); + env.GLSL120GLES('canvas_shadow.glsl'); env.GLSL120GLES('blur.glsl'); env.GLSL120GLES('copy.glsl'); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index f36741d586..c4f0847870 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -18,20 +18,81 @@ attribute highp vec2 uv_attrib; // attrib:4 varying vec2 uv_interp; varying vec4 color_interp; +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform highp mat4 light_matrix; +uniform highp mat4 light_local_matrix; +uniform vec2 light_pos; +varying vec4 light_uv_interp; + +#if defined(NORMAL_USED) +varying vec4 local_rot; +uniform vec2 normal_flip; +#endif + +#ifdef USE_SHADOWS +varying highp vec2 pos; +#endif + +#endif + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + //uniform bool snap_pixels; +VERTEX_SHADER_GLOBALS + void main() { color_interp = color_attrib; uv_interp = uv_attrib; - highp vec4 outvec = vec4(vertex, 1.0); - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; + highp vec4 outvec = vec4(vertex, 1.0); +{ + vec2 src_vtx=outvec.xy; +VERTEX_SHADER_CODE + +} +#if !defined(USE_WORLD_VEC) + outvec = extra_matrix * outvec; + outvec = modelview_matrix * outvec; +#endif + + + #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec.xy+0.5); #endif + + gl_Position = projection_matrix * outvec; + +#ifdef USE_LIGHTING + + light_uv_interp.xy = (light_matrix * outvec).xy; + light_uv_interp.zw =(light_local_matrix * outvec).xy; +#ifdef USE_SHADOWS + pos=outvec.xy; +#endif + +#if defined(NORMAL_USED) + local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x; + local_rot.zw=normalize( (modelview_matrix * ( extra_matrix * vec4(0.0,1.0,0.0,0.0) )).xy )*normal_flip.y; +#endif + +#endif + } [fragment] @@ -54,17 +115,268 @@ varying vec4 color_interp; #endif +#if defined(ENABLE_SCREEN_UV) + +uniform vec2 screen_uv_mult; + +#endif + +#if defined(ENABLE_TEXSCREEN) + +uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; +uniform sampler2D texscreen_tex; + +#endif + + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + +#if defined(USE_TIME) +uniform float time; +#endif + +#ifdef USE_MODULATE + +uniform vec4 modulate; + +#endif + +#ifdef USE_LIGHTING + +uniform sampler2D light_texture; +uniform vec4 light_color; +uniform float light_height; +varying vec4 light_uv_interp; + +#if defined(NORMAL_USED) +varying vec4 local_rot; +#endif + +#ifdef USE_SHADOWS + +uniform highp sampler2D shadow_texture; +uniform float shadow_attenuation; + +uniform highp mat4 shadow_matrix; +varying highp vec2 pos; +uniform float shadowpixel_size; + +#ifdef SHADOW_ESM +uniform float shadow_esm_multiplier; +#endif + +#endif + +#endif + +#if defined(USE_TEXPIXEL_SIZE) +uniform vec2 texpixel_size; +#endif + + +FRAGMENT_SHADER_GLOBALS + + void main() { vec4 color = color_interp; - +#if defined(NORMAL_USED) + vec3 normal = vec3(0.0,0.0,1.0); +#endif + +#ifdef USE_DISTANCE_FIELD + const float smoothing = 1.0/32.0; + float distance = texture2D(texture, uv_interp).a; + color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance); +#else color *= texture2D( texture, uv_interp ); +#endif + + +#if defined(ENABLE_SCREEN_UV) + vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; +#endif + + +{ +FRAGMENT_SHADER_CODE +} #ifdef DEBUG_ENCODED_32 highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ); color = vec4(vec3(enc32),1.0); #endif +#ifdef USE_MODULATE + + color*=modulate; +#endif + + +#ifdef USE_LIGHTING + + vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping + +#if defined(NORMAL_USED) + normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy; +#endif + + float att=1.0; + + vec2 light_uv = light_uv_interp.xy; + vec4 light = texture2D(light_texture,light_uv) * light_color; +#if defined(USE_LIGHT_SHADOW_COLOR) + vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); +#endif + +#if defined(USE_LIGHT_SHADER_CODE) +//light is written by the light shader +{ + vec4 light_out=light*color; +LIGHT_SHADER_CODE + color=light_out; +} + +#else + +#if defined(NORMAL_USED) + vec3 light_normal = normalize(vec3(light_vec,-light_height)); + light*=max(dot(-light_normal,normal),0.0); +#endif + + color*=light; +/* +#ifdef USE_NORMAL + color.xy=local_rot.xy;//normal.xy; + color.zw=vec2(0.0,1.0); +#endif +*/ + +//light shader code +#endif + + if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) { + color.a=0.0; //invisible + } else { + +#ifdef USE_SHADOWS + + float angle_to_light = -atan(light_vec.x,light_vec.y); + float PI = 3.14159265358979323846264; + /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays + float ang*/ + + float su,sz; + + float abs_angle = abs(angle_to_light); + vec2 point; + float sh; + if (abs_angle<45.0*PI/180.0) { + point = light_vec; + sh=0.0+(1.0/8.0); + } else if (abs_angle>135.0*PI/180.0) { + point = -light_vec; + sh = 0.5+(1.0/8.0); + } else if (angle_to_light>0.0) { + + point = vec2(light_vec.y,-light_vec.x); + sh = 0.25+(1.0/8.0); + } else { + + point = vec2(-light_vec.y,light_vec.x); + sh = 0.75+(1.0/8.0); + + } + + + highp vec4 s = shadow_matrix * highp vec4(point,0.0,1.0); + s.xyz/=s.w; + su=s.x*0.5+0.5; + sz=s.z*0.5+0.5; + + highp float shadow_attenuation=0.0; + +#ifdef USE_DEPTH_SHADOWS + +#define SHADOW_DEPTH(m_tex,m_uv) (texture2D((m_tex),(m_uv)).z) + +#else + +//#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) +#define SHADOW_DEPTH(m_tex,m_uv) dot(texture2D((m_tex),(m_uv)),vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ) + +#endif + + + +#ifdef SHADOW_PCF5 + + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation/=5.0; + +#endif + +#ifdef SHADOW_PCF13 + + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*3.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*4.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*5.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size*6.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*2.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*3.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*4.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*5.0,sh))<sz?0.0:1.0; + shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su-shadowpixel_size*6.0,sh))<sz?0.0:1.0; + shadow_attenuation/=13.0; + +#endif + +#ifdef SHADOW_ESM + + + { + float unnormalized = su/shadowpixel_size; + float fractional = fract(unnormalized); + unnormalized = floor(unnormalized); + float zc = SHADOW_DEPTH(shadow_texture,vec2((unnormalized-0.5)*shadowpixel_size,sh)); + float zn = SHADOW_DEPTH(shadow_texture,vec2((unnormalized+0.5)*shadowpixel_size,sh)); + float z = mix(zc,zn,fractional); + shadow_attenuation=clamp(exp(shadow_esm_multiplier* ( z - sz )),0.0,1.0); + } + +#endif + +#if !defined(SHADOW_PCF5) && !defined(SHADOW_PCF13) && !defined(SHADOW_ESM) + + shadow_attenuation = SHADOW_DEPTH(shadow_texture,vec2(su+shadowpixel_size,sh))<sz?0.0:1.0; + +#endif + +#if defined(USE_LIGHT_SHADOW_COLOR) + color=mix(shadow_color,color,shadow_attenuation); +#else + color*=shadow_attenuation; +#endif +//use shadows +#endif + } + +//use lighting +#endif // color.rgb*=color.a; gl_FragColor = color; diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl new file mode 100644 index 0000000000..40cf321dce --- /dev/null +++ b/drivers/gles2/shaders/canvas_shadow.glsl @@ -0,0 +1,62 @@ +[vertex] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +uniform highp mat4 projection_matrix; +uniform highp mat4 light_matrix; +uniform highp mat4 world_matrix; + +attribute highp vec3 vertex; // attrib:0 + +#ifndef USE_DEPTH_SHADOWS + +varying vec4 position_interp; + +#endif + + +void main() { + + gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0))); + +#ifndef USE_DEPTH_SHADOWS + position_interp = gl_Position; +#endif + +} + +[fragment] + +#ifdef USE_GLES_OVER_GL +#define mediump +#define highp +#else +precision mediump float; +precision mediump int; +#endif + +#ifndef USE_DEPTH_SHADOWS + +varying vec4 position_interp; + +#endif + +void main() { + +#ifdef USE_DEPTH_SHADOWS + +#else + highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; + highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); + comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); + gl_FragColor = comp; +#endif + +} + diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 44337e1197..38fb03ab5c 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -60,7 +60,7 @@ uniform float normal_mult; #ifdef USE_SKELETON attribute vec4 bone_indices; // attrib:6 attribute vec4 bone_weights; // attrib:7 -uniform highp sampler2D skeleton_matrices; // texunit:6 +uniform highp sampler2D skeleton_matrices; uniform highp float skeltex_pixel_size; #endif @@ -76,7 +76,7 @@ attribute highp vec4 instance_row3; // attrib:11 #ifdef USE_TEXTURE_INSTANCING attribute highp vec3 instance_uv; // attrib:6 -uniform highp sampler2D instance_matrices; // texunit:6 +uniform highp sampler2D instance_matrices; #endif @@ -595,8 +595,10 @@ uniform float time; varying highp vec3 ambient_octree_coords; uniform highp float ambient_octree_lattice_size; uniform highp vec2 ambient_octree_pix_size; +uniform highp vec2 ambient_octree_light_pix_size; uniform highp float ambient_octree_lattice_divide; uniform highp sampler2D ambient_octree_tex; +uniform highp sampler2D ambient_octree_light_tex; uniform float ambient_octree_multiplier; uniform int ambient_octree_steps; @@ -609,6 +611,12 @@ uniform float ambient_lightmap_multiplier; #endif +#ifdef ENABLE_AMBIENT_DP_SAMPLER + +uniform highp sampler2D ambient_dp_sampler; +uniform float ambient_dp_sampler_multiplier; + +#endif FRAGMENT_SHADER_GLOBALS @@ -771,6 +779,7 @@ uniform highp mat4 camera_inverse_transform; #if defined(ENABLE_TEXSCREEN) uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; uniform sampler2D texscreen_tex; #endif @@ -918,12 +927,12 @@ FRAGMENT_SHADER_CODE } //sample color - octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; + octant_uv=(octant_uv+0.5)*ambient_octree_light_pix_size; highp vec3 sub=(mod(ambient_octree_coords,ld)/ld); - octant_uv.xy+=sub.xy*ambient_octree_pix_size.xy; - vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb; - octant_uv.y+=ambient_octree_pix_size.y*2.0; - vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb; + octant_uv.xy+=sub.xy*ambient_octree_light_pix_size.xy; + vec3 col_up=texture2D(ambient_octree_light_tex,octant_uv).rgb; + octant_uv.y+=ambient_octree_light_pix_size.y*2.0; + vec3 col_down=texture2D(ambient_octree_light_tex,octant_uv).rgb; ambientmap_color=mix(col_up,col_down,sub.z)*ambient_octree_multiplier; ambientmap_color*=diffuse.rgb; @@ -934,6 +943,26 @@ FRAGMENT_SHADER_CODE +#ifdef ENABLE_AMBIENT_DP_SAMPLER + + vec3 ambientmap_color = vec3(0.0,0.0,0.0); + + { + + vec3 dp_normal = normalize((vec4(normal,0) * camera_inverse_transform).xyz); + vec2 ambient_uv = (dp_normal.xy / (1.0+abs(dp_normal.z)))*0.5+0.5; //dual paraboloid + ambient_uv.y*=0.5; + if (dp_normal.z<0) { + + ambient_uv.y=(0.5-ambient_uv.y)+0.5; + + } + + ambientmap_color = texture2D(ambient_dp_sampler,ambient_uv ).rgb * ambient_dp_sampler_multiplier; + ambientmap_color*=diffuse.rgb; + } + +#endif @@ -1186,7 +1215,7 @@ LIGHT_SHADER_CODE # if !defined(LIGHT_TYPE_DIRECTIONAL) && !defined(LIGHT_TYPE_OMNI) && !defined (LIGHT_TYPE_SPOT) //none #ifndef SHADELESS - diffuse.rgb=vec3(0.0,0.0,0.0); + diffuse.rgb=ambient_light *diffuse.rgb; #endif # endif @@ -1202,7 +1231,7 @@ LIGHT_SHADER_CODE vec3 ambient = const_light_mult*ambient_light*diffuse.rgb; # if defined(LIGHT_TYPE_OMNI) || defined (LIGHT_TYPE_SPOT) - ambient*=diffuse_interp.a; //attenuation affects ambient too +// ambient*=diffuse_interp.a; //attenuation affects ambient too # endif @@ -1224,7 +1253,7 @@ LIGHT_SHADER_CODE #endif -#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) +#if defined(ENABLE_AMBIENT_OCTREE) || defined(ENABLE_AMBIENT_LIGHTMAP) || defined(ENABLE_AMBIENT_DP_SAMPLER) diffuse.rgb+=ambientmap_color; #endif diff --git a/drivers/mpc/audio_stream_mpc.cpp b/drivers/mpc/audio_stream_mpc.cpp index e1f9aacf5f..cd8125c9af 100644 --- a/drivers/mpc/audio_stream_mpc.cpp +++ b/drivers/mpc/audio_stream_mpc.cpp @@ -8,6 +8,7 @@ Error AudioStreamMPC::_open_file() { f=NULL; } Error err; + //printf("mpc open file %ls\n", file.c_str()); f=FileAccess::open(file,FileAccess::READ,&err); if (err) { @@ -16,9 +17,10 @@ Error AudioStreamMPC::_open_file() { return err; } - f->seek_end(0); - streamlen=f->get_pos(); - f->seek(0); + //printf("file size is %i\n", f->get_len()); + //f->seek_end(0); + streamlen=f->get_len(); + //f->seek(0); if (streamlen<=0) { memdelete(f); f=NULL; @@ -275,7 +277,7 @@ void AudioStreamMPC::stop() { } bool AudioStreamMPC::is_playing() const { - return active; + return active || (get_total() - get_todo() -1 > 0); } void AudioStreamMPC::set_paused(bool p_paused) { diff --git a/drivers/ogg/SCsub b/drivers/ogg/SCsub index 5cdc3ea1c0..dd59890064 100644 --- a/drivers/ogg/SCsub +++ b/drivers/ogg/SCsub @@ -6,5 +6,6 @@ ogg_sources = [ "ogg/framing.c", ] -env.drivers_sources+=ogg_sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources+=ogg_sources diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 316397ed80..6fc20f36f7 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -102,6 +102,9 @@ Error ImageLoaderPNG::_load_image(void *rf_up,png_rw_ptr p_func,Image *p_image) png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); + png_textp t; + //https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp + //png_get_text(png,info,) /* printf("Image width:%i\n", width); printf("Image Height:%i\n", height); diff --git a/drivers/png/pngpriv.h b/drivers/png/pngpriv.h index 67e486c577..56532f4eeb 100644 --- a/drivers/png/pngpriv.h +++ b/drivers/png/pngpriv.h @@ -341,7 +341,11 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strlen lstrlenA +# ifdef WINRT_ENABLED +# define png_strlen strlen +# else +# define png_strlen lstrlenA +# endif # define png_memcmp memcmp # define png_memcpy CopyMemory # define png_memset memset diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index a898f6e618..462051b21e 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -30,6 +30,8 @@ #include "scene/resources/texture.h" #include "drivers/png/png.h" #include "os/file_access.h" +#include "globals.h" +#include "core/image.h" static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { @@ -45,12 +47,56 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t ERR_EXPLAIN("Can't save empty texture as PNG"); ERR_FAIL_COND_V(!texture->get_width() || !texture->get_height(),ERR_INVALID_PARAMETER); + Image img = texture->get_data(); - if (img.get_format() > Image::FORMAT_INDEXED_ALPHA) - img.decompress(); + Error err = save_image(p_path, img); + + if (err == OK) { + + bool global_filter = Globals::get_singleton()->get("image_loader/filter"); + bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps"); + bool global_repeat = Globals::get_singleton()->get("image_loader/repeat"); + + String text; + + if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) { + text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n"; + } + if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) { + text+=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)?"gen_mipmaps=true\n":"gen_mipmaps=false\n"; + } + if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) { + text+=bool(texture->get_flags()&Texture::FLAG_REPEAT)?"repeat=true\n":"repeat=false\n"; + } + if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) { + text+="anisotropic=true\n"; + } + if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) { + text+="tolinear=true\n"; + } + + if (text!="" || FileAccess::exists(p_path+".flags")) { - ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER); + FileAccess* f = FileAccess::open(p_path+".flags",FileAccess::WRITE); + if (f) { + + f->store_string(text); + memdelete(f); + } + } + } + + + return err; +}; + +Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { + + if (p_img.get_format() > Image::FORMAT_INDEXED_ALPHA) + p_img.decompress(); + + ERR_FAIL_COND_V(p_img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER); png_structp png_ptr; png_infop info_ptr; @@ -88,7 +134,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t int cs=0; - switch(img.get_format()) { + switch(p_img.get_format()) { case Image::FORMAT_GRAYSCALE: { @@ -112,14 +158,14 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } break; default: { - if (img.detect_alpha()) { + if (p_img.detect_alpha()) { - img.convert(Image::FORMAT_RGBA); + p_img.convert(Image::FORMAT_RGBA); pngf=PNG_COLOR_TYPE_RGB_ALPHA; cs=4; } else { - img.convert(Image::FORMAT_RGB); + p_img.convert(Image::FORMAT_RGB); pngf=PNG_COLOR_TYPE_RGB; cs=3; } @@ -127,8 +173,8 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } } - int w = img.get_width(); - int h = img.get_height(); + int w = p_img.get_width(); + int h = p_img.get_height(); png_set_IHDR(png_ptr, info_ptr, w,h, 8, pngf, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); @@ -143,7 +189,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } - DVector<uint8_t>::Read r = img.get_data().read(); + DVector<uint8_t>::Read r = p_img.get_data().read(); row_pointers = (png_bytep*)memalloc(sizeof(png_bytep)*h); for(int i=0;i<h;i++) { @@ -164,7 +210,6 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t png_write_end(png_ptr, NULL); memdelete(f); - /* cleanup heap allocation */ return OK; @@ -181,3 +226,8 @@ void ResourceSaverPNG::get_recognized_extensions(const RES& p_resource,List<Stri } } + +ResourceSaverPNG::ResourceSaverPNG() { + + Image::save_png_func = &save_image; +}; diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 7da50150e2..116d425d24 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -6,9 +6,13 @@ class ResourceSaverPNG : public ResourceFormatSaver { public: + static Error save_image(const String &p_path, Image& p_img); + 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; + + ResourceSaverPNG(); }; diff --git a/drivers/gles1/SCsub b/drivers/pulseaudio/SCsub index 6a3e474eae..9fbb467baa 100644 --- a/drivers/gles1/SCsub +++ b/drivers/pulseaudio/SCsub @@ -1,5 +1,5 @@ Import('env') -Export('env'); env.add_source_files(env.drivers_sources,"*.cpp") +Export('env') diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp new file mode 100644 index 0000000000..dfe9ddc55f --- /dev/null +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -0,0 +1,194 @@ +/*************************************************************************/ +/* audio_driver_alsa.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 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 */ +/* "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 "audio_driver_pulseaudio.h" + +#ifdef PULSEAUDIO_ENABLED + +#include <pulse/error.h> + +#include "globals.h" + +Error AudioDriverPulseAudio::init() { + + active = false; + thread_exited = false; + exit_thread = false; + pcm_open = false; + samples_in = NULL; + samples_out = NULL; + + mix_rate = 44100; + output_format = OUTPUT_STEREO; + channels = 2; + + pa_sample_spec spec; + spec.format = PA_SAMPLE_S16LE; + spec.channels = channels; + spec.rate = mix_rate; + + int error_code; + pulse = pa_simple_new(NULL, // default server + "Godot", // application name + PA_STREAM_PLAYBACK, + NULL, // default device + "Sound", // stream description + &spec, + NULL, // use default channel map + NULL, // use default buffering attributes + &error_code + ); + + if (pulse == NULL) { + + fprintf(stderr, "PulseAudio ERR: %s\n", pa_strerror(error_code));\ + ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN); + } + + int latency = GLOBAL_DEF("audio/output_latency", 25); + buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + + samples_in = memnew_arr(int32_t, buffer_size * channels); + samples_out = memnew_arr(int16_t, buffer_size * channels); + + mutex = Mutex::create(); + thread = Thread::create(AudioDriverPulseAudio::thread_func, this); + + return OK; +} + +void AudioDriverPulseAudio::thread_func(void* p_udata) { + + AudioDriverPulseAudio* ad = (AudioDriverPulseAudio*)p_udata; + + while (!ad->exit_thread) { + + if (!ad->active) { + + for (unsigned int i=0; i < ad->buffer_size * ad->channels; i++) { + + ad->samples_out[i] = 0; + } + + } else { + + ad->lock(); + + ad->audio_server_process(ad->buffer_size, ad->samples_in); + + ad->unlock(); + + for (unsigned int i=0; i < ad->buffer_size * ad->channels;i ++) { + + ad->samples_out[i] = ad->samples_in[i] >> 16; + } + } + + // pa_simple_write always consumes the entire buffer + + int error_code; + int byte_size = ad->buffer_size * sizeof(int16_t) * ad->channels; + if (pa_simple_write(ad->pulse, ad->samples_out, byte_size, &error_code) < 0) { + + // can't recover here + fprintf(stderr, "PulseAudio failed and can't recover: %s\n", pa_strerror(error_code)); + ad->active = false; + ad->exit_thread = true; + break; + } + } + + ad->thread_exited = true; +} + +void AudioDriverPulseAudio::start() { + + active = true; +} + +int AudioDriverPulseAudio::get_mix_rate() const { + + return mix_rate; +} + +AudioDriverSW::OutputFormat AudioDriverPulseAudio::get_output_format() const { + + return output_format; +} + +void AudioDriverPulseAudio::lock() { + + if (!thread || !mutex) + return; + mutex->lock(); +} + +void AudioDriverPulseAudio::unlock() { + + if (!thread || !mutex) + return; + mutex->unlock(); +} + +void AudioDriverPulseAudio::finish() { + + if (!thread) + return; + + exit_thread = true; + Thread::wait_to_finish(thread); + + if (pulse) + pa_simple_free(pulse); + + if (samples_in) { + memdelete_arr(samples_in); + memdelete_arr(samples_out); + }; + + memdelete(thread); + if (mutex) { + memdelete(mutex); + mutex = NULL; + } + + thread = NULL; +} + +AudioDriverPulseAudio::AudioDriverPulseAudio() { + + mutex = NULL; + thread = NULL; + pulse = NULL; +} + +AudioDriverPulseAudio::~AudioDriverPulseAudio() { + +} + +#endif diff --git a/scene/gui/empty_control.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.h index 1e377b2b73..e82e0c24be 100644 --- a/scene/gui/empty_control.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* empty_control.cpp */ +/* audio_driver_pulseaudio.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -26,34 +26,54 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "empty_control.h"
-
-Size2 EmptyControl::get_minimum_size() const {
-
- return minsize;
-}
-
-void EmptyControl::set_minsize(const Size2& p_size) {
-
- minsize=p_size;
- minimum_size_changed();
-}
-
-Size2 EmptyControl::get_minsize() const {
-
- return minsize;
-}
-
-
-void EmptyControl::_bind_methods() {
-
-
- ObjectTypeDB::bind_method(_MD("set_minsize","minsize"),&EmptyControl::set_minsize);
- ObjectTypeDB::bind_method(_MD("get_minsize"),&EmptyControl::get_minsize);
-
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"minsize"), _SCS("set_minsize"),_SCS("get_minsize") );
-}
-
-EmptyControl::EmptyControl()
-{
-}
+#include "servers/audio/audio_server_sw.h" + +#ifdef PULSEAUDIO_ENABLED + +#include "core/os/thread.h" +#include "core/os/mutex.h" + +#include <pulse/simple.h> + +class AudioDriverPulseAudio : public AudioDriverSW { + + Thread* thread; + Mutex* mutex; + + pa_simple* pulse; + + int32_t* samples_in; + int16_t* samples_out; + + static void thread_func(void* p_udata); + + unsigned int mix_rate; + OutputFormat output_format; + + unsigned int buffer_size; + int channels; + + bool active; + bool thread_exited; + mutable bool exit_thread; + bool pcm_open; + +public: + + const char* get_name() const { + return "PulseAudio"; + }; + + virtual Error init(); + virtual void start(); + virtual int get_mix_rate() const; + virtual OutputFormat get_output_format() const; + virtual void lock(); + virtual void unlock(); + virtual void finish(); + + AudioDriverPulseAudio(); + ~AudioDriverPulseAudio(); +}; + +#endif diff --git a/drivers/pvr/AlphaBitmap.h b/drivers/pvr/AlphaBitmap.h new file mode 100644 index 0000000000..57c6b026ea --- /dev/null +++ b/drivers/pvr/AlphaBitmap.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Bitmap.h" + +namespace Javelin { + +class AlphaBitmap : public Bitmap { +public: + AlphaBitmap(int w, int h) + : Bitmap(w, h, 1) { + } + + const unsigned char *GetData() const { return data; } + + unsigned char *GetData() { return data; } +}; + +} diff --git a/drivers/pvr/BitScale.cpp b/drivers/pvr/BitScale.cpp new file mode 100644 index 0000000000..97b3f0aa25 --- /dev/null +++ b/drivers/pvr/BitScale.cpp @@ -0,0 +1,184 @@ +#include "BitScale.h" + + +const uint8_t Javelin::Data::BITSCALE_5_TO_8[32] = { + 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, + 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, + 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, + 246, 255}; + +const uint8_t Javelin::Data::BITSCALE_4_TO_8[16] = { + 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, + 170, 187, 204, 221, 238, 255}; + +const uint8_t Javelin::Data::BITSCALE_3_TO_8[8] = { + 0, 36, 72, 109, 145, 182, 218, 255}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_5_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, + 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, + 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, + 30, 30, 30, 30, 30, 31}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_4_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_3_FLOOR[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 7}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_5_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, + 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, + 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, + 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, + 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, + 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, + 31, 31, 31, 31, 31, 31}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_4_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15}; + +const uint8_t Javelin::Data::BITSCALE_8_TO_3_CEIL[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7}; + diff --git a/drivers/pvr/BitScale.h b/drivers/pvr/BitScale.h new file mode 100644 index 0000000000..36613aeeee --- /dev/null +++ b/drivers/pvr/BitScale.h @@ -0,0 +1,28 @@ +//============================================================================ + +#pragma once + +#include "typedefs.h" + +//============================================================================ + +namespace Javelin +{ + namespace Data + { +//============================================================================ + + extern const uint8_t BITSCALE_5_TO_8[32]; + extern const uint8_t BITSCALE_4_TO_8[16]; + extern const uint8_t BITSCALE_3_TO_8[8]; + extern const uint8_t BITSCALE_8_TO_5_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_4_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_3_FLOOR[256]; + extern const uint8_t BITSCALE_8_TO_5_CEIL[256]; + extern const uint8_t BITSCALE_8_TO_4_CEIL[256]; + extern const uint8_t BITSCALE_8_TO_3_CEIL[256]; + +//============================================================================ + } // namespace Data +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/BitUtility.h b/drivers/pvr/BitUtility.h new file mode 100644 index 0000000000..588ff3e892 --- /dev/null +++ b/drivers/pvr/BitUtility.h @@ -0,0 +1,19 @@ +#pragma once + +namespace Javelin { + +class BitUtility { +public: + static bool IsPowerOf2(unsigned int x) { + return (x & (x - 1)) == 0; + } + + static unsigned int RotateRight(unsigned int value, unsigned int shift) { + if ((shift &= sizeof(value) * 8 - 1) == 0) { + return value; + } + return (value >> shift) | (value << (sizeof(value) * 8 - shift)); + } +}; + +} diff --git a/drivers/pvr/Bitmap.h b/drivers/pvr/Bitmap.h new file mode 100644 index 0000000000..508ed8cb75 --- /dev/null +++ b/drivers/pvr/Bitmap.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Point2.h" + +namespace Javelin { + +class Bitmap { +public: + int width; + int height; + unsigned char *data; + + Bitmap(int w, int h, int bytesPerPixel) + : width(w) + , height(h) + , data(new unsigned char[width * height * bytesPerPixel]) { + } + + virtual ~Bitmap() { + delete [] data; + } + + Point2<int> GetSize() const { return Point2<int>(width, height); } + + int GetArea() const { return width * height; } + + int GetBitmapWidth() const { return width; } + + int GetBitmapHeight() const { return height; } + + const unsigned char *GetRawData() const { return data; } +}; + +} diff --git a/drivers/pvr/ColorRgba.h b/drivers/pvr/ColorRgba.h new file mode 100644 index 0000000000..6b46d65e3c --- /dev/null +++ b/drivers/pvr/ColorRgba.h @@ -0,0 +1,152 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class ColorRgb { +public: + T b; + T g; + T r; + + + ColorRgb() + : r(0) + , g(0) + , b(0) { + } + + ColorRgb(T red, T green, T blue) + : r(red) + , g(green) + , b(blue) { + } + + ColorRgb(const ColorRgb<T> &x) + : r(x.r) + , g(x.g) + , b(x.b) { + } + + ColorRgb<int> operator *(int x) { + return ColorRgb<int>(r * x, g * x, b * x); + } + + ColorRgb<int> operator +(const ColorRgb<T> &x) const { + return ColorRgb<int>(r + (int)x.r, g + (int)x.g, b + (int)x.b); + } + + ColorRgb<int> operator -(const ColorRgb<T> &x) const { + return ColorRgb<int>(r - (int)x.r, g - (int)x.g, b - (int)x.b); + } + + int operator %(const ColorRgb<T> &x) const { + return r * (int)x.r + g * (int)x.g + b * (int)x.b; + } + + bool operator ==(const ColorRgb<T> &x) const { + return r == x.r && g == x.g && b == x.b; + } + + bool operator !=(const ColorRgb<T> &x) const { + return r != x.r || g != x.g || b != x.b; + } + + void SetMin(const ColorRgb<T> &x) { + if (x.r < r) { + r = x.r; + } + if (x.g < g) { + g = x.g; + } + if (x.b < b) { + b = x.b; + } + } + + void SetMax(const ColorRgb<T> &x) { + if (x.r > r) { + r = x.r; + } + if (x.g > g) { + g = x.g; + } + if (x.b > b) { + b = x.b; + } + } +}; + +template<typename T> +class ColorRgba : public ColorRgb<T> { +public: + T a; + + ColorRgba() : + a(0) { + } + + ColorRgba(T red, T green, T blue, T alpha) + : ColorRgb<T>(red, green, blue) + , a(alpha) { + } + + ColorRgba(const ColorRgba<T> &x) + : ColorRgb<T>(x.r, x.g, x.b) + , a(x.a) { + } + + ColorRgba<int> operator *(int x) { + return ColorRgba<T>(ColorRgb<T>::r * x, + ColorRgb<T>::g * x, + ColorRgb<T>::b * x, + a * x); + } + + ColorRgba<int> operator +(const ColorRgba<T> &x) { + return ColorRgba<T>(ColorRgb<T>::r + (int)x.r, + ColorRgb<T>::g + (int)x.g, + ColorRgb<T>::b + (int)x.b, + a + (int)x.a); + } + + ColorRgba<int> operator -(const ColorRgba<T> &x) { + return ColorRgba<T>(ColorRgb<T>::r - (int)x.r, + ColorRgb<T>::g - (int)x.g, + ColorRgb<T>::b - (int)x.b, + a - (int)x.a); + } + + int operator %(const ColorRgba<T> &x) { + return ColorRgb<T>::r * (int)x.r + + ColorRgb<T>::g * (int)x.g + + ColorRgb<T>::b * (int)x.b + + a * (int)x.a; + } + + bool operator ==(const ColorRgba<T> &x) { + return ColorRgb<T>::r == x.r && ColorRgb<T>::g == x.g && + ColorRgb<T>::b == x.b && a == x.a; + } + + bool operator !=(const ColorRgba<T> &x) { + return ColorRgb<T>::r != x.r || ColorRgb<T>::g != x.g || + ColorRgb<T>::b != x.b || a != x.a; + } + + void SetMin(const ColorRgba<T> &x) { + ColorRgb<T>::SetMin(x); + if (x.a < a) { + a = x.a; + } + } + + void SetMax(const ColorRgba<T> &x) { + ColorRgb<T>::SetMax(x); + if (x.a > a) { + a = x.a; + } + } +}; + +} diff --git a/drivers/pvr/Interval.h b/drivers/pvr/Interval.h new file mode 100644 index 0000000000..a7252e8375 --- /dev/null +++ b/drivers/pvr/Interval.h @@ -0,0 +1,21 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class Interval { +public: + T min; + T max; + + Interval() { + } + + Interval<T> &operator|=(const T &x) { + min.SetMin(x); + max.SetMax(x); + return *this; + } +}; + +} diff --git a/drivers/pvr/MortonTable.cpp b/drivers/pvr/MortonTable.cpp new file mode 100644 index 0000000000..29a5af67f6 --- /dev/null +++ b/drivers/pvr/MortonTable.cpp @@ -0,0 +1,43 @@ +//============================================================================ + +#include "MortonTable.h" + +//============================================================================ + +const unsigned short Javelin::Data::MORTON_TABLE[256] = +{ + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 +}; + +//============================================================================ diff --git a/drivers/pvr/MortonTable.h b/drivers/pvr/MortonTable.h new file mode 100644 index 0000000000..7a27e59544 --- /dev/null +++ b/drivers/pvr/MortonTable.h @@ -0,0 +1,18 @@ +//============================================================================ + +#pragma once + +//============================================================================ + +namespace Javelin +{ + namespace Data + { +//============================================================================ + + extern const unsigned short MORTON_TABLE[256]; + +//============================================================================ + } // namespace Data +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/Point2.h b/drivers/pvr/Point2.h new file mode 100644 index 0000000000..89fa4b6322 --- /dev/null +++ b/drivers/pvr/Point2.h @@ -0,0 +1,17 @@ +#pragma once + +namespace Javelin { + +template<typename T> +class Point2 { +public: + T x; + T y; + + Point2(int a, int b) + : x(a) + , y(b) { + } +}; + +} diff --git a/drivers/pvr/PvrTcDecoder.cpp b/drivers/pvr/PvrTcDecoder.cpp new file mode 100644 index 0000000000..d8a36b342c --- /dev/null +++ b/drivers/pvr/PvrTcDecoder.cpp @@ -0,0 +1,144 @@ +//============================================================================ + +#include "PvrTcDecoder.h" +#include "PvrTcPacket.h" + +#include "MortonTable.h" +#include <assert.h> + +//============================================================================ + +using namespace Javelin; +using Data::MORTON_TABLE; + +//============================================================================ + +inline unsigned PvrTcDecoder::GetMortonNumber(int x, int y) +{ + return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF]; +} + +//============================================================================ + +void PvrTcDecoder::DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data) +{ + assert(size.x == size.y); + + const int blocks = size.x / 4; + const int blockMask = blocks-1; + const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const PvrTcPacket* packet = packets + GetMortonNumber(x, y); + + unsigned mod = packet->modulationData; + const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha; + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const unsigned char* w = weights[mod&3]; + ColorRgb<unsigned char> c; + c.r = (ca.r * w[0] + cb.r * w[1]) >> 7; + c.g = (ca.g * w[0] + cb.g * w[1]) >> 7; + c.b = (ca.b * w[0] + cb.b * w[1]) >> 7; + + result[(py+y*4)*size.x + (px+x*4)] = c; + mod >>= 2; + factor++; + } + } + } + } +} + +void PvrTcDecoder::DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data) +{ + assert(size.x == size.y); + + const int blocks = size.x / 4; + const int blockMask = blocks-1; + const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const PvrTcPacket* packet = packets + GetMortonNumber(x, y); + + unsigned mod = packet->modulationData; + const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha; + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] + + p1->GetColorRgbaA() * (*factor)[1] + + p2->GetColorRgbaA() * (*factor)[2] + + p3->GetColorRgbaA() * (*factor)[3]; + + ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] + + p1->GetColorRgbaB() * (*factor)[1] + + p2->GetColorRgbaB() * (*factor)[2] + + p3->GetColorRgbaB() * (*factor)[3]; + + const unsigned char* w = weights[mod&3]; + ColorRgba<unsigned char> c; + c.r = (ca.r * w[0] + cb.r * w[1]) >> 7; + c.g = (ca.g * w[0] + cb.g * w[1]) >> 7; + c.b = (ca.b * w[0] + cb.b * w[1]) >> 7; + c.a = (ca.a * w[2] + cb.a * w[3]) >> 7; + + result[(py+y*4)*size.x + (px+x*4)] = c; + mod >>= 2; + factor++; + } + } + } + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcDecoder.h b/drivers/pvr/PvrTcDecoder.h new file mode 100644 index 0000000000..1b6fcf964c --- /dev/null +++ b/drivers/pvr/PvrTcDecoder.h @@ -0,0 +1,25 @@ +//============================================================================ + +#pragma once +#include "Point2.h" +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + class PvrTcDecoder + { + public: + static void DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data); + static void DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data); + + private: + static unsigned GetMortonNumber(int x, int y); + }; + +//============================================================================ +} +//============================================================================ diff --git a/drivers/pvr/PvrTcEncoder.cpp b/drivers/pvr/PvrTcEncoder.cpp new file mode 100644 index 0000000000..587b1320f1 --- /dev/null +++ b/drivers/pvr/PvrTcEncoder.cpp @@ -0,0 +1,474 @@ +//============================================================================ + +#include "PvrTcEncoder.h" +#include "AlphaBitmap.h" +#include "PvrTcPacket.h" +#include "RgbBitmap.h" +#include "RgbaBitmap.h" +#include "MortonTable.h" +#include "BitUtility.h" +#include "Interval.h" +#include <assert.h> +#include <math.h> +#include <stdint.h> + +//============================================================================ + +using namespace Javelin; +using Data::MORTON_TABLE; + +//============================================================================ + +static const unsigned char MODULATION_LUT[16] = +{ + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 +}; + +//============================================================================ + +inline unsigned PvrTcEncoder::GetMortonNumber(int x, int y) +{ + return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF]; +} + +//============================================================================ + +void PvrTcEncoder::EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap) +{ + int size = bitmap.GetBitmapWidth(); + assert(size == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(size)); + + // Blocks in each dimension. + int xBlocks = size/8; + int yBlocks = size/4; + + const unsigned char* bitmapData = bitmap.GetRawData(); + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + for(int y = 0; y < yBlocks; ++y) + { + for(int x = 0; x < xBlocks; ++x) + { + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->colorAIsOpaque = 0; + packet->colorA = 0x7ff; // White, with 0 alpha + packet->colorBIsOpaque = 1; + packet->colorB = 0x7fff; // White with full alpha + + const unsigned char* blockBitmapData = &bitmapData[y*4*size + x*8]; + + uint32_t modulationData = 0; + for(int py = 0; py < 4; ++py) + { + const unsigned char* rowBitmapData = blockBitmapData; + for(int px = 0; px < 8; ++px) + { + unsigned char pixel = *rowBitmapData++; + modulationData = BitUtility::RotateRight(modulationData | (pixel >> 7), 1); + } + blockBitmapData += size; + } + packet->modulationData = modulationData; + } + } +} + +void PvrTcEncoder::EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap) +{ + int size = bitmap.GetBitmapWidth(); + assert(size == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(size)); + + // Blocks in each dimension. + int blocks = size/4; + + const unsigned char* bitmapData = bitmap.GetRawData(); + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->colorAIsOpaque = 0; + packet->colorA = 0x7ff; // White, with 0 alpha + packet->colorBIsOpaque = 1; + packet->colorB = 0x7fff; // White with full alpha + + const unsigned char* blockBitmapData = &bitmapData[(y*size + x)*4]; + + uint32_t modulationData = 0; + for(int py = 0; py < 4; ++py) + { + const unsigned char* rowBitmapData = blockBitmapData; + for(int px = 0; px < 4; ++px) + { + unsigned char pixel = *rowBitmapData++; + modulationData = BitUtility::RotateRight(modulationData | MODULATION_LUT[pixel>>4], 2); + } + blockBitmapData += size; + } + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +typedef Interval<ColorRgb<unsigned char> > ColorRgbBoundingBox; + +static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgb<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgb<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const ColorRgb<unsigned char>& pixel = data[py*size + px]; + ColorRgb<int> d = cb - ca; + ColorRgb<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + ColorRgb<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] + + p1->GetColorRgbA() * (*factor)[1] + + p2->GetColorRgbA() * (*factor)[2] + + p3->GetColorRgbA() * (*factor)[3]; + + ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] + + p1->GetColorRgbB() * (*factor)[1] + + p2->GetColorRgbB() * (*factor)[2] + + p3->GetColorRgbB() * (*factor)[3]; + + const ColorRgb<unsigned char>& pixel = data[py*size + px]; + ColorRgb<int> d = cb - ca; + ColorRgb<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + ColorRgb<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ + +typedef Interval<ColorRgba<unsigned char> > ColorRgbaBoundingBox; + +static void CalculateBoundingBox(ColorRgbaBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY) +{ + int size = bitmap.GetBitmapWidth(); + const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4; + + cbb.min = data[0]; + cbb.max = data[0]; + + cbb |= data[1]; + cbb |= data[2]; + cbb |= data[3]; + + cbb |= data[size]; + cbb |= data[size+1]; + cbb |= data[size+2]; + cbb |= data[size+3]; + + cbb |= data[2*size]; + cbb |= data[2*size+1]; + cbb |= data[2*size+2]; + cbb |= data[2*size+3]; + + cbb |= data[3*size]; + cbb |= data[3*size+1]; + cbb |= data[3*size+2]; + cbb |= data[3*size+3]; +} + +void PvrTcEncoder::EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap) +{ + assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight()); + assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth())); + const int size = bitmap.GetBitmapWidth(); + const int blocks = size / 4; + const int blockMask = blocks-1; + + PvrTcPacket* packets = static_cast<PvrTcPacket*>(result); + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + ColorRgbaBoundingBox cbb; + CalculateBoundingBox(cbb, bitmap, x, y); + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->usePunchthroughAlpha = 0; + packet->SetColorA(cbb.min); + packet->SetColorB(cbb.max); + } + } + + for(int y = 0; y < blocks; ++y) + { + for(int x = 0; x < blocks; ++x) + { + const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS; + const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4; + + uint32_t modulationData = 0; + + for(int py = 0; py < 4; ++py) + { + const int yOffset = (py < 2) ? -1 : 0; + const int y0 = (y + yOffset) & blockMask; + const int y1 = (y0+1) & blockMask; + + for(int px = 0; px < 4; ++px) + { + const int xOffset = (px < 2) ? -1 : 0; + const int x0 = (x + xOffset) & blockMask; + const int x1 = (x0+1) & blockMask; + + const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0); + const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0); + const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1); + const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1); + + ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] + + p1->GetColorRgbaA() * (*factor)[1] + + p2->GetColorRgbaA() * (*factor)[2] + + p3->GetColorRgbaA() * (*factor)[3]; + + ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] + + p1->GetColorRgbaB() * (*factor)[1] + + p2->GetColorRgbaB() * (*factor)[2] + + p3->GetColorRgbaB() * (*factor)[3]; + + const ColorRgba<unsigned char>& pixel = data[py*size + px]; + ColorRgba<int> d = cb - ca; + ColorRgba<int> p; + p.r=pixel.r*16; + p.g=pixel.g*16; + p.b=pixel.b*16; + p.a=pixel.a*16; + ColorRgba<int> v = p - ca; + + // PVRTC uses weightings of 0, 3/8, 5/8 and 1 + // The boundaries for these are 3/16, 1/2 (=8/16), 13/16 + int projection = (v % d) * 16; + int lengthSquared = d % d; + if(projection > 3*lengthSquared) modulationData++; + if(projection > 8*lengthSquared) modulationData++; + if(projection > 13*lengthSquared) modulationData++; + + modulationData = BitUtility::RotateRight(modulationData, 2); + + factor++; + } + } + + PvrTcPacket* packet = packets + GetMortonNumber(x, y); + packet->modulationData = modulationData; + } + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcEncoder.h b/drivers/pvr/PvrTcEncoder.h new file mode 100644 index 0000000000..b9344367d9 --- /dev/null +++ b/drivers/pvr/PvrTcEncoder.h @@ -0,0 +1,40 @@ +//============================================================================ + +#pragma once +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + class AlphaBitmap; + class RgbBitmap; + class RgbaBitmap; + + class PvrTcEncoder + { + public: + // Result must be large enough for bitmap.GetArea()/4 bytes + static void EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap); + + // Result must be large enough for bitmap.GetArea()/2 bytes + static void EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap); + + private: + static unsigned GetMortonNumber(int x, int y); + }; + +//============================================================================ +} +//============================================================================ diff --git a/drivers/pvr/PvrTcPacket.cpp b/drivers/pvr/PvrTcPacket.cpp new file mode 100644 index 0000000000..2e40d371e8 --- /dev/null +++ b/drivers/pvr/PvrTcPacket.cpp @@ -0,0 +1,209 @@ +//============================================================================ + +#include "PvrTcPacket.h" +#include "BitScale.h" + +//============================================================================ + +using namespace Javelin; + +//============================================================================ + +const unsigned char PvrTcPacket::BILINEAR_FACTORS[16][4] = +{ + { 4, 4, 4, 4 }, + { 2, 6, 2, 6 }, + { 8, 0, 8, 0 }, + { 6, 2, 6, 2 }, + + { 2, 2, 6, 6 }, + { 1, 3, 3, 9 }, + { 4, 0, 12, 0 }, + { 3, 1, 9, 3 }, + + { 8, 8, 0, 0 }, + { 4, 12, 0, 0 }, + { 16, 0, 0, 0 }, + { 12, 4, 0, 0 }, + + { 6, 6, 2, 2 }, + { 3, 9, 1, 3 }, + { 12, 0, 4, 0 }, + { 9, 3, 3, 1 }, +}; + +// Weights are { colorA, colorB, alphaA, alphaB } +const unsigned char PvrTcPacket::WEIGHTS[8][4] = +{ + // Weights for Mode=0 + { 8, 0, 8, 0 }, + { 5, 3, 5, 3 }, + { 3, 5, 3, 5 }, + { 0, 8, 0, 8 }, + + // Weights for Mode=1 + { 8, 0, 8, 0 }, + { 4, 4, 4, 4 }, + { 4, 4, 0, 0 }, + { 0, 8, 0, 8 }, +}; + +//============================================================================ + +ColorRgb<int> PvrTcPacket::GetColorRgbA() const +{ + if(colorAIsOpaque) + { + unsigned char r = colorA >> 9; + unsigned char g = colorA >> 4 & 0x1f; + unsigned char b = colorA & 0xf; + return ColorRgb<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_4_TO_8[b]); + } + else + { + unsigned char r = (colorA >> 7) & 0xf; + unsigned char g = (colorA >> 3) & 0xf; + unsigned char b = colorA & 7; + return ColorRgb<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_3_TO_8[b]); + } +} + +ColorRgb<int> PvrTcPacket::GetColorRgbB() const +{ + if(colorBIsOpaque) + { + unsigned char r = colorB >> 10; + unsigned char g = colorB >> 5 & 0x1f; + unsigned char b = colorB & 0x1f; + return ColorRgb<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_5_TO_8[b]); + } + else + { + unsigned char r = colorB >> 8 & 0xf; + unsigned char g = colorB >> 4 & 0xf; + unsigned char b = colorB & 0xf; + return ColorRgb<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_4_TO_8[b]); + } +} + +ColorRgba<int> PvrTcPacket::GetColorRgbaA() const +{ + if(colorAIsOpaque) + { + unsigned char r = colorA >> 9; + unsigned char g = colorA >> 4 & 0x1f; + unsigned char b = colorA & 0xf; + return ColorRgba<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_4_TO_8[b], + 255); + } + else + { + unsigned char a = colorA >> 11 & 7; + unsigned char r = colorA >> 7 & 0xf; + unsigned char g = colorA >> 3 & 0xf; + unsigned char b = colorA & 7; + return ColorRgba<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_3_TO_8[b], + Data::BITSCALE_3_TO_8[a]); + } +} + +ColorRgba<int> PvrTcPacket::GetColorRgbaB() const +{ + if(colorBIsOpaque) + { + unsigned char r = colorB >> 10; + unsigned char g = colorB >> 5 & 0x1f; + unsigned char b = colorB & 0x1f; + return ColorRgba<int>(Data::BITSCALE_5_TO_8[r], + Data::BITSCALE_5_TO_8[g], + Data::BITSCALE_5_TO_8[b], + 255); + } + else + { + unsigned char a = colorB >> 12 & 7; + unsigned char r = colorB >> 8 & 0xf; + unsigned char g = colorB >> 4 & 0xf; + unsigned char b = colorB & 0xf; + return ColorRgba<int>(Data::BITSCALE_4_TO_8[r], + Data::BITSCALE_4_TO_8[g], + Data::BITSCALE_4_TO_8[b], + Data::BITSCALE_3_TO_8[a]); + } +} + +//============================================================================ + +void PvrTcPacket::SetColorA(const ColorRgb<unsigned char>& c) +{ + int r = Data::BITSCALE_8_TO_5_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_5_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_4_FLOOR[c.b]; + colorA = r<<9 | g<<4 | b; + colorAIsOpaque = true; +} + +void PvrTcPacket::SetColorB(const ColorRgb<unsigned char>& c) +{ + int r = Data::BITSCALE_8_TO_5_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_5_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_5_CEIL[c.b]; + colorB = r<<10 | g<<5 | b; + colorBIsOpaque = true; +} + +void PvrTcPacket::SetColorA(const ColorRgba<unsigned char>& c) +{ + int a = Data::BITSCALE_8_TO_3_FLOOR[c.a]; + if(a == 7) + { + int r = Data::BITSCALE_8_TO_5_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_5_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_4_FLOOR[c.b]; + colorA = r<<9 | g<<4 | b; + colorAIsOpaque = true; + } + else + { + int r = Data::BITSCALE_8_TO_4_FLOOR[c.r]; + int g = Data::BITSCALE_8_TO_4_FLOOR[c.g]; + int b = Data::BITSCALE_8_TO_3_FLOOR[c.b]; + colorA = a<<11 | r<<7 | g<<3 | b; + colorAIsOpaque = false; + } +} + +void PvrTcPacket::SetColorB(const ColorRgba<unsigned char>& c) +{ + int a = Data::BITSCALE_8_TO_3_CEIL[c.a]; + if(a == 7) + { + int r = Data::BITSCALE_8_TO_5_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_5_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_5_CEIL[c.b]; + colorB = r<<10 | g<<5 | b; + colorBIsOpaque = true; + } + else + { + int r = Data::BITSCALE_8_TO_4_CEIL[c.r]; + int g = Data::BITSCALE_8_TO_4_CEIL[c.g]; + int b = Data::BITSCALE_8_TO_4_CEIL[c.b]; + colorB = a<<12 | r<<8 | g<<4 | b; + colorBIsOpaque = false; + } +} + +//============================================================================ diff --git a/drivers/pvr/PvrTcPacket.h b/drivers/pvr/PvrTcPacket.h new file mode 100644 index 0000000000..ac3b6a4dd1 --- /dev/null +++ b/drivers/pvr/PvrTcPacket.h @@ -0,0 +1,65 @@ +//============================================================================ +// +// Modulation data specifies weightings of colorA to colorB for each pixel +// +// For mode = 0 +// 00: 0/8 +// 01: 3/8 +// 10: 5/8 +// 11: 8/8 +// +// For mode = 1 +// 00: 0/8 +// 01: 4/8 +// 10: 4/8 with alpha punchthrough +// 11: 8/8 +// +// For colorIsOpaque=0 +// 3 bits A +// 4 bits R +// 4 bits G +// 3/4 bits B +// +// For colorIsOpaque=1 +// 5 bits R +// 5 bits G +// 4/5 bits B +// +//============================================================================ + +#pragma once +#include "ColorRgba.h" + +//============================================================================ + +namespace Javelin +{ +//============================================================================ + + struct PvrTcPacket + { + unsigned int modulationData; + unsigned usePunchthroughAlpha : 1; + unsigned colorA : 14; + unsigned colorAIsOpaque : 1; + unsigned colorB : 15; + unsigned colorBIsOpaque : 1; + + ColorRgb<int> GetColorRgbA() const; + ColorRgb<int> GetColorRgbB() const; + ColorRgba<int> GetColorRgbaA() const; + ColorRgba<int> GetColorRgbaB() const; + + void SetColorA(const ColorRgb<unsigned char>& c); + void SetColorB(const ColorRgb<unsigned char>& c); + + void SetColorA(const ColorRgba<unsigned char>& c); + void SetColorB(const ColorRgba<unsigned char>& c); + + static const unsigned char BILINEAR_FACTORS[16][4]; + static const unsigned char WEIGHTS[8][4]; + }; + +//============================================================================ +} // namespace Javelin +//============================================================================ diff --git a/drivers/pvr/RgbBitmap.h b/drivers/pvr/RgbBitmap.h new file mode 100644 index 0000000000..cf1d78667d --- /dev/null +++ b/drivers/pvr/RgbBitmap.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Bitmap.h" +#include "ColorRgba.h" + +namespace Javelin { + +class RgbBitmap : public Bitmap { +public: + RgbBitmap(int w, int h) + : Bitmap(w, h, 3) { + } + + const ColorRgb<unsigned char> *GetData() const { + return reinterpret_cast<ColorRgb<unsigned char> *>(data); + } + + ColorRgb<unsigned char> *GetData() { + return reinterpret_cast<ColorRgb<unsigned char> *>(data); + } +}; + +} diff --git a/drivers/pvr/RgbaBitmap.h b/drivers/pvr/RgbaBitmap.h new file mode 100644 index 0000000000..66b5542c1a --- /dev/null +++ b/drivers/pvr/RgbaBitmap.h @@ -0,0 +1,23 @@ +#pragma once + +#include "ColorRgba.h" +#include "Bitmap.h" + +namespace Javelin { + +class RgbaBitmap : public Bitmap { +public: + RgbaBitmap(int w, int h) + : Bitmap(w, h, 4) { + } + + const ColorRgba<unsigned char> *GetData() const { + return reinterpret_cast<ColorRgba<unsigned char> *>(data); + } + + ColorRgba<unsigned char> *GetData() { + return reinterpret_cast<ColorRgba<unsigned char> *>(data); + } +}; + +} diff --git a/drivers/pvr/SCsub b/drivers/pvr/SCsub index bd4c6f3f88..44b8c3d6bb 100644 --- a/drivers/pvr/SCsub +++ b/drivers/pvr/SCsub @@ -2,10 +2,14 @@ Import('env') pvr_sources = [ + "pvr/BitScale.cpp", + "pvr/MortonTable.cpp", + "pvr/PvrTcDecoder.cpp", + "pvr/PvrTcEncoder.cpp", + "pvr/PvrTcPacket.cpp", "pvr/texture_loader_pvr.cpp" ] env.drivers_sources+=pvr_sources #env.add_source_files(env.drivers_sources, pvr_sources) - diff --git a/drivers/pvr/texture_loader_pvr.cpp b/drivers/pvr/texture_loader_pvr.cpp index b12e0c28b8..5268b953f4 100644 --- a/drivers/pvr/texture_loader_pvr.cpp +++ b/drivers/pvr/texture_loader_pvr.cpp @@ -1,6 +1,8 @@ #include "texture_loader_pvr.h" #include "os/file_access.h" #include <string.h> +#include "PvrTcEncoder.h" +#include "RgbaBitmap.h" static void _pvrtc_decompress(Image* p_img); @@ -154,10 +156,59 @@ String ResourceFormatPVR::get_resource_type(const String &p_path) const { } + +static void _compress_pvrtc4(Image * p_img) { + + Image img = *p_img; + + bool make_mipmaps=false; + if (img.get_width()%8 || img.get_height()%8) { + make_mipmaps=img.get_mipmaps()>0; + img.resize(img.get_width()+(8-(img.get_width()%8)),img.get_height()+(8-(img.get_height()%8))); + } + img.convert(Image::FORMAT_RGBA); + if (img.get_mipmaps()==0 && make_mipmaps) + img.generate_mipmaps(); + + bool use_alpha=img.detect_alpha(); + + Image new_img; + new_img.create(img.get_width(),img.get_height(),true,use_alpha?Image::FORMAT_PVRTC4_ALPHA:Image::FORMAT_PVRTC4); + DVector<uint8_t> data=new_img.get_data(); + { + DVector<uint8_t>::Write wr=data.write(); + DVector<uint8_t>::Read r=img.get_data().read(); + + + for(int i=0;i<=new_img.get_mipmaps();i++) { + + int ofs,size,w,h; + img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h); + Javelin::RgbaBitmap bm(w,h); + copymem(bm.GetData(),&r[ofs],size); + { + Javelin::ColorRgba<unsigned char> *dp = bm.GetData(); + for(int j=0;j<size/4;j++) { + SWAP(dp[j].r,dp[j].b); + } + } + + new_img.get_mipmap_offset_size_and_dimensions(i,ofs,size,w,h); + Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs],bm); + } + + } + + *p_img = Image(new_img.get_width(),new_img.get_height(),new_img.get_mipmaps(),new_img.get_format(),data); + +} + ResourceFormatPVR::ResourceFormatPVR() { Image::_image_decompress_pvrtc=_pvrtc_decompress; + Image::_image_compress_pvrtc4_func=_compress_pvrtc4; + Image::_image_compress_pvrtc2_func=_compress_pvrtc4; } diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index e4bb1a343a..e730171fbb 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -222,7 +222,10 @@ void register_driver_types() { #endif #endif +#ifdef ETC1_ENABLED _register_etc1_compress_func(); +#endif + initialize_chibi(); } diff --git a/drivers/theora/SCsub b/drivers/theora/SCsub index d3e5838276..ecabce6c9d 100644 --- a/drivers/theora/SCsub +++ b/drivers/theora/SCsub @@ -32,6 +32,7 @@ sources = [ "theora/video_stream_theora.cpp", ] -env.drivers_sources += sources +if env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index 023b2c928b..09fb13d8e9 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -59,27 +59,47 @@ src/YUV/C/yuv420_grey_c.c src/YUV/C/yuv420_yuv_c.c src/YUV/C/yuv420_rgb_c.c src/TheoraVideoFrame.cpp -video_stream_theoraplayer.cpp """) +env_theora = env.Clone() + if env["platform"] == "iphone": sources.append("src/AVFoundation/TheoraVideoClip_AVFoundation.mm") env.Append(LINKFLAGS=['-framework', 'CoreVideo', '-framework', 'CoreMedia', '-framework', 'AVFoundation']) + if env["target"] == "release": + env_theora.Append(CPPFLAGS=["-D_IOS", "-D__ARM_NEON__", "-fstrict-aliasing", "-fmessage-length=210", "-fdiagnostics-show-note-include-stack", "-fmacro-backtrace-limit=0", "-fcolor-diagnostics", "-Wno-trigraphs", "-fpascal-strings", "-fvisibility=hidden", "-fvisibility-inlines-hidden"]) -env_theora = env.Clone() - -env_theora.Append(CPPFLAGS=["-D_YUV_C", "-D__THEORA", "-D_LIB"]) +env_theora.Append(CPPFLAGS=["-D_LIB", "-D__THEORA"]) # removed -D_YUV_C +env_theora.Append(CPPFLAGS=["-D_YUV_LIBYUV"]) +#env_theora.Append(CPPFLAGS=["-D_YUV_C"]) if env["platform"] == "iphone": env_theora.Append(CPPFLAGS=["-D__AVFOUNDATION"]) +else: + pass + #env_theora.Append(CPPFLAGS=["-D__FFMPEG"]) if env["platform"] == "android": env_theora.Append(CPPFLAGS=["-D_ANDROID"]) +if env["platform"] == "winrt": + env_theora.Append(CPPFLAGS=["-D_WINRT"]) + env_theora.Append(CPPPATH=["#drivers/theoraplayer/include/theoraplayer", "#drivers/theoraplayer/src/YUV", "#drivers/theoraplayer/src/YUV/libyuv/include", "#drivers/theoraplayer/src/Theora", "#drivers/theoraplayer/src/AVFoundation"]) objs = [] -env_theora.add_source_files(objs, sources) + +env_theora.add_source_files(objs, ["video_stream_theoraplayer.cpp"]) + +if env['use_theoraplayer_binary'] == "yes": + if env["platform"] == "iphone": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/ios']) + env.Append(LIBS=['theoraplayer', 'ogg', 'theora', 'tremor']) + if env["platform"] == "windows": + env.Append(LIBPATH=['#drivers/theoraplayer/lib/windows']) + env.Append(LINKFLAGS=['libtheoraplayer_static.lib', 'libogg.lib', 'libtheora.lib', 'libvorbis.lib']) +else: + env_theora.add_source_files(objs, sources) env.drivers_sources += objs diff --git a/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h b/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h index b2987c01c4..fe71cf8566 100644 --- a/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h +++ b/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h @@ -87,6 +87,7 @@ protected: std::string mName; int mWidth, mHeight, mStride; int mNumFrames; + int audio_track; int mSubFrameWidth, mSubFrameHeight, mSubFrameOffsetX, mSubFrameOffsetY; float mAudioGain; //! multiplier for audio samples. between 0 and 1 @@ -233,6 +234,7 @@ public: bool getAutoRestart() { return mAutoRestart; } + void set_audio_track(int p_track) { audio_track=p_track; } /** TODO: user priority. Useful only when more than one video is being decoded diff --git a/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h b/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h index 3ff9b217cd..d94c51b4d4 100644 --- a/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h +++ b/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h @@ -67,8 +67,8 @@ public: //! search registered clips by name TheoraVideoClip* getVideoClipByName(std::string name); - TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0); - TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0); + TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_track=0); + TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_audio_track=0); void update(float timeDelta); diff --git a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm index 8c3d2cc3b9..1b5cf0ab13 100644 --- a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm +++ b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm @@ -271,7 +271,10 @@ void TheoraVideoClip_AVFoundation::load(TheoraDataSource* source) AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; NSArray* audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; - AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:0] : NULL; + if (audio_track >= audioTracks.count) + audio_track = 0; + AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:audio_track] : NULL; + printf("*********** using audio track %i\n", audio_track); #ifdef _AVFOUNDATION_BGRX bool yuv_output = (mOutputMode != TH_BGRX && mOutputMode != TH_RGBA); diff --git a/drivers/theoraplayer/src/TheoraVideoClip.cpp b/drivers/theoraplayer/src/TheoraVideoClip.cpp index 3ee4b83370..16897ee80e 100644 --- a/drivers/theoraplayer/src/TheoraVideoClip.cpp +++ b/drivers/theoraplayer/src/TheoraVideoClip.cpp @@ -51,6 +51,8 @@ TheoraVideoClip::TheoraVideoClip(TheoraDataSource* data_source, mWaitingForCache(false), mOutputMode(TH_UNDEFINED) { + + audio_track=0; mAudioMutex = NULL; mThreadAccessMutex = new TheoraMutex(); mTimer = mDefaultTimer = new TheoraTimer(); @@ -75,7 +77,7 @@ TheoraVideoClip::~TheoraVideoClip() if (mAudioInterface) { mAudioMutex->lock(); // ensure a thread isn't using this mutex - memdelete(mAudioInterface); // notify audio interface it's time to call it a day + delete mAudioInterface; // notify audio interface it's time to call it a day mAudioMutex ->unlock(); delete mAudioMutex; } @@ -247,6 +249,7 @@ int TheoraVideoClip::discardOutdatedFrames(float absTime) if (nPop > 0) { +#define _DEBUG #ifdef _DEBUG std::string log = getName() + ": dropped frame "; diff --git a/drivers/theoraplayer/src/TheoraVideoManager.cpp b/drivers/theoraplayer/src/TheoraVideoManager.cpp index 87696d12a9..53b211374a 100644 --- a/drivers/theoraplayer/src/TheoraVideoManager.cpp +++ b/drivers/theoraplayer/src/TheoraVideoManager.cpp @@ -35,6 +35,8 @@ extern "C" void initYUVConversionModule(); } +#include "core/os/memory.h" + //#define _DECODING_BENCHMARK //uncomment to test average decoding time on a given device @@ -184,16 +186,18 @@ TheoraAudioInterfaceFactory* TheoraVideoManager::getAudioInterfaceFactory() TheoraVideoClip* TheoraVideoManager::createVideoClip(std::string filename, TheoraOutputMode output_mode, int numPrecachedOverride, - bool usePower2Stride) + bool usePower2Stride, + int p_track) { - TheoraDataSource* src=new TheoraFileDataSource(filename); - return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride); + TheoraDataSource* src=memnew(TheoraFileDataSource(filename)); + return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride, p_track); } TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_source, TheoraOutputMode output_mode, int numPrecachedOverride, - bool usePower2Stride) + bool usePower2Stride, + int p_audio_track) { mWorkMutex->lock(); @@ -226,6 +230,8 @@ TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_sour #ifdef __FFMPEG clip = new TheoraVideoClip_FFmpeg(data_source, output_mode, nPrecached, usePower2Stride); #endif + + clip->set_audio_track(p_audio_track); clip->load(data_source); clip->decodeNextFrame(); // ensure the first frame is always preloaded and have the main thread do it to prevent potential thread starvatio diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp index b2ff8062cc..9f4a44ae9d 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.cpp +++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp @@ -37,6 +37,11 @@ #include "include/theoraplayer/TheoraException.h" #include "core/ring_buffer.h" +#include "core/os/thread_safe.h" + +#include "core/globals.h" + +static TheoraVideoManager* mgr = NULL; class TPDataFA : public TheoraDataSource { @@ -107,6 +112,8 @@ public: class AudioStreamInput : public AudioStreamResampled { + _THREAD_SAFE_CLASS_; + int channels; int freq; @@ -114,20 +121,35 @@ class AudioStreamInput : public AudioStreamResampled { mutable RingBuffer<float> rb; int rb_power; int total_wrote; + bool playing; + bool paused; public: virtual void play() { + + _THREAD_SAFE_METHOD_ _setup(channels, freq, 256); stream_rid=AudioServer::get_singleton()->audio_stream_create(get_audio_stream()); AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,1); + playing = true; + paused = false; + }; + virtual void stop() { + + _THREAD_SAFE_METHOD_ + + AudioServer::get_singleton()->stream_set_active(stream_rid,false); + //_clear_stream(); + playing=false; + _clear(); }; - virtual void stop() {}; + virtual bool is_playing() const { return true; }; - virtual void set_paused(bool p_paused) {}; - virtual bool is_paused(bool p_paused) const { return false; }; + virtual void set_paused(bool p_paused) { paused = p_paused; }; + virtual bool is_paused(bool p_paused) const { return paused; }; virtual void set_loop(bool p_enable) {}; virtual bool has_loop() const { return false; }; @@ -141,32 +163,39 @@ public: virtual float get_pos() const { return 0; }; virtual void seek_pos(float p_time) {}; - virtual UpdateMode get_update_mode() const { return UPDATE_IDLE; }; + virtual UpdateMode get_update_mode() const { return UPDATE_THREAD; }; virtual bool _can_mix() const { return true; }; void input(float* p_data, int p_samples) { + + _THREAD_SAFE_METHOD_; + //printf("input %i samples from %p\n", p_samples, p_data); if (rb.space_left() < p_samples) { rb_power += 1; rb.resize(rb_power); } rb.write(p_data, p_samples); + + update(); //update too here for less latency }; void update() { + _THREAD_SAFE_METHOD_; int todo = get_todo(); int16_t* buffer = get_write_buffer(); - int samples = rb.data_left(); - const int to_write = MIN(todo, samples); + int frames = rb.data_left()/channels; + const int to_write = MIN(todo, frames); - for (int i=0; i<to_write; i++) { + for (int i=0; i<to_write*channels; i++) { - uint16_t sample = uint16_t(rb.read() * 32767); + int v = rb.read() * 32767; + int16_t sample = CLAMP(v,-32768,32767); buffer[i] = sample; }; - write(to_write/channels); + write(to_write); total_wrote += to_write; }; @@ -181,12 +210,19 @@ public: AudioStreamInput(int p_channels, int p_freq) { + playing = false; + paused = true; channels = p_channels; freq = p_freq; total_wrote = 0; - rb_power = 12; + rb_power = 22; rb.resize(rb_power); }; + + ~AudioStreamInput() { + + stop(); + }; }; class TPAudioGodot : public TheoraAudioInterface, TheoraTimer { @@ -206,7 +242,7 @@ public: TPAudioGodot(TheoraVideoClip* owner, int nChannels, int p_freq) : TheoraAudioInterface(owner, nChannels, p_freq), TheoraTimer() { - printf("***************** audio interface constructor\n"); + printf("***************** audio interface constructor freq %i\n", p_freq); channels = nChannels; freq = p_freq; stream = Ref<AudioStreamInput>(memnew(AudioStreamInput(nChannels, p_freq))); @@ -215,14 +251,22 @@ public: owner->setTimer(this); }; + void stop() { + + stream->stop(); + }; + void update(float time_increase) { - mTime = (float)(stream->get_total_wrote() / channels) / freq; + float prev_time = mTime; + //mTime = (float)(stream->get_total_wrote()) / freq; + //mTime = MAX(0,mTime-AudioServer::get_singleton()->get_output_delay()); //mTime = (float)sample_count / channels / freq; - //mTime += time_increase; + mTime += time_increase; + if (mTime - prev_time > .02) printf("time increase %f secs\n", mTime - prev_time); //float duration=mClip->getDuration(); //if (mTime > duration) mTime=duration; - //printf("time at timer is %f, samples %i\n", mTime, sample_count); + //printf("time at timer is %f, %f, samples %i\n", mTime, time_increase, sample_count); } }; @@ -232,7 +276,7 @@ public: TheoraAudioInterface* createInstance(TheoraVideoClip* owner, int nChannels, int freq) { printf("************** creating audio output\n"); - TheoraAudioInterface* ta = memnew(TPAudioGodot(owner, nChannels, freq)); + TheoraAudioInterface* ta = new TPAudioGodot(owner, nChannels, freq); return ta; }; }; @@ -242,13 +286,16 @@ static TPAudioGodotFactory* audio_factory = NULL; void VideoStreamTheoraplayer::stop() { playing = false; - if (clip) + if (clip) { + clip->stop(); clip->seek(0); + }; + started = true; }; void VideoStreamTheoraplayer::play() { - - playing = true; + if (clip) + playing = true; }; bool VideoStreamTheoraplayer::is_playing() const { @@ -258,7 +305,13 @@ bool VideoStreamTheoraplayer::is_playing() const { void VideoStreamTheoraplayer::set_paused(bool p_paused) { - playing = false; + paused = p_paused; + if (paused) { + clip->pause(); + } else { + if (clip && playing && !started) + clip->play(); + } }; bool VideoStreamTheoraplayer::is_paused(bool p_paused) const { @@ -306,22 +359,37 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const { if (!clip) return 0; - if (!frame.empty()) - return 1; + TheoraVideoFrame* f = clip->getNextFrame(); + return f ? 1 : 0; +}; + + +void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) { + + if (!clip) + return; TheoraVideoFrame* f = clip->getNextFrame(); - if (!f) - return 0; + if (!f) { + return; + }; + +#ifdef GLES2_ENABLED +// RasterizerGLES2* r = RasterizerGLES2::get_singleton(); +// r->_texture_set_data(p_tex, f->mBpp == 3 ? Image::Format_RGB : Image::Format_RGBA, f->mBpp, w, h, f->getBuffer()); + +#endif float w=clip->getWidth(),h=clip->getHeight(); - int imgsize = w * h * f->mBpp; + int imgsize = w * h * f->mBpp; int size = f->getStride() * f->getHeight() * f->mBpp; - DVector<uint8_t> data; data.resize(imgsize); - DVector<uint8_t>::Write wr = data.write(); - uint8_t* ptr = wr.ptr(); - copymem(ptr, f->getBuffer(), imgsize); + { + DVector<uint8_t>::Write wr = data.write(); + uint8_t* ptr = wr.ptr(); + memcpy(ptr, f->getBuffer(), imgsize); + } /* for (int i=0; i<h; i++) { int dstofs = i * w * f->mBpp; @@ -329,24 +397,32 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const { copymem(ptr + dstofs, f->getBuffer() + dstofs, w * f->mBpp); }; */ - frame = Image(); + Image frame = Image(); frame.create(w, h, 0, f->mBpp == 3 ? Image::FORMAT_RGB : Image::FORMAT_RGBA, data); clip->popFrame(); - return 1; + if (p_tex->get_width() == 0) { + p_tex->create(frame.get_width(),frame.get_height(),frame.get_format(),Texture::FLAG_VIDEO_SURFACE|Texture::FLAG_FILTER); + p_tex->set_data(frame); + } else { + + p_tex->set_data(frame); + }; }; +/* Image VideoStreamTheoraplayer::pop_frame() { Image ret = frame; frame = Image(); return ret; }; +*/ Image VideoStreamTheoraplayer::peek_frame() const { - return frame; + return Image(); }; void VideoStreamTheoraplayer::update(float p_time) { @@ -354,6 +430,12 @@ void VideoStreamTheoraplayer::update(float p_time) { if (!mgr) return; + if (!clip) + return; + + if (!playing || paused) + return; + //printf("video update!\n"); if (started) { if (clip->getNumReadyFrames() < 2) { @@ -370,6 +452,13 @@ void VideoStreamTheoraplayer::update(float p_time) { mgr->update(p_time); }; + +void VideoStreamTheoraplayer::set_audio_track(int p_idx) { + audio_track=p_idx; + if (clip) + clip->set_audio_track(audio_track); +} + void VideoStreamTheoraplayer::set_file(const String& p_file) { FileAccess* f = FileAccess::open(p_file, FileAccess::READ); @@ -380,13 +469,18 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { audio_factory = memnew(TPAudioGodotFactory); }; - mgr = memnew(TheoraVideoManager); - mgr->setAudioInterfaceFactory(audio_factory); + if (mgr == NULL) { + mgr = memnew(TheoraVideoManager); + mgr->setAudioInterfaceFactory(audio_factory); + }; + + int track = GLOBAL_DEF("theora/audio_track", 0); // hack if (p_file.find(".mp4") != -1) { std::string file = p_file.replace("res://", "").utf8().get_data(); - clip = mgr->createVideoClip(file); + clip = mgr->createVideoClip(file, TH_RGBX, 2, false, track); + //clip->set_audio_track(audio_track); memdelete(f); } else { @@ -395,6 +489,7 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { try { clip = mgr->createVideoClip(ds); + clip->set_audio_track(audio_track); } catch (_TheoraGenericException e) { printf("exception ocurred! %s\n", e.repr().c_str()); clip = NULL; @@ -407,19 +502,26 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { VideoStreamTheoraplayer::~VideoStreamTheoraplayer() { - if (mgr) { - memdelete(mgr); + stop(); + //if (mgr) { // this should be a singleton or static or something + // memdelete(mgr); + //}; + //mgr = NULL; + if (clip) { + mgr->destroyVideoClip(clip); + clip = NULL; }; - mgr = NULL; }; VideoStreamTheoraplayer::VideoStreamTheoraplayer() { - mgr = NULL; + //mgr = NULL; clip = NULL; started = false; playing = false; + paused = false; loop = false; + audio_track=0; }; diff --git a/drivers/theoraplayer/video_stream_theoraplayer.h b/drivers/theoraplayer/video_stream_theoraplayer.h index 063bf38953..d43c12609f 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.h +++ b/drivers/theoraplayer/video_stream_theoraplayer.h @@ -3,6 +3,7 @@ #include "scene/resources/video_stream.h" #include "io/resource_loader.h" +#include "scene/resources/texture.h" class TheoraVideoManager; class TheoraVideoClip; @@ -11,12 +12,14 @@ class VideoStreamTheoraplayer : public VideoStream { OBJ_TYPE(VideoStreamTheoraplayer,VideoStream); - mutable Image frame; - TheoraVideoManager* mgr; + mutable DVector<uint8_t> data; TheoraVideoClip* clip; bool started; bool playing; bool loop; + bool paused; + + int audio_track; public: @@ -37,12 +40,13 @@ public: virtual float get_length() const; virtual int get_pending_frame_count() const; - virtual Image pop_frame(); + virtual void pop_frame(Ref<ImageTexture> p_tex); virtual Image peek_frame() const; void update(float p_time); void set_file(const String& p_file); + void set_audio_track(int p_idx); ~VideoStreamTheoraplayer(); VideoStreamTheoraplayer(); diff --git a/drivers/trex/trex.c b/drivers/trex/trex.c index e63a248e9e..b3668c3a11 100644 --- a/drivers/trex/trex.c +++ b/drivers/trex/trex.c @@ -489,7 +489,7 @@ static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *s return cur;
}
case OP_WB:
- if(str == exp->_bol && !isspace(*str)
+ if((str == exp->_bol && !isspace(*str))
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 452d791d96..5f51865432 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -161,6 +161,7 @@ String DirAccessUnix::get_next() { } + _cishidden=(fname!="." && fname!=".." && fname.begins_with(".")); @@ -173,6 +174,11 @@ bool DirAccessUnix::current_is_dir() const { return _cisdir; } +bool DirAccessUnix::current_is_hidden() const { + + return _cishidden; +} + void DirAccessUnix::list_dir_end() { diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 119cb5c3f4..f6089ccfe1 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -50,12 +50,14 @@ class DirAccessUnix : public DirAccess { String current_dir; bool _cisdir; + bool _cishidden; public: virtual bool list_dir_begin(); ///< This starts dir listing virtual String get_next(); virtual bool current_is_dir() const; + virtual bool current_is_hidden() const; virtual void list_dir_end(); ///< diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 7f85526852..2f91eee90e 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -74,7 +74,7 @@ Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) { else if (p_mode_flags==WRITE) mode_string="wb"; else if (p_mode_flags==READ_WRITE) - mode_string="wb+"; + mode_string="rb+"; else return ERR_INVALID_PARAMETER; diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index c221743457..ad0d4e00ea 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "ip_unix.h" -#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) && !defined(WINRT_ENABLED) #ifdef WINDOWS_ENABLED @@ -50,11 +50,16 @@ #ifdef ANDROID_ENABLED #include "platform/android/ifaddrs_android.h" #else + #ifdef __FreeBSD__ + #include <sys/types.h> + #endif #include <ifaddrs.h> #endif #include <arpa/inet.h> #include <sys/socket.h> - + #ifdef __FreeBSD__ + #include <netinet/in.h> + #endif #endif IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp index fa1266b2df..4711f4f090 100644 --- a/drivers/unix/memory_pool_static_malloc.cpp +++ b/drivers/unix/memory_pool_static_malloc.cpp @@ -40,10 +40,9 @@ * so BE CAREFUL! */ - void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) { - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 return _alloc(p_bytes, p_description); @@ -123,7 +122,7 @@ void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) { void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) { - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 return _realloc(p_memory,p_bytes); #else @@ -172,7 +171,6 @@ void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) { bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr); bool is_list = ( ringlist == ringptr ); - RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr)); ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed @@ -213,7 +211,7 @@ void MemoryPoolStaticMalloc::free(void *p_ptr) { ERR_FAIL_COND( !MemoryPoolStatic::get_singleton()); - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 _free(p_ptr); #else diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index ef4cf644fd..d51a7c74e8 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -42,8 +42,11 @@ #include "dir_access_unix.h" #include "tcp_server_posix.h" #include "stream_peer_tcp_posix.h" +#include "packet_peer_udp_posix.h" - +#ifdef __FreeBSD__ +#include <sys/param.h> +#endif #include <stdarg.h> #include <sys/time.h> #include <sys/wait.h> @@ -115,6 +118,7 @@ void OS_Unix::initialize_core() { #ifndef NO_NETWORK TCPServerPosix::make_default(); StreamPeerTCPPosix::make_default(); + PacketPeerUDPPosix::make_default(); IP_Unix::make_default(); #endif mempool_static = new MemoryPoolStaticMalloc; @@ -303,7 +307,17 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo args.push_back((char*)cs[i].get_data());// shitty C cast args.push_back(0); +#ifdef __FreeBSD__ + if(p_path.find("/")) { + // exec name contains path so use it + execv(p_path.utf8().get_data(),&args[0]); + }else{ + // use program name and search through PATH to find it + execvp(getprogname(),&args[0]); + } +#else execv(p_path.utf8().get_data(),&args[0]); +#endif // still alive? something failed.. fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data()); abort(); @@ -330,6 +344,12 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo Error OS_Unix::kill(const ProcessID& p_pid) { int ret = ::kill(p_pid,SIGKILL); + if (!ret) { + //avoid zombie process + int st; + ::waitpid(p_pid,&st,0); + + } return ret?ERR_INVALID_PARAMETER:OK; } @@ -413,6 +433,12 @@ String OS_Unix::get_executable_path() const { return OS::get_executable_path(); } return b; +#elif defined(__FreeBSD__) + char resolved_path[MAXPATHLEN]; + + realpath(OS::get_executable_path().utf8().get_data(), resolved_path); + + return String(resolved_path); #else ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly."); return OS::get_executable_path(); diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp new file mode 100644 index 0000000000..26a0b29228 --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -0,0 +1,194 @@ +#include "packet_peer_udp_posix.h" + +#ifdef UNIX_ENABLED + + +#include <errno.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <stdio.h> + +#ifndef NO_FCNTL +#include <sys/fcntl.h> +#else +#include <sys/ioctl.h> +#endif + +#ifdef JAVASCRIPT_ENABLED +#include <arpa/inet.h> +#endif + + +int PacketPeerUDPPosix::get_available_packet_count() const { + + Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false); + if (err!=OK) + return 0; + + return queue_count; +} + +Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{ + + Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false); + if (err!=OK) + return err; + if (queue_count==0) + return ERR_UNAVAILABLE; + + uint32_t size; + rb.read((uint8_t*)&packet_ip.host,4,true); + rb.read((uint8_t*)&packet_port,4,true); + rb.read((uint8_t*)&size,4,true); + rb.read(packet_buffer,size,true); + --queue_count; + *r_buffer=packet_buffer; + r_buffer_size=size; + return OK; + +} +Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ + + int sock = _get_socket(); + ERR_FAIL_COND_V( sock == -1, FAILED ); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(peer_port); + addr.sin_addr = *((struct in_addr*)&peer_addr.host); + + errno = 0; + int err; + + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + + if (errno != EAGAIN) { + return FAILED; + } + } + + return OK; +} + +int PacketPeerUDPPosix::get_max_packet_size() const{ + + return 512; // uhm maybe not +} + +Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){ + + close(); + int sock = _get_socket(); + if (sock == -1 ) + return ERR_CANT_CREATE; + sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(p_port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + close(); + return ERR_UNAVAILABLE; + } + printf("UDP Connection listening on port %i bufsize %i \n", p_port,p_recv_buffer_size); + rb.resize(nearest_shift(p_recv_buffer_size)); + return OK; +} + +void PacketPeerUDPPosix::close(){ + + if (sockfd != -1) + ::close(sockfd); + sockfd=-1; + rb.resize(8); + queue_count=0; +} + + +Error PacketPeerUDPPosix::wait() { + + return _poll(true); +} + +Error PacketPeerUDPPosix::_poll(bool p_wait) { + + struct sockaddr_in from = {0}; + socklen_t len = sizeof(struct sockaddr_in); + int ret; + while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { + rb.write((uint8_t*)&from.sin_addr, 4); + uint32_t port = ntohs(from.sin_port); + rb.write((uint8_t*)&port, 4); + rb.write((uint8_t*)&ret, 4); + rb.write(recv_buffer, ret); + len = sizeof(struct sockaddr_in); + ++queue_count; + }; + + if (ret == 0 || (ret == -1 && errno != EAGAIN) ) { + close(); + return FAILED; + }; + + return OK; +} +bool PacketPeerUDPPosix::is_listening() const{ + + return sockfd!=-1; +} + +IP_Address PacketPeerUDPPosix::get_packet_address() const { + + return packet_ip; +} + +int PacketPeerUDPPosix::get_packet_port() const{ + + return packet_port; +} + +int PacketPeerUDPPosix::_get_socket() { + + if (sockfd != -1) + return sockfd; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ERR_FAIL_COND_V( sockfd == -1, -1 ); + //fcntl(sockfd, F_SETFL, O_NONBLOCK); + + return sockfd; +} + + +void PacketPeerUDPPosix::set_send_address(const IP_Address& p_address,int p_port) { + + peer_addr=p_address; + peer_port=p_port; +} + +PacketPeerUDP* PacketPeerUDPPosix::_create() { + + return memnew(PacketPeerUDPPosix); +}; + +void PacketPeerUDPPosix::make_default() { + + PacketPeerUDP::_create = PacketPeerUDPPosix::_create; +}; + + +PacketPeerUDPPosix::PacketPeerUDPPosix() { + + sockfd=-1; + packet_port=0; + queue_count=0; + peer_port=0; +} + +PacketPeerUDPPosix::~PacketPeerUDPPosix() { + + close(); +} +#endif diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h new file mode 100644 index 0000000000..b14568eb5f --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.h @@ -0,0 +1,57 @@ +#ifndef PACKET_PEER_UDP_POSIX_H +#define PACKET_PEER_UDP_POSIX_H + +#ifdef UNIX_ENABLED + +#include "io/packet_peer_udp.h" +#include "ring_buffer.h" + +class PacketPeerUDPPosix : public PacketPeerUDP { + + + enum { + PACKET_BUFFER_SIZE=65536 + }; + + mutable RingBuffer<uint8_t> rb; + uint8_t recv_buffer[PACKET_BUFFER_SIZE]; + mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; + IP_Address packet_ip; + int packet_port; + mutable int queue_count; + int sockfd; + + IP_Address peer_addr; + int peer_port; + + _FORCE_INLINE_ int _get_socket(); + + static PacketPeerUDP* _create(); + virtual Error _poll(bool p_block); + +public: + + virtual int get_available_packet_count() const; + virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const; + virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size); + + virtual int get_max_packet_size() const; + + virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual void close(); + virtual Error wait(); + virtual bool is_listening() const; + + virtual IP_Address get_packet_address() const; + virtual int get_packet_port() const; + + virtual void set_send_address(const IP_Address& p_address,int p_port); + + static void make_default(); + + PacketPeerUDPPosix(); + ~PacketPeerUDPPosix(); +}; + +#endif // PACKET_PEER_UDP_POSIX_H +#endif diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub index 1c7cccc427..2c137629ac 100644 --- a/drivers/vorbis/SCsub +++ b/drivers/vorbis/SCsub @@ -3,6 +3,9 @@ Import('env') sources = [ "vorbis/audio_stream_ogg_vorbis.cpp", +] + +sources_lib = [ "vorbis/analysis.c", #"vorbis/barkmel.c", "vorbis/bitrate.c", @@ -32,3 +35,6 @@ sources = [ env.drivers_sources += sources +if env['theora'] != "yes" or env['use_theoraplayer_binary'] != "yes": + env.drivers_sources += sources_lib + diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.cpp b/drivers/vorbis/audio_stream_ogg_vorbis.cpp index d9b7b1d161..996f75d165 100644 --- a/drivers/vorbis/audio_stream_ogg_vorbis.cpp +++ b/drivers/vorbis/audio_stream_ogg_vorbis.cpp @@ -215,7 +215,7 @@ AudioStreamOGGVorbis::UpdateMode AudioStreamOGGVorbis::get_update_mode() const { bool AudioStreamOGGVorbis::is_playing() const { - return playing; + return playing || (get_total() - get_todo() -1 > 0); } float AudioStreamOGGVorbis::get_pos() const { diff --git a/drivers/vorbis/codebook.c b/drivers/vorbis/codebook.c index 759d7b4254..8a928cebb9 100644 --- a/drivers/vorbis/codebook.c +++ b/drivers/vorbis/codebook.c @@ -248,7 +248,7 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){ } /* quantized values */ - if((quantvals*s->q_quant+7>>3)>opb->storage-oggpack_bytes(opb)) + if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb)) goto _eofout; s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals); for(i=0;i<quantvals;i++) diff --git a/drivers/vorbis/floor1.c b/drivers/vorbis/floor1.c index 9f3154a6a3..ae3dcedb1f 100644 --- a/drivers/vorbis/floor1.c +++ b/drivers/vorbis/floor1.c @@ -1035,7 +1035,7 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ } } - fit_value[i]=val+predicted&0x7fff; + fit_value[i]=(val+predicted)&0x7fff; fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; diff --git a/drivers/vorbis/os.h b/drivers/vorbis/os.h index 276b4decc7..3df1d194e9 100644 --- a/drivers/vorbis/os.h +++ b/drivers/vorbis/os.h @@ -120,7 +120,7 @@ static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise, /* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the * 64 bit compiler */ -#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) +#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) && !defined(WINDOWSPHONE_ENABLED) # define VORBIS_FPU_CONTROL typedef ogg_int16_t vorbis_fpu_control; diff --git a/drivers/webp/dsp/dsp.h b/drivers/webp/dsp/dsp.h index 9ff53174d4..afe30413c6 100644 --- a/drivers/webp/dsp/dsp.h +++ b/drivers/webp/dsp/dsp.h @@ -33,7 +33,7 @@ extern "C" { #define WEBP_ANDROID_NEON // Android targets that might support NEON #endif -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED) +#if ( (defined(__ARM_NEON__) && !defined(__aarch64__)) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED) #define WEBP_USE_NEON #endif diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h index d80b497149..43cd948fd4 100644 --- a/drivers/webp/utils/bit_reader.h +++ b/drivers/webp/utils/bit_reader.h @@ -1,3 +1,4 @@ +// // Copyright 2010 Google Inc. All Rights Reserved. // // This code is licensed under the same terms as WebM: diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index df6cc6c5e2..4c265a1ab2 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -68,6 +68,7 @@ struct DirAccessWindowsPrivate { bool DirAccessWindows::list_dir_begin() { _cisdir=false; + _cishidden=false; if (unicode) { list_dir_end(); @@ -95,6 +96,8 @@ String DirAccessWindows::get_next() { if (unicode) { _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); + String name=p->fu.cFileName; if (FindNextFileW(p->h, &p->fu) == 0) { @@ -106,7 +109,9 @@ String DirAccessWindows::get_next() { return name; } else { +#ifndef WINRT_ENABLED _cisdir=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + _cishidden=(p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); String name=p->f.cFileName; @@ -117,7 +122,8 @@ String DirAccessWindows::get_next() { } return name; - +#endif + return ""; } } @@ -126,6 +132,11 @@ bool DirAccessWindows::current_is_dir() const { return _cisdir; } +bool DirAccessWindows::current_is_hidden() const { + + return _cishidden; +} + void DirAccessWindows::list_dir_end() { if (p->h!=INVALID_HANDLE_VALUE) { @@ -268,7 +279,7 @@ Error DirAccessWindows::make_dir(String p_dir) { return OK; }; - if (err == ERROR_ALREADY_EXISTS) { + if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) { return ERR_ALREADY_EXISTS; }; @@ -358,6 +369,7 @@ bool DirAccessWindows::dir_exists(String p_dir) { return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); } else { +#ifndef WINRT_ENABLED DWORD fileAttr; fileAttr = GetFileAttributesExA(p_dir.ascii().get_data(), GetFileExInfoStandard, &fileInfo); @@ -366,8 +378,8 @@ bool DirAccessWindows::dir_exists(String p_dir) { return (fileAttr&FILE_ATTRIBUTE_DIRECTORY); +#endif } - return false; } diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 36530ba9b3..4a668a7364 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -58,12 +58,14 @@ class DirAccessWindows : public DirAccess { bool unicode; bool _cisdir; + bool _cishidden; public: virtual bool list_dir_begin(); ///< This starts dir listing 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/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 3cd065841f..19a62967ea 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -28,14 +28,20 @@ /*************************************************************************/ #ifdef WINDOWS_ENABLED +#define WINVER 0x0500 + +#include <windows.h> +#include "shlwapi.h" #include "file_access_windows.h" + #include <sys/types.h> #include <sys/stat.h> #include <wchar.h> #include <tchar.h> #include "print_string.h" + #ifdef _MSC_VER #define S_ISREG(m) ((m)&_S_IFREG) #endif @@ -54,7 +60,6 @@ void FileAccessWindows::check_errors() const { Error FileAccessWindows::_open(const String& p_filename, int p_mode_flags) { String filename=fix_path(p_filename); - if (f) close(); @@ -66,7 +71,7 @@ Error FileAccessWindows::_open(const String& p_filename, int p_mode_flags) { else if (p_mode_flags==WRITE) mode_string=L"wb"; else if (p_mode_flags==READ_WRITE) - mode_string=L"wb+"; + mode_string=L"rb+"; else return ERR_INVALID_PARAMETER; @@ -112,10 +117,20 @@ void FileAccessWindows::close() { //unlink(save_path.utf8().get_data()); //print_line("renaming.."); - _wunlink(save_path.c_str()); //unlink if exists - int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); + //_wunlink(save_path.c_str()); //unlink if exists + //int rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str()); + + + bool rename_error; + if (!PathFileExistsW(save_path.c_str())) { + //creating new file + rename_error = _wrename((save_path+".tmp").c_str(),save_path.c_str())!=0; + } else { + //atomic replace for existing file + rename_error = !ReplaceFileW(save_path.c_str(), (save_path+".tmp").c_str(), NULL, 2|4, NULL, NULL); + } save_path=""; - ERR_FAIL_COND( rename_error != 0); + ERR_FAIL_COND( rename_error ); } diff --git a/main/main.cpp b/main/main.cpp index fa7ce50c6d..f0e376a045 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -111,7 +111,7 @@ static String unescape_cmdline(const String& p_str) { void Main::print_help(const char* p_binary) { - OS::get_singleton()->print(VERSION_FULL_NAME" (c) 2008-2010 Juan Linietsky, Ariel Manzur.\n"); + OS::get_singleton()->print(VERSION_FULL_NAME" (c) 2008-2015 Juan Linietsky, Ariel Manzur.\n"); OS::get_singleton()->print("Usage: %s [options] [scene]\n",p_binary); OS::get_singleton()->print("Options:\n"); OS::get_singleton()->print("\t-path [dir] : Path to a game, containing engine.cfg\n"); @@ -147,6 +147,7 @@ void Main::print_help(const char* p_binary) { OS::get_singleton()->print(", "); OS::get_singleton()->print("%s",OS::get_singleton()->get_audio_driver_name(i)); } + OS::get_singleton()->print(")\n"); OS::get_singleton()->print("\t-rthread <mode>\t : Render Thread Mode ('unsafe', 'safe', 'separate)."); OS::get_singleton()->print(")\n"); OS::get_singleton()->print("\t-s,-script [script] : Run a script.\n"); @@ -819,6 +820,8 @@ Error Main::setup2() { register_module_types(); register_driver_types(); + ScriptServer::init_languages(); + MAIN_PRINT("Main: Load Translations"); translation_server->setup(); //register translations, load them, etc. @@ -961,7 +964,7 @@ bool Main::start() { MainLoop *main_loop=NULL; if (editor) { - main_loop = memnew(SceneMainLoop); + main_loop = memnew(SceneTree); }; if (test!="") { @@ -979,7 +982,7 @@ bool Main::start() { ERR_EXPLAIN("Can't load script: "+script); ERR_FAIL_COND_V(script_res.is_null(),false); - if( script_res->can_instance() /*&& script_res->inherits_from("SceneMainLoopScripted")*/) { + if( script_res->can_instance() /*&& script_res->inherits_from("SceneTreeScripted")*/) { StringName instance_type=script_res->get_instance_base_type(); @@ -1005,7 +1008,7 @@ bool Main::start() { } if (!main_loop && main_loop_type=="") - main_loop_type="SceneMainLoop"; + main_loop_type="SceneTree"; if (!main_loop) { if (!ObjectTypeDB::type_exists(main_loop_type)) { @@ -1030,9 +1033,9 @@ bool Main::start() { } } - if (main_loop->is_type("SceneMainLoop")) { + if (main_loop->is_type("SceneTree")) { - SceneMainLoop *sml = main_loop->cast_to<SceneMainLoop>(); + SceneTree *sml = main_loop->cast_to<SceneTree>(); #ifdef TOOLS_ENABLED @@ -1060,19 +1063,19 @@ bool Main::start() { String stretch_aspect = GLOBAL_DEF("display/stretch_aspect","ignore"); Size2i stretch_size = Size2(GLOBAL_DEF("display/width",0),GLOBAL_DEF("display/height",0)); - SceneMainLoop::StretchMode sml_sm=SceneMainLoop::STRETCH_MODE_DISABLED; + SceneTree::StretchMode sml_sm=SceneTree::STRETCH_MODE_DISABLED; if (stretch_mode=="2d") - sml_sm=SceneMainLoop::STRETCH_MODE_2D; + sml_sm=SceneTree::STRETCH_MODE_2D; else if (stretch_mode=="viewport") - sml_sm=SceneMainLoop::STRETCH_MODE_VIEWPORT; + sml_sm=SceneTree::STRETCH_MODE_VIEWPORT; - SceneMainLoop::StretchAspect sml_aspect=SceneMainLoop::STRETCH_ASPECT_IGNORE; + SceneTree::StretchAspect sml_aspect=SceneTree::STRETCH_ASPECT_IGNORE; if (stretch_aspect=="keep") - sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP; + sml_aspect=SceneTree::STRETCH_ASPECT_KEEP; else if (stretch_aspect=="keep_width") - sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP_WIDTH; + sml_aspect=SceneTree::STRETCH_ASPECT_KEEP_WIDTH; else if (stretch_aspect=="keep_height") - sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP_HEIGHT; + sml_aspect=SceneTree::STRETCH_ASPECT_KEEP_HEIGHT; sml->set_screen_stretch(sml_sm,sml_aspect,stretch_size); diff --git a/main/performance.cpp b/main/performance.cpp index 9999cc0ae0..5b76472ceb 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -133,7 +133,7 @@ float Performance::get_monitor(Monitor p_monitor) const { MainLoop *ml = OS::get_singleton()->get_main_loop(); if (!ml) return 0; - SceneMainLoop *sml = ml->cast_to<SceneMainLoop>(); + SceneTree *sml = ml->cast_to<SceneTree>(); if (!sml) return 0; return sml->get_node_count(); diff --git a/makefile b/makefile deleted file mode 100644 index d24bd0cd32..0000000000 --- a/makefile +++ /dev/null @@ -1,30 +0,0 @@ -#*************************************************************************/ -#* This file is part of: */ -#* GODOT ENGINE */ -#* http://www.godotengine.org */ -#*************************************************************************/ -# Simple makefile to give support for external C/C++ IDEs */ -#*************************************************************************/ - -# Default build -all: debug - -# Release Build -release: - scons target="release" bin/godot - -# Profile Build -profile: - scons target="profile" bin/godot - -# Debug Build -debug: - # Debug information (code size gets severely affected): - # g: Default (same as g2) - # g0: no debug info - # g1: minimal info - # g3: maximal info - scons target="debug" CCFLAGS="-g" bin/godot - -clean: - scons -c bin/godot diff --git a/methods.py b/methods.py index 77da82fe24..9608b1b61d 100755 --- a/methods.py +++ b/methods.py @@ -1083,44 +1083,13 @@ def build_gles2_headers( target, source, env ): def update_version(): - rev = 0 + rev = "custom_build" - try: - f = open("custom_version.txt","rb") - rev = int( f.readline().strip() ) - except: - pass - - if (rev==0): - try: - f = open(".svn/entries") - line = f.readline(); - next_rev = False - while line != "": - line = line.rstrip('\r\n') - if next_rev: - rev = line - break - if line == "dir": - next_rev = True - line = f.readline(); - - if rev != 0: - f = open("version.py") - ver = f.read() - import re - ver = re.sub(r'\$Rev: \d* \$', '$Rev: '+str(rev)+' $', ver) - f = open("version.py", "wb") - f.write(ver) - f.close() - - except: - pass - + if (os.getenv("BUILD_REVISION")!=None): + rev=os.getenv("BUILD_REVISION") + print("Using custom revision: "+rev) import version - - rev=version.revision - rev=rev[5:-1].strip() + f=open("core/version.h","wb") f.write("#define VERSION_SHORT_NAME "+str(version.short_name)+"\n") @@ -1322,6 +1291,14 @@ def android_module_manifest(self,file): base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file f = open(base_path,"rb") self.android_manifest_chunk+=f.read() +def android_module_permission(self,file): + base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file + f = open(base_path,"rb") + self.android_permission_chunk+=f.read() +def android_module_attribute(self,file): + base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file + f = open(base_path,"rb") + self.android_appattributes_chunk+=f.read() def disable_module(self): self.disabled_modules.append(self.current_module) @@ -1347,3 +1324,39 @@ def save_active_platforms(apnames,ap): logow = open(wf,"wb") logow.write(str) + +def colored(sys,env): + + #If the output is not a terminal, do nothing + if not sys.stdout.isatty(): + return + + colors = {} + colors['cyan'] = '\033[96m' + colors['purple'] = '\033[95m' + colors['blue'] = '\033[94m' + colors['green'] = '\033[92m' + colors['yellow'] = '\033[93m' + colors['red'] = '\033[91m' + colors['end'] = '\033[0m' + + compile_source_message = '%sCompiling %s==> %s$SOURCE%s' % (colors['blue'], colors['purple'], colors['yellow'], colors['end']) + java_compile_source_message = '%sCompiling %s==> %s$SOURCE%s' % (colors['blue'], colors['purple'], colors['yellow'], colors['end']) + compile_shared_source_message = '%sCompiling shared %s==> %s$SOURCE%s' % (colors['blue'], colors['purple'], colors['yellow'], colors['end']) + link_program_message = '%sLinking Program %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end']) + link_library_message = '%sLinking Static Library %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end']) + ranlib_library_message = '%sRanlib Library %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end']) + link_shared_library_message = '%sLinking Shared Library %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end']) + java_library_message = '%sCreating Java Archive %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end']) + + env.Append( CXXCOMSTR=[compile_source_message] ) + env.Append( CCCOMSTR=[compile_source_message] ) + env.Append( SHCCCOMSTR=[compile_shared_source_message] ) + env.Append( SHCXXCOMSTR=[compile_shared_source_message] ) + env.Append( ARCOMSTR=[link_library_message] ) + env.Append( RANLIBCOMSTR=[ranlib_library_message] ) + env.Append( SHLINKCOMSTR=[link_shared_library_message] ) + env.Append( LINKCOMSTR=[link_program_message] ) + env.Append( JARCOMSTR=[java_library_message] ) + env.Append( JAVACCOMSTR=[java_compile_source_message] ) + diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index 45eac23450..278651d642 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -45,8 +45,13 @@ void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) return; error=p_error; - err_line=p_node->line; - err_column=p_node->column; + if (p_node) { + err_line=p_node->line; + err_column=p_node->column; + } else { + err_line=0; + err_column=0; + } } bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level) { @@ -65,18 +70,18 @@ bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::Operato return true; } -bool GDCompiler::_create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level) { +bool GDCompiler::_create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level,bool p_initializer) { ERR_FAIL_COND_V(on->arguments.size()!=2,false); - int src_address_a = _parse_expression(codegen,on->arguments[0],p_stack_level); + int src_address_a = _parse_expression(codegen,on->arguments[0],p_stack_level,false,p_initializer); if (src_address_a<0) return false; if (src_address_a&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) p_stack_level++; //uses stack for return, increase stack - int src_address_b = _parse_expression(codegen,on->arguments[1],p_stack_level); + int src_address_b = _parse_expression(codegen,on->arguments[1],p_stack_level,false,p_initializer); if (src_address_b<0) return false; @@ -111,6 +116,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser:: Variant::Operator var_op=Variant::OP_MAX; + switch(p_expression->op) { case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op=Variant::OP_ADD; break; @@ -123,6 +129,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser:: case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op=Variant::OP_BIT_AND; break; case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op=Variant::OP_BIT_OR; break; case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op=Variant::OP_BIT_XOR; break; + case GDParser::OperatorNode::OP_INIT_ASSIGN: case GDParser::OperatorNode::OP_ASSIGN: { //none @@ -133,12 +140,14 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser:: } } + bool initializer = p_expression->op==GDParser::OperatorNode::OP_INIT_ASSIGN; + if (var_op==Variant::OP_MAX) { - return _parse_expression(codegen,p_expression->arguments[1],p_stack_level); + return _parse_expression(codegen,p_expression->arguments[1],p_stack_level,false,initializer); } - if (!_create_binary_operator(codegen,p_expression,var_op,p_stack_level)) + if (!_create_binary_operator(codegen,p_expression,var_op,p_stack_level,initializer)) return -1; int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS); @@ -148,7 +157,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser:: } -int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root) { +int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root,bool p_initializer) { switch(p_expression->type) { @@ -165,21 +174,20 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre StringName identifier = in->name; // TRY STACK! - if (codegen.stack_identifiers.has(identifier)) { + if (!p_initializer && codegen.stack_identifiers.has(identifier)) { int pos = codegen.stack_identifiers[identifier]; return pos|(GDFunction::ADDR_TYPE_STACK_VARIABLE<<GDFunction::ADDR_BITS); } - //TRY ARGUMENTS! + //TRY MEMBERS! if (!codegen.function_node || !codegen.function_node->_static) { // TRY MEMBER VARIABLES! - //static function if (codegen.script->member_indices.has(identifier)) { - int idx = codegen.script->member_indices[identifier]; + int idx = codegen.script->member_indices[identifier].index; return idx|(GDFunction::ADDR_TYPE_MEMBER<<GDFunction::ADDR_BITS); //argument (stack root) } } @@ -520,7 +528,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre int ret = _parse_expression(codegen,on->arguments[i],slevel); if (ret<0) return ret; - if (ret&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) { + if (ret&(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)) { slevel++; codegen.alloc_stack(slevel); } @@ -686,6 +694,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: + case GDParser::OperatorNode::OP_INIT_ASSIGN: case GDParser::OperatorNode::OP_ASSIGN: { ERR_FAIL_COND_V(on->arguments.size()!=2,-1); @@ -843,7 +852,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre int slevel = p_stack_level; - int dst_address_a = _parse_expression(codegen,on->arguments[0],slevel); + int dst_address_a = _parse_expression(codegen,on->arguments[0],slevel,false,on->op==GDParser::OperatorNode::OP_INIT_ASSIGN); if (dst_address_a<0) return -1; @@ -1164,6 +1173,7 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * codegen.current_line=0; codegen.call_max=0; codegen.debug_stack=ScriptDebugger::get_singleton()!=NULL; + Vector<StringName> argnames; int stack_level=0; @@ -1171,6 +1181,9 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * for(int i=0;i<p_func->arguments.size();i++) { int idx = i; codegen.add_stack_identifier(p_func->arguments[i],i); +#ifdef TOOLS_ENABLED + argnames.push_back(p_func->arguments[i]); +#endif } stack_level=p_func->arguments.size(); } @@ -1245,6 +1258,9 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * if (p_func) gdfunc->_static=p_func->_static; +#ifdef TOOLS_ENABLED + gdfunc->arg_names=argnames; +#endif //constants if (codegen.constant_map.size()) { gdfunc->_constant_count=codegen.constant_map.size(); @@ -1507,8 +1523,12 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars #endif } - int new_idx = p_script->member_indices.size(); - p_script->member_indices[name]=new_idx; + //int new_idx = p_script->member_indices.size(); + GDScript::MemberInfo minfo; + minfo.index = p_script->member_indices.size(); + minfo.setter = p_class->variables[i].setter; + minfo.getter = p_class->variables[i].getter; + p_script->member_indices[name]=minfo; p_script->members.insert(name); } @@ -1571,6 +1591,48 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars return err; } +#ifdef DEBUG_ENABLED + //validate setters/getters if debug is enabled + for(int i=0;i<p_class->variables.size();i++) { + + if (p_class->variables[i].setter) { + const Map<StringName,GDFunction>::Element *E=p_script->get_member_functions().find(p_class->variables[i].setter); + if (!E) { + _set_error("Setter function '"+String(p_class->variables[i].setter)+"' not found in class.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + if (E->get().is_static()) { + + _set_error("Setter function '"+String(p_class->variables[i].setter)+"' is static.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + } + if (p_class->variables[i].getter) { + const Map<StringName,GDFunction>::Element *E=p_script->get_member_functions().find(p_class->variables[i].getter); + if (!E) { + _set_error("Getter function '"+String(p_class->variables[i].getter)+"' not found in class.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + if (E->get().is_static()) { + + _set_error("Getter function '"+String(p_class->variables[i].getter)+"' is static.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + } + } +#endif return OK; } diff --git a/modules/gdscript/gd_compiler.h b/modules/gdscript/gd_compiler.h index cda221dab0..0c34c23b25 100644 --- a/modules/gdscript/gd_compiler.h +++ b/modules/gdscript/gd_compiler.h @@ -37,77 +37,65 @@ class GDCompiler { const GDParser *parser; struct CodeGen { - - GDScript *script; const GDParser::ClassNode *class_node; const GDParser::FunctionNode *function_node; - - - bool debug_stack; - - - List< Map<StringName,int> > stack_id_stack; - Map<StringName,int> stack_identifiers; - - List<GDFunction::StackDebug> stack_debug; - List< Map<StringName,int> > block_identifier_stack; - Map<StringName,int> block_identifiers; - - - void add_stack_identifier(const StringName& p_id,int p_stackpos) { - - stack_identifiers[p_id]=p_stackpos; - if (debug_stack) { - - block_identifiers[p_id]=p_stackpos; - GDFunction::StackDebug sd; - sd.added=true; - sd.line=current_line; - sd.identifier=p_id; - sd.pos=p_stackpos; - stack_debug.push_back(sd); - } - } - - void push_stack_identifiers() { - - stack_id_stack.push_back( stack_identifiers ); - if (debug_stack) { - - block_identifier_stack.push_back(block_identifiers); - block_identifiers.clear(); - } - } - - void pop_stack_identifiers() { - - stack_identifiers = stack_id_stack.back()->get(); - stack_id_stack.pop_back(); - - if (debug_stack) { - for (Map<StringName,int>::Element *E=block_identifiers.front();E;E=E->next()) { - - GDFunction::StackDebug sd; - sd.added=false; - sd.identifier=E->key(); - sd.line=current_line; - sd.pos=E->get(); - stack_debug.push_back(sd); - } - block_identifiers=block_identifier_stack.back()->get(); - block_identifier_stack.pop_back(); - } - - } - - - // int get_identifier_pos(const StringName& p_dentifier) const; + bool debug_stack; + + List< Map<StringName,int> > stack_id_stack; + Map<StringName,int> stack_identifiers; + + List<GDFunction::StackDebug> stack_debug; + List< Map<StringName,int> > block_identifier_stack; + Map<StringName,int> block_identifiers; + + void add_stack_identifier(const StringName& p_id,int p_stackpos) { + stack_identifiers[p_id]=p_stackpos; + if (debug_stack) { + block_identifiers[p_id]=p_stackpos; + GDFunction::StackDebug sd; + sd.added=true; + sd.line=current_line; + sd.identifier=p_id; + sd.pos=p_stackpos; + stack_debug.push_back(sd); + } + } + + void push_stack_identifiers() { + stack_id_stack.push_back( stack_identifiers ); + if (debug_stack) { + + block_identifier_stack.push_back(block_identifiers); + block_identifiers.clear(); + } + } + + void pop_stack_identifiers() { + stack_identifiers = stack_id_stack.back()->get(); + stack_id_stack.pop_back(); + + if (debug_stack) { + for (Map<StringName,int>::Element *E=block_identifiers.front();E;E=E->next()) { + + GDFunction::StackDebug sd; + sd.added=false; + sd.identifier=E->key(); + sd.line=current_line; + sd.pos=E->get(); + stack_debug.push_back(sd); + } + block_identifiers=block_identifier_stack.back()->get(); + block_identifier_stack.pop_back(); + } + } + + + //int get_identifier_pos(const StringName& p_dentifier) const; HashMap<Variant,int,VariantHasher> constant_map; Map<StringName,int> name_map; int get_name_map_pos(const StringName& p_identifier) { - int ret; if (!name_map.has(p_identifier)) { ret=name_map.size(); @@ -118,11 +106,7 @@ class GDCompiler { return ret; } - - int get_constant_pos(const Variant& p_constant) { - - if (constant_map.has(p_constant)) return constant_map[p_constant]; int pos = constant_map.size(); @@ -134,7 +118,7 @@ class GDCompiler { void alloc_stack(int p_level) { if (p_level >= stack_max) stack_max=p_level+1; } void alloc_call(int p_params) { if (p_params >= call_max) call_max=p_params; } - int current_line; + int current_line; int stack_max; int call_max; }; @@ -153,11 +137,11 @@ class GDCompiler { void _set_error(const String& p_error,const GDParser::Node *p_node); bool _create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level); - bool _create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level); + bool _create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level,bool p_initializer=false); //int _parse_subexpression(CodeGen& codegen,const GDParser::BlockNode *p_block,const GDParser::Node *p_expression); int _parse_assign_right_expression(CodeGen& codegen,const GDParser::OperatorNode *p_expression, int p_stack_level); - int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false); + int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false,bool p_initializer=false); Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1); Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func); Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class); diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 9610f9827f..df091fbcc9 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -28,11 +28,12 @@ /*************************************************************************/ #include "gd_script.h" #include "gd_compiler.h" - +#include "globals.h" void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { p_delimiters->push_back("#"); + p_delimiters->push_back("\"\"\""); } void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { @@ -50,7 +51,7 @@ String GDScriptLanguage::get_template(const String& p_class_name, const String& "# var a=2\n"+ "# var b=\"textvar\"\n\n"+ "func _ready():\n"+ - "\t# Initalization here\n"+ + "\t# Initialization here\n"+ "\tpass\n"+ "\n"+ "\n"; @@ -65,7 +66,7 @@ bool GDScriptLanguage::validate(const String& p_script, int &r_line_error,int &r GDParser parser; - Error err = parser.parse(p_script,p_path.get_base_dir(),true); + Error err = parser.parse(p_script,p_path.get_base_dir(),true,p_path); if (err) { r_line_error=parser.get_error_line(); r_col_error=parser.get_error_column(); @@ -250,12 +251,12 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p ERR_FAIL_COND( script.is_null() ); - const Map<StringName,int>& mi = script->debug_get_member_indices(); + const Map<StringName,GDScript::MemberInfo>& mi = script->debug_get_member_indices(); - for(const Map<StringName,int>::Element *E=mi.front();E;E=E->next()) { + for(const Map<StringName,GDScript::MemberInfo>::Element *E=mi.front();E;E=E->next()) { p_members->push_back(E->key()); - p_values->push_back( instance->debug_get_member_by_index(E->get())); + p_values->push_back( instance->debug_get_member_by_index(E->get().index)); } } @@ -311,485 +312,1588 @@ String GDScriptLanguage::make_function(const String& p_class,const String& p_nam } -static void _parse_native_symbols(const StringName& p_native,bool p_static,List<String>* r_options) { +#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) - if (!p_static) { - List<MethodInfo> methods; - ObjectTypeDB::get_method_list(p_native,&methods); - for(List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { - if (!E->get().name.begins_with("_")) { - r_options->push_back(E->get().name); - } +struct GDCompletionIdentifier { + + StringName obj_type; + Variant::Type type; + Variant value; //im case there is a value, also return it +}; + + + +static GDCompletionIdentifier _get_type_from_variant(const Variant& p_variant) { + + GDCompletionIdentifier t; + t.type=p_variant.get_type(); + t.value=p_variant; + if (p_variant.get_type()==Variant::OBJECT) { + Object *obj = p_variant; + if (obj) { + //if (obj->cast_to<GDNativeClass>()) { + // t.obj_type=obj->cast_to<GDNativeClass>()->get_name(); + // t.value=Variant(); + //} else { + t.obj_type=obj->get_type(); + //} } } + return t; +} - List<String> constants; - ObjectTypeDB::get_integer_constant_list(p_native,&constants); +static GDCompletionIdentifier _get_type_from_pinfo(const PropertyInfo& p_info) { - for(List<String>::Element *E=constants.front();E;E=E->next()) { - r_options->push_back(E->get()); + GDCompletionIdentifier t; + t.type=p_info.type; + if (p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) { + t.obj_type=p_info.hint_string; } - + return t; } +struct GDCompletionContext { -static bool _parse_script_symbols(const Ref<GDScript>& p_script,bool p_static,List<String>* r_options,List<String>::Element *p_indices); + const GDParser::ClassNode *_class; + const GDParser::FunctionNode *function; + const GDParser::BlockNode *block; + Object* base; + String base_path; +}; -static bool _parse_completion_variant(const Variant& p_var,List<String>* r_options,List<String>::Element *p_indices) { - if (p_indices) { +static Ref<Reference> _get_parent_class(GDCompletionContext& context) { - bool ok; - Variant si = p_var.get(p_indices->get(),&ok); - if (!ok) - return false; - return _parse_completion_variant(si,r_options,p_indices->next()); - } else { - switch(p_var.get_type()) { + if (context._class->extends_used) { + //do inheritance + String path = context._class->extends_file; - case Variant::DICTIONARY: { + Ref<GDScript> script; + Ref<GDNativeClass> native; - Dictionary d=p_var; - List<Variant> vl; - d.get_key_list(&vl); - for (List<Variant>::Element *E=vl.front();E;E=E->next()) { + if (path!="") { + //path (and optionally subclasses) - if (E->get().get_type()==Variant::STRING) - r_options->push_back(E->get()); - } + if (path.is_rel_path()) { + path=context.base_path.plus_file(path); + } + script = ResourceLoader::load(path); + if (script.is_null()) { + return REF(); + } + if (script->is_valid()) { + + return REF(); + } + //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid)); + + if (context._class->extends_class.size()) { + + for(int i=0;i<context._class->extends_class.size();i++) { + + String sub = context._class->extends_class[i]; + if (script->get_subclasses().has(sub)) { - List<MethodInfo> ml; - p_var.get_method_list(&ml); - for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) { - r_options->push_back(E->get().name); + script=script->get_subclasses()[sub]; + } else { + + return REF(); + } } + } - } break; - case Variant::OBJECT: { + if (script.is_valid()) + return script; + } else { - Object *o=p_var; - if (o) { - print_line("OBJECT: "+o->get_type()); - if (p_var.is_ref() && o->cast_to<GDScript>()) { + if (context._class->extends_class.size()==0) { + ERR_PRINT("BUG"); + return REF(); + } - Ref<GDScript> gds = p_var; - _parse_script_symbols(gds,true,r_options,NULL); - } else if (o->is_type("GDNativeClass")){ + String base=context._class->extends_class[0]; + const GDParser::ClassNode *p = context._class->owner; + Ref<GDScript> base_class; +#if 0 + while(p) { + + if (p->subclasses.has(base)) { + + base_class=p->subclasses[base]; + break; + } + p=p->_owner; + } +#endif + if (base_class.is_valid()) { +#if 0 + for(int i=1;i<context._class->extends_class.size();i++) { - GDNativeClass *gnc = o->cast_to<GDNativeClass>(); - _parse_native_symbols(gnc->get_name(),false,r_options); + String subclass=context._class->extends_class[i]; + + if (base_class->subclasses.has(subclass)) { + + base_class=base_class->subclasses[subclass]; } else { - print_line("REGULAR BLEND"); - _parse_native_symbols(o->get_type(),false,r_options); + print_line("Could not find subclass: "+subclass); + return _get_type_from_class(context); //fail please } } - } break; - default: { + script=base_class; +#endif + + } else { + + if (context._class->extends_class.size()>1) { + + return REF(); + - List<PropertyInfo> pi; - p_var.get_property_list(&pi); - for(List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) { - r_options->push_back(E->get().name); } - List<StringName> cl; + //if not found, try engine classes + if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { - p_var.get_numeric_constants_for_type(p_var.get_type(),&cl); - for(List<StringName>::Element *E=cl.front();E;E=E->next()) { - r_options->push_back(E->get()); + return REF(); } - List<MethodInfo> ml; - p_var.get_method_list(&ml); - for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) { - r_options->push_back(E->get().name); + int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; + native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; + if (!native.is_valid()) { + + print_line("Global not a class: '"+base+"'"); + } + return native; + } + - } break; } - return true; } + return Ref<Reference>(); +} + + +static GDCompletionIdentifier _get_native_class(GDCompletionContext& context) { + + //eeh... + GDCompletionIdentifier id; + id.type=Variant::NIL; + + REF pc = _get_parent_class(context); + if (!pc.is_valid()) { + return id; + } + Ref<GDNativeClass> nc = pc; + Ref<GDScript> s = pc; + + if (s.is_null() && nc.is_null()) { + return id; + } + while(!s.is_null()) { + nc=s->get_native(); + s=s->get_base(); + } + if (nc.is_null()) { + return id; + } + + + id.type=Variant::OBJECT; + if (context.base) + id.value=context.base; + id.obj_type=nc->get_name(); + return id; } +static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type); -static void _parse_expression_node(const GDParser::Node *p_node,List<String>* r_options,List<String>::Element *p_indices) { +static bool _guess_expression_type(GDCompletionContext& context,const GDParser::Node* p_node,int p_line,GDCompletionIdentifier &r_type) { if (p_node->type==GDParser::Node::TYPE_CONSTANT) { const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(p_node); - _parse_completion_variant(cn->value,r_options,p_indices?p_indices->next():NULL); + + r_type=_get_type_from_variant(cn->value); + + return true; } else if (p_node->type==GDParser::Node::TYPE_DICTIONARY) { - const GDParser::DictionaryNode *dn=static_cast<const GDParser::DictionaryNode*>(p_node); - for(int i=0;i<dn->elements.size();i++) { + r_type.type=Variant::DICTIONARY; - if (dn->elements[i].key->type==GDParser::Node::TYPE_CONSTANT) { - const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(dn->elements[i].key); - if (cn->value.get_type()==Variant::STRING) { + //what the heck, fill it anyway + const GDParser::DictionaryNode *an = static_cast<const GDParser::DictionaryNode *>(p_node); + Dictionary d; + for(int i=0;i<an->elements.size();i++) { + GDCompletionIdentifier k; + if (_guess_expression_type(context,an->elements[i].key,p_line,k) && k.value.get_type()!=Variant::NIL) { + GDCompletionIdentifier v; + if (_guess_expression_type(context,an->elements[i].value,p_line,v)) { + d[k.value]=v.value; + } - String str=cn->value; - if (p_indices) { + } + } + r_type.value=d; + return true; + } else if (p_node->type==GDParser::Node::TYPE_ARRAY) { + + r_type.type=Variant::ARRAY; + //what the heck, fill it anyway + const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(p_node); + Array arr; + arr.resize(an->elements.size()); + for(int i=0;i<an->elements.size();i++) { + GDCompletionIdentifier ci; + if (_guess_expression_type(context,an->elements[i],p_line,ci)) { + arr[i]=ci.value; + } + } + r_type.value=arr; + return true; - if (str==p_indices->get()) { - _parse_expression_node(dn->elements[i].value,r_options,p_indices->next()); - return; + } else if (p_node->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) { + + MethodInfo mi = GDFunctions::get_info(static_cast<const GDParser::BuiltInFunctionNode*>(p_node)->function); + r_type=_get_type_from_pinfo(mi.return_val); + + return true; + } else if (p_node->type==GDParser::Node::TYPE_IDENTIFIER) { + + return _guess_identifier_type(context,p_line-1,static_cast<const GDParser::IdentifierNode *>(p_node)->name,r_type); + } else if (p_node->type==GDParser::Node::TYPE_SELF) { + //eeh... + + r_type=_get_native_class(context); + return r_type.type!=Variant::NIL; + + } else if (p_node->type==GDParser::Node::TYPE_OPERATOR) { + + + const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(p_node); + if (op->op==GDParser::OperatorNode::OP_CALL) { + if (op->arguments[0]->type==GDParser::Node::TYPE_TYPE) { + + const GDParser::TypeNode *tn = static_cast<const GDParser::TypeNode *>(op->arguments[0]); + r_type.type=tn->vtype; + return true; + } else if (op->arguments[0]->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) { + + + const GDParser::BuiltInFunctionNode *bin = static_cast<const GDParser::BuiltInFunctionNode *>(op->arguments[0]); + return _guess_expression_type(context,bin,p_line,r_type); + + } else if (op->arguments.size()>1 && op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) { + + + GDCompletionIdentifier base; + if (!_guess_expression_type(context,op->arguments[0],p_line,base)) + return false; + + StringName id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1])->name; + + if (base.type==Variant::OBJECT) { + + if (id.operator String()=="new" && base.value.get_type()==Variant::OBJECT) { + Object *obj = base.value; + if (obj && obj->cast_to<GDNativeClass>()) { + GDNativeClass *gdnc = obj->cast_to<GDNativeClass>(); + r_type.type=Variant::OBJECT; + r_type.value=Variant(); + r_type.obj_type=gdnc->get_name(); + return true; + } + } + + if (ObjectTypeDB::has_method(base.obj_type,id)) { + +#ifdef TOOLS_ENABLED + MethodBind *mb = ObjectTypeDB::get_method(base.obj_type,id); + PropertyInfo pi = mb->get_argument_info(-1); + + //try calling the function if constant and all args are constant, should not crash.. + Object *baseptr = base.value; + + if (baseptr && mb->is_const() && pi.type==Variant::OBJECT) { + bool all_valid=true; + Vector<Variant> args; + for(int i=2;i<op->arguments.size();i++) { + GDCompletionIdentifier arg; + + if (_guess_expression_type(context,op->arguments[i],p_line,arg)) { + if (arg.value.get_type()!=Variant::NIL && arg.value.get_type()!=Variant::OBJECT) { // calling with object seems dangerous, i don' t know + args.push_back(arg.value); + } else { + all_valid=false; + break; + } + } else { + all_valid=false; + } + } + if (all_valid) { + Vector<const Variant*> argptr; + for(int i=0;i<args.size();i++) { + argptr.push_back(&args[i]); + } + + Variant::CallError ce; + Variant ret=mb->call(baseptr,argptr.ptr(),argptr.size(),ce); + + + if (ce.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) { + + if (ret.get_type()!=Variant::OBJECT || ret.operator Object*()!=NULL) { + + r_type=_get_type_from_variant(ret); + return true; + } + } + + } } + r_type.type=pi.type; + if (pi.hint==PROPERTY_HINT_RESOURCE_TYPE) { + r_type.obj_type=pi.hint_string; + } + + + + return true; +#else + return false; +#endif } else { - r_options->push_back(str); + return false; + } + } else { + //method for some variant.. + Variant::CallError ce; + Variant v = Variant::construct(base.type,NULL,0,ce); + List<MethodInfo> mi; + v.get_method_list(&mi); + for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { + + if (!E->get().name.begins_with("_") && E->get().name==id.operator String()) { + + + MethodInfo mi = E->get(); + r_type.type=mi.return_val.type; + if (mi.return_val.hint==PROPERTY_HINT_RESOURCE_TYPE) { + r_type.obj_type=mi.return_val.hint_string; + } + return true; + } } + } + + } + } else if (op->op==GDParser::OperatorNode::OP_INDEX || op->op==GDParser::OperatorNode::OP_INDEX_NAMED) { + + GDCompletionIdentifier p1; + GDCompletionIdentifier p2; + + + + if (op->op==GDParser::OperatorNode::OP_INDEX_NAMED) { + + if (op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) { + String id = static_cast<const GDParser::IdentifierNode*>(op->arguments[1])->name; + p2.type=Variant::STRING; + p2.value=id; + } + + } else { + if (op->arguments[1]) { + if (!_guess_expression_type(context,op->arguments[1],p_line,p2)) { + + return false; + } + } + } + + if (op->arguments[0]->type==GDParser::Node::TYPE_ARRAY) { + + const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode *>(op->arguments[0]); + if (p2.value.is_num()) { + int index = p2.value; + if (index<0 || index>=an->elements.size()) + return false; + return _guess_expression_type(context,an->elements[index],p_line,r_type); + } + + } else if (op->arguments[0]->type==GDParser::Node::TYPE_DICTIONARY) { + + const GDParser::DictionaryNode *dn = static_cast<const GDParser::DictionaryNode *>(op->arguments[0]); + + if (p2.value.get_type()==Variant::NIL) + return false; + + for(int i=0;i<dn->elements.size();i++) { + + GDCompletionIdentifier k; + + if (!_guess_expression_type(context,dn->elements[i].key,p_line,k)) { + + return false; + } + + if (k.value.get_type()==Variant::NIL) + return false; + + if (k.value==p2.value) { + + return _guess_expression_type(context,dn->elements[i].value,p_line,r_type); + } + } + + } else { + + if (op->arguments[0]) { + if (!_guess_expression_type(context,op->arguments[0],p_line,p1)) { + + return false; + } + + } + + if (p1.value.get_type()==Variant::OBJECT) { + //?? + } else if (p1.value.get_type()!=Variant::NIL) { + + bool valid; + Variant ret = p1.value.get(p2.value,&valid); + if (valid) { + r_type=_get_type_from_variant(ret); + return true; + } + + } else { + if (p1.type!=Variant::NIL) { + Variant::CallError ce; + Variant base = Variant::construct(p1.type,NULL,0,ce); + bool valid; + Variant ret = base.get(p2.value,&valid); + if (valid) { + r_type=_get_type_from_variant(ret); + return true; + } + } + } + } + + } else { + + + Variant::Operator vop = Variant::OP_MAX; + switch(op->op) { + case GDParser::OperatorNode::OP_ADD: vop=Variant::OP_ADD; break; + case GDParser::OperatorNode::OP_SUB: vop=Variant::OP_SUBSTRACT; break; + case GDParser::OperatorNode::OP_MUL: vop=Variant::OP_MULTIPLY; break; + case GDParser::OperatorNode::OP_DIV: vop=Variant::OP_DIVIDE; break; + case GDParser::OperatorNode::OP_MOD: vop=Variant::OP_MODULE; break; + case GDParser::OperatorNode::OP_SHIFT_LEFT: vop=Variant::OP_SHIFT_LEFT; break; + case GDParser::OperatorNode::OP_SHIFT_RIGHT: vop=Variant::OP_SHIFT_RIGHT; break; + case GDParser::OperatorNode::OP_BIT_AND: vop=Variant::OP_BIT_AND; break; + case GDParser::OperatorNode::OP_BIT_OR: vop=Variant::OP_BIT_OR; break; + case GDParser::OperatorNode::OP_BIT_XOR: vop=Variant::OP_BIT_XOR; break; + default:{} + + } + + + + if (vop==Variant::OP_MAX) + return false; + + + + GDCompletionIdentifier p1; + GDCompletionIdentifier p2; + + if (op->arguments[0]) { + if (!_guess_expression_type(context,op->arguments[0],p_line,p1)) { + + return false; + } + + } + + if (op->arguments.size()>1) { + if (!_guess_expression_type(context,op->arguments[1],p_line,p2)) { + + return false; + } + } + + Variant::CallError ce; + bool v1_use_value = p1.value.get_type()!=Variant::NIL && p1.value.get_type()!=Variant::OBJECT; + Variant v1 = (v1_use_value)?p1.value:Variant::construct(p1.type,NULL,0,ce); + bool v2_use_value = p2.value.get_type()!=Variant::NIL && p2.value.get_type()!=Variant::OBJECT; + Variant v2 = (v2_use_value)?p2.value:Variant::construct(p2.type,NULL,0,ce); + // avoid potential invalid ops + if ((vop==Variant::OP_DIVIDE || vop==Variant::OP_MODULE) && v2.get_type()==Variant::INT) { + v2=1; + v2_use_value=false; + } + if (vop==Variant::OP_DIVIDE && v2.get_type()==Variant::REAL) { + v2=1.0; + v2_use_value=false; + } + + Variant r; + bool valid; + Variant::evaluate(vop,v1,v2,r,valid); + if (!valid) + return false; + r_type.type=r.get_type(); + if (v1_use_value && v2_use_value) + r_type.value=r; + + return true; + } + } + + return false; } -static bool _parse_completion_block(const GDParser::BlockNode *p_block,int p_line,List<String>* r_options,List<String>::Element *p_indices) { +static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { - for(int i=0;i<p_block->sub_blocks.size();i++) { - //parse inner first - if (p_line>=p_block->sub_blocks[i]->line && (p_line<=p_block->sub_blocks[i]->end_line || p_block->sub_blocks[i]->end_line==-1)) { - if (_parse_completion_block(p_block->sub_blocks[i],p_line,r_options,p_indices)) - return true; + + + const GDParser::Node *last_assign=NULL; + int last_assign_line=-1; + + for (int i=0;i<context.block->statements.size();i++) { + + if (context.block->statements[i]->line>p_line) + continue; + + + if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + + const GDParser::LocalVarNode *lv=static_cast<const GDParser::LocalVarNode *>(context.block->statements[i]); + + if (lv->assign && lv->name==p_identifier) { + + last_assign=lv->assign; + last_assign_line=context.block->statements[i]->line; + } + } + + if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_OPERATOR) { + const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(context.block->statements[i]); + if (op->op==GDParser::OperatorNode::OP_ASSIGN) { + + if (op->arguments.size() && op->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER) { + + const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[0]); + + if (id->name==p_identifier) { + + last_assign=op->arguments[1]; + last_assign_line=context.block->statements[i]->line; + } + } + } + } + } + + //use the last assignment, (then backwards?) + if (last_assign) { + + return _guess_expression_type(context,last_assign,last_assign_line,r_type); + } + + + return false; +} + +static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { + + //go to block first + + + const GDParser::BlockNode *block=context.block; + + while(block) { + + GDCompletionContext c = context; + c.block=block; + + if (_guess_identifier_type_in_block(c,p_line,p_identifier,r_type)) { + return true; } + + block=block->parent_block; } - if (p_indices) { + //guess from argument if virtual + if (context.function && context.function->name!=StringName()) { - //parse indices in expressions :| - for (int i=0;i<p_block->statements.size();i++) { + int argindex = -1; - if (p_block->statements[i]->line>p_line) + for(int i=0;i<context.function->arguments.size();i++) { + + if (context.function->arguments[i]==p_identifier) { + argindex=i; break; + } - if (p_block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + } - const GDParser::LocalVarNode *lv=static_cast<const GDParser::LocalVarNode *>(p_block->statements[i]); - if (lv->assign && String(lv->name)==p_indices->get()) { + if (argindex!=-1) { + GDCompletionIdentifier id =_get_native_class(context); + if (id.type==Variant::OBJECT && id.obj_type!=StringName()) { + //this kinda sucks but meh - _parse_expression_node(lv->assign,r_options,p_indices->next()); - return true; + List<MethodInfo> vmethods; + ObjectTypeDB::get_virtual_methods(id.obj_type,&vmethods); + for (List<MethodInfo>::Element *E=vmethods.front();E;E=E->next()) { + + + if (E->get().name==context.function->name && argindex<E->get().arguments.size()) { + + PropertyInfo arg=E->get().arguments[argindex]; + + int scp = arg.name.find(":"); + if (scp!=-1) { + + + r_type.type=Variant::OBJECT; + r_type.obj_type=arg.name.substr(scp+1,arg.name.length()); + return true; + + } else { + + r_type.type=arg.type; + if (arg.hint==PROPERTY_HINT_RESOURCE_TYPE) + r_type.obj_type=arg.hint_string; + return true; + } + } } } } + } + + //guess type in constant + + for(int i=0;i<context._class->constant_expressions.size();i++) { + + if (context._class->constant_expressions[i].identifier==p_identifier) { + + ERR_FAIL_COND_V( context._class->constant_expressions[i].expression->type!=GDParser::Node::TYPE_CONSTANT, false ); + r_type=_get_type_from_variant(static_cast<const GDParser::ConstantNode*>(context._class->constant_expressions[i].expression)->value ); + return true; + } + } - } else { - for(int i=0;i<p_block->variables.size();i++) { - //parse variables second - if (p_line>=p_block->variable_lines[i]) { - r_options->push_back(p_block->variables[i]); - } - else break; + if (!(context.function && context.function->_static)) { + for(int i=0;i<context._class->variables.size();i++) { + + if (context._class->variables[i].identifier==p_identifier) { + + if (context._class->variables[i]._export.type!=Variant::NIL) { + + r_type=_get_type_from_pinfo(context._class->variables[i]._export); + return true; + } else if (context._class->variables[i].expression) { + return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type); + } + } } } + + + for(Map<StringName,int>::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { + if (E->key()==p_identifier) { + + r_type=_get_type_from_variant(GDScriptLanguage::get_singleton()->get_global_array()[E->get()]); + return true; + } + + } return false; } -static bool _parse_script_symbols(const Ref<GDScript>& p_script,bool p_static,List<String>* r_options,List<String>::Element *p_indices) { +static void _find_identifiers_in_block(GDCompletionContext& context,int p_line,bool p_only_functions,Set<String>& result) { + + if (p_only_functions) + return; + + for (int i=0;i<context.block->statements.size();i++) { + + if (context.block->statements[i]->line>p_line) + continue; - //for (Map<StringName,Ref<GDScript> >::Element ? - if (!p_static && !p_indices) { - for(const Set<StringName>::Element *E=p_script->get_members().front();E;E=E->next()) { + if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { - r_options->push_back(E->get()); + const GDParser::LocalVarNode *lv=static_cast<const GDParser::LocalVarNode *>(context.block->statements[i]); + result.insert(lv->name.operator String()); } } +} - for (const Map<StringName,Variant >::Element *E=p_script->get_constants().front();E;E=E->next()) { +static void _find_identifiers_in_class(GDCompletionContext& context,bool p_static,bool p_only_functions,Set<String>& result) { - if( p_indices) { - if (p_indices->get()==String(E->get())) { - _parse_completion_variant(E->get(),r_options,p_indices->next()); - return true; - } - } else { - r_options->push_back(E->key()); + if (!p_static && !p_only_functions) { + + for(int i=0;i<context._class->variables.size();i++) { + result.insert(context._class->variables[i].identifier); } } + if (!p_only_functions) { - if (!p_indices){ - for (const Map<StringName,GDFunction>::Element *E=p_script->get_member_functions().front();E;E=E->next()) { + for(int i=0;i<context._class->constant_expressions.size();i++) { + result.insert(context._class->constant_expressions[i].identifier); + } - if (E->get().is_static() || !p_static) - r_options->push_back(E->key()); + for(int i=0;i<context._class->subclasses.size();i++) { + result.insert(context._class->subclasses[i]->name); } + } - if (p_script->get_base().is_valid()){ - if (_parse_script_symbols(p_script->get_base(),p_static,r_options,p_indices)) - return true; - } else if (p_script->get_native().is_valid() && !p_indices) { - _parse_native_symbols(p_script->get_native()->get_name(),p_static,r_options); + for(int i=0;i<context._class->static_functions.size();i++) { + if (context._class->static_functions[i]->arguments.size()) + result.insert(context._class->static_functions[i]->name.operator String()+"("); + else + result.insert(context._class->static_functions[i]->name.operator String()+"()"); + } + + if (!p_static) { + + for(int i=0;i<context._class->functions.size();i++) { + if (context._class->functions[i]->arguments.size()) + result.insert(context._class->functions[i]->name.operator String()+"("); + else + result.insert(context._class->functions[i]->name.operator String()+"()"); + } + } + + //globals + + Ref<Reference> base = _get_parent_class(context); + + while(true) { + + Ref<GDScript> script = base; + Ref<GDNativeClass> nc = base; + if (script.is_valid()) { + + if (!p_static && !p_only_functions) { + for (const Set<StringName>::Element *E=script->get_members().front();E;E=E->next()) { + result.insert(E->get().operator String()); + } + } + + if (!p_only_functions) { + for (const Map<StringName,Variant>::Element *E=script->get_constants().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } + } + + for (const Map<StringName,GDFunction>::Element *E=script->get_member_functions().front();E;E=E->next()) { + if (!p_static || E->get().is_static()) { + if (E->get().get_argument_count()) + result.insert(E->key().operator String()+"("); + else + result.insert(E->key().operator String()+"()"); + } + } + + if (!p_only_functions) { + for (const Map<StringName,Ref<GDScript> >::Element *E=script->get_subclasses().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } + } + + base=script->get_base(); + if (base.is_null()) + base=script->get_native(); + } else if (nc.is_valid()) { + + if (!p_only_functions) { + + StringName type = nc->get_name(); + List<String> constants; + ObjectTypeDB::get_integer_constant_list(type,&constants); + for(List<String>::Element *E=constants.front();E;E=E->next()) { + result.insert(E->get()); + } + + List<MethodInfo> methods; + ObjectTypeDB::get_method_list(type,&methods); + for(List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { + if (E->get().name.begins_with("_")) + continue; + if (E->get().arguments.size()) + result.insert(E->get().name+"("); + else + result.insert(E->get().name+"()"); + } + } + break; + } else + break; + } - return false; } +static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_only_functions,Set<String>& result) { + + const GDParser::BlockNode *block=context.block; + + while(block) { + + GDCompletionContext c = context; + c.block=block; + + _find_identifiers_in_block(c,p_line,p_only_functions,result); + block=block->parent_block; + } + + const GDParser::ClassNode *clss=context._class; -static bool _parse_completion_class(const String& p_base_path,const GDParser::ClassNode *p_class,int p_line,List<String>* r_options,List<String>::Element *p_indices) { + bool _static=context.function && context.function->_static; + while(clss) { + GDCompletionContext c = context; + c._class=clss; + c.block=NULL; + c.function=NULL; + _find_identifiers_in_class(c,_static,p_only_functions,result); + clss=clss->owner; + } + + for(int i=0;i<GDFunctions::FUNC_MAX;i++) { + + result.insert(GDFunctions::get_func_name(GDFunctions::Function(i))); + } static const char*_type_names[Variant::VARIANT_MAX]={ "null","bool","int","float","String","Vector2","Rect2","Vector3","Matrix32","Plane","Quat","AABB","Matrix3","Trasnform", "Color","Image","NodePath","RID","Object","InputEvent","Dictionary","Array","RawArray","IntArray","FloatArray","StringArray", "Vector2Array","Vector3Array","ColorArray"}; - if (p_indices && !p_indices->next()) { - for(int i=0;i<Variant::VARIANT_MAX;i++) { + for(int i=0;i<Variant::VARIANT_MAX;i++) { + result.insert(_type_names[i]); + } + + for(const Map<StringName,int>::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } +} - if (p_indices->get()==_type_names[i]) { - List<StringName> ic; +static String _get_visual_datatype(const PropertyInfo& p_info,bool p_isarg=true) { - Variant::get_numeric_constants_for_type(Variant::Type(i),&ic); - for(List<StringName>::Element *E=ic.front();E;E=E->next()) { - r_options->push_back(E->get()); - } - return true; - } - } + String n = p_info.name; + int idx = n.find(":"); + if (idx!=-1) { + return n.substr(idx+1,n.length()); } + if (p_info.type==Variant::OBJECT && p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) + return p_info.hint_string; + if (p_info.type==Variant::NIL) { + if (p_isarg) + return "var"; + else + return "void"; + } + return Variant::get_type_name(p_info.type); +} - for(int i=0;i<p_class->subclasses.size();i++) { +static void _make_function_hint(const GDParser::FunctionNode* p_func,int p_argidx,String& arghint) { - if (p_line>=p_class->subclasses[i]->line && (p_line<=p_class->subclasses[i]->end_line || p_class->subclasses[i]->end_line==-1)) { + arghint="func "+p_func->name+"("; + for (int i=0;i<p_func->arguments.size();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; - if (_parse_completion_class(p_base_path,p_class->subclasses[i],p_line,r_options,p_indices)) - return true; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); } - } + arghint+=p_func->arguments[i].operator String(); + int deffrom = p_func->arguments.size()-p_func->default_values.size(); - bool in_static_func=false; + if (i>=deffrom) { + int defidx = deffrom-i; - for(int i=0;i<p_class->functions.size();i++) { + if (defidx>=0 && defidx<p_func->default_values.size()) { - const GDParser::FunctionNode *fu = p_class->functions[i]; + if (p_func->default_values[defidx]->type==GDParser::Node::TYPE_OPERATOR) { - if (p_line>=fu->body->line && (p_line<=fu->body->end_line || fu->body->end_line==-1)) { - //if in function, first block stuff from outer to inner - if (_parse_completion_block(fu->body,p_line,r_options,p_indices)) - return true; - //then function arguments - if (!p_indices) { - for(int j=0;j<fu->arguments.size();j++) { + const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(p_func->default_values[defidx]); + if (op->op==GDParser::OperatorNode::OP_ASSIGN) { + const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(op->arguments[1]); + arghint+="="+cn->value.get_construct_string(); + + } + } else { - r_options->push_back(fu->arguments[j]); } } } + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } } + if (p_func->arguments.size()>0) + arghint+=" "; + arghint+=")"; +} - for(int i=0;i<p_class->static_functions.size();i++) { - const GDParser::FunctionNode *fu = p_class->static_functions[i]; +static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const StringName& p_method,const GDCompletionIdentifier& id, int p_argidx, Set<String>& result, String& arghint) { - if (p_line>=fu->body->line && (p_line<=fu->body->end_line || fu->body->end_line==-1)) { - //if in function, first block stuff from outer to inne - if (_parse_completion_block(fu->body,p_line,r_options,p_indices)) - return true; - //then function arguments - if (!p_indices) { - for(int j=0;j<fu->arguments.size();j++) { + if (id.type==Variant::INPUT_EVENT && String(p_method)=="is_action" && p_argidx==0) { - r_options->push_back(fu->arguments[j]); - } - } + List<PropertyInfo> pinfo; + Globals::get_singleton()->get_property_list(&pinfo); - in_static_func=true; + for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); + result.insert("\""+name+"\""); } - } + } else if (id.type==Variant::OBJECT && id.obj_type!=StringName()) { - //add all local names - if (!p_indices) { - if (!in_static_func) { + MethodBind *m = ObjectTypeDB::get_method(id.obj_type,p_method); + if (!m) + return; - for(int i=0;i<p_class->variables.size();i++) { + if (p_method.operator String()=="connect") { - r_options->push_back(p_class->variables[i].identifier); + + if (p_argidx==0) { + List<MethodInfo> sigs; + ObjectTypeDB::get_signal_list(id.obj_type,&sigs); + for (List<MethodInfo>::Element *E=sigs.front();E;E=E->next()) { + result.insert("\""+E->get().name+"\""); + } } - } + /*if (p_argidx==2) { - for(int i=0;i<p_class->constant_expressions.size();i++) { + ERR_FAIL_COND(p_node->type!=GDParser::Node::TYPE_OPERATOR); + const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(p_node); + if (op->arguments.size()>) - r_options->push_back(p_class->constant_expressions[i].identifier); - } + }*/ + } else { - if (!in_static_func) { - for(int i=0;i<p_class->functions.size();i++) { + Object *obj=id.value; + if (obj) { + List<String> options; + obj->get_argument_options(p_method,p_argidx,&options); + for(List<String>::Element *E=options.front();E;E=E->next()) { - r_options->push_back(p_class->functions[i]->name); + result.insert(E->get()); + } } + } - for(int i=0;i<p_class->static_functions.size();i++) { + arghint = _get_visual_datatype(m->get_argument_info(-1),false)+" "+p_method.operator String()+String("("); + + for(int i=0;i<m->get_argument_count();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; + + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + String n = m->get_argument_info(i).name; + int dp = n.find(":"); + if (dp!=-1) + n=n.substr(0,dp); + arghint+=_get_visual_datatype(m->get_argument_info(i))+" "+n; + int deffrom = m->get_argument_count()-m->get_default_argument_count(); + + + if (i>=deffrom) { + int defidx = i-deffrom; + + if (defidx>=0 && defidx<m->get_default_argument_count()) { + Variant v= m->get_default_argument(i); + arghint+="="+v.get_construct_string(); + } + } + + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } - r_options->push_back(p_class->static_functions[i]->name); } + if (m->get_argument_count()>0) + arghint+=" "; + + + arghint+=")"; + } +} - if (p_class->extends_used) { - //do inheritance - String path = p_class->extends_file; +static void _find_call_arguments(GDCompletionContext& context,const GDParser::Node* p_node, int p_line,int p_argidx, Set<String>& result, String& arghint) { - Ref<GDScript> script; - Ref<GDNativeClass> native; - if (path!="") { - //path (and optionally subclasses) - script = ResourceLoader::load(path); - if (script.is_null()) { - return false; + if (!p_node || p_node->type!=GDParser::Node::TYPE_OPERATOR) { + + return; + } + + const GDParser::OperatorNode *op = static_cast<const GDParser::OperatorNode *>(p_node); + + if (op->op!=GDParser::OperatorNode::OP_CALL) { + + return; + } + + if (op->arguments[0]->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) { + //complete built-in function + const GDParser::BuiltInFunctionNode *fn = static_cast<const GDParser::BuiltInFunctionNode*>(op->arguments[0]); + MethodInfo mi = GDFunctions::get_info(fn->function); + + arghint = _get_visual_datatype(mi.return_val,false)+" "+GDFunctions::get_func_name(fn->function)+String("("); + for(int i=0;i<mi.arguments.size();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=_get_visual_datatype(mi.arguments[i])+" "+mi.arguments[i].name; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); } - if (p_class->extends_class.size()) { + } + if (mi.arguments.size()>0) + arghint+=" "; + arghint+=")"; + + } else if (op->arguments[0]->type==GDParser::Node::TYPE_TYPE) { + //complete built-in function + const GDParser::TypeNode *tn = static_cast<const GDParser::TypeNode*>(op->arguments[0]); + + List<MethodInfo> mil; + Variant::get_constructor_list(tn->vtype,&mil); + + for(List<MethodInfo>::Element *E=mil.front();E;E=E->next()) { + + MethodInfo mi = E->get(); + if (mi.arguments.size()==0) + continue; + if (E->prev()) + arghint+="\n"; + arghint += Variant::get_type_name(tn->vtype)+" "+Variant::get_type_name(tn->vtype)+String("("); + for(int i=0;i<mi.arguments.size();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=_get_visual_datatype(mi.arguments[i])+" "+mi.arguments[i].name; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } - for(int i=0;i<p_class->extends_class.size();i++) { + } + if (mi.arguments.size()>0) + arghint+=" "; + arghint+=")"; + } - String sub = p_class->extends_class[i]; - if (script->get_subclasses().has(sub)) { + } else if (op->arguments.size()>=2 && op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) { + //make sure identifier exists... - script=script->get_subclasses()[sub]; - } else { + const GDParser::IdentifierNode *id=static_cast<const GDParser::IdentifierNode *>(op->arguments[1]); - return false; + if (op->arguments[0]->type==GDParser::Node::TYPE_SELF) { + //self, look up + + for(int i=0;i<context._class->static_functions.size();i++) { + if (context._class->static_functions[i]->name==id->name) { + _make_function_hint(context._class->static_functions[i],p_argidx,arghint); + return; + } + } + + if (context.function && !context.function->_static) { + + for(int i=0;i<context._class->functions.size();i++) { + if (context._class->functions[i]->name==id->name) { + _make_function_hint(context._class->functions[i],p_argidx,arghint); + return; } } } - } else { + Ref<Reference> base = _get_parent_class(context); - ERR_FAIL_COND_V(p_class->extends_class.size()==0,false); - //look around for the subclasses + while(true) { - String base=p_class->extends_class[0]; - Ref<GDScript> base_class; -#if 0 - while(p) { + Ref<GDScript> script = base; + Ref<GDNativeClass> nc = base; + if (script.is_valid()) { - if (p->subclasses.has(base)) { - base_class=p->subclasses[base]; + for (const Map<StringName,GDFunction>::Element *E=script->get_member_functions().front();E;E=E->next()) { + + if (E->key()==id->name) { + + if (context.function && context.function->_static && !E->get().is_static()) + continue; + + + arghint = "func "+id->name.operator String()+String("("); + for(int i=0;i<E->get().get_argument_count();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=E->get().get_argument_name(i); + int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count(); + if (i>=deffrom) { + int defidx = deffrom-i; + if (defidx>=0 && defidx<E->get().get_default_argument_count()) { + arghint+="="+E->get().get_default_argument(defidx).get_construct_string(); + } + } + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + + } + if (E->get().get_argument_count()>0) + arghint+=" "; + arghint+=")"; + return; + } + } + + base=script->get_base(); + if (base.is_null()) + base=script->get_native(); + } else if (nc.is_valid()) { + + if (context.function && !context.function->_static) { + + GDCompletionIdentifier ci; + ci.type=Variant::OBJECT; + ci.obj_type=nc->get_name(); + if (!context._class->owner) + ci.value=context.base; + + _find_type_arguments(p_node,p_line,id->name,ci,p_argidx,result,arghint); + //guess type.. + /* + List<MethodInfo> methods; + ObjectTypeDB::get_method_list(type,&methods); + for(List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { + //if (E->get().arguments.size()) + // result.insert(E->get().name+"("); + //else + // result.insert(E->get().name+"()"); + }*/ + } break; - } - p=p->_owner; + } else + break; + } + } else { - if (base_class.is_valid()) { - for(int i=1;i<p_class->extends_class.size();i++) { + GDCompletionIdentifier ci; + if (_guess_expression_type(context,op->arguments[0],p_line,ci)) { - String subclass=p_class->extends_class[i]; + _find_type_arguments(p_node,p_line,id->name,ci,p_argidx,result,arghint); + return; + } - if (base_class->subclasses.has(subclass)) { + } - base_class=base_class->subclasses[subclass]; - } else { + } +#if 0 + bool _static=context.function->_static; - _set_error("Could not find subclass: "+subclass,p_class); - return ERR_FILE_NOT_FOUND; - } - } - } else { -#endif - if (p_class->extends_class.size()>1) { - return false; + for(int i=0;i<context._class->static_functions.size();i++) { + if (context._class->static_functions[i]->arguments.size()) + result.insert(context._class->static_functions[i]->name.operator String()+"("); + else + result.insert(context._class->static_functions[i]->name.operator String()+"()"); + } + + if (!p_static) { + + for(int i=0;i<context._class->functions.size();i++) { + if (context._class->functions[i]->arguments.size()) + result.insert(context._class->functions[i]->name.operator String()+"("); + else + result.insert(context._class->functions[i]->name.operator String()+"()"); + } + } + + Ref<Reference> base = _get_parent_class(context); + while(true) { + + Ref<GDScript> script = base; + Ref<GDNativeClass> nc = base; + if (script.is_valid()) { + + if (!p_static && !p_only_functions) { + for (const Set<StringName>::Element *E=script->get_members().front();E;E=E->next()) { + result.insert(E->get().operator String()); } - //if not found, try engine classes - if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { - return false; + } + + if (!p_only_functions) { + for (const Map<StringName,Variant>::Element *E=script->get_constants().front();E;E=E->next()) { + result.insert(E->key().operator String()); } + } - int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; - native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; - if (!native.is_valid()) { - return false; + for (const Map<StringName,GDFunction>::Element *E=script->get_member_functions().front();E;E=E->next()) { + if (!p_static || E->get().is_static()) { + if (E->get().get_argument_count()) + result.insert(E->key().operator String()+"("); + else + result.insert(E->key().operator String()+"()"); } -#if 0 } -#endif - } + if (!p_only_functions) { + for (const Map<StringName,Ref<GDScript> >::Element *E=script->get_subclasses().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } + } - if (script.is_valid()) { - if (_parse_script_symbols(script,in_static_func,r_options,p_indices)) - return true; + base=script->get_base(); + if (base.is_null()) + base=script->get_native(); + } else if (nc.is_valid()) { - } else if (native.is_valid() && !p_indices) { + if (!p_only_functions) { + + StringName type = nc->get_name(); + List<String> constants; + ObjectTypeDB::get_integer_constant_list(type,&constants); + for(List<String>::Element *E=constants.front();E;E=E->next()) { + result.insert(E->get()); + } + + List<MethodInfo> methods; + ObjectTypeDB::get_method_list(type,&methods); + for(List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { + if (E->get().arguments.size()) + result.insert(E->get().name+"("); + else + result.insert(E->get().name+"()"); + } + } + break; + } else + break; - _parse_native_symbols(native->get_name(),in_static_func,r_options); - } } - return false; + for(int i=0;i<GDFunctions::FUNC_MAX;i++) { -} + result.insert(GDFunctions::get_func_name(GDFunctions::Function(i))); + } +#endif + +} -Error GDScriptLanguage::complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_base, List<String>* r_options) { +Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List<String>* r_options, String &r_call_hint) { + //print_line( p_code.replace(String::chr(0xFFFF),"<cursor>")); GDParser p; - Error err = p.parse(p_code,p_base_path); - // don't care much about error I guess - const GDParser::Node* root = p.get_parse_tree(); - ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_INVALID_DATA); + Error err = p.parse(p_code,p_base_path,true); + bool isfunction=false; + Set<String> options; + + GDCompletionContext context; + context._class=p.get_completion_class(); + context.block=p.get_completion_block(); + context.function=p.get_completion_function(); + context.base=p_owner; + context.base_path=p_base_path; + + switch(p.get_completion_type()) { + + case GDParser::COMPLETION_NONE: { + print_line("No completion"); + } break; + case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: { + print_line("Built in type constant"); + List<StringName> constants; + Variant::get_numeric_constants_for_type(p.get_completion_built_in_constant(),&constants); + for(List<StringName>::Element *E=constants.front();E;E=E->next()) { + options.insert(E->get().operator String()); + } - const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root); - List<String> indices; - Vector<String> spl = p_base.split("."); + } break; + case GDParser::COMPLETION_FUNCTION: + isfunction=true; + case GDParser::COMPLETION_IDENTIFIER: { - for(int i=0;i<spl.size()-1;i++) { - indices.push_back(spl[i]); - } + _find_identifiers(context,p.get_completion_line(),isfunction,options); + } break; + case GDParser::COMPLETION_PARENT_FUNCTION: { + print_line("parent function"); + + } break; + case GDParser::COMPLETION_METHOD: + isfunction=true; + case GDParser::COMPLETION_INDEX: { + + const GDParser::Node *node = p.get_completion_node(); + if (node->type!=GDParser::Node::TYPE_OPERATOR) + break; + + + + + GDCompletionIdentifier t; + if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) { + + if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { + + + if (t.value.get_type()) { + Object *obj=t.value; + if (obj) { + GDScript *scr = obj->cast_to<GDScript>(); + while (scr) { + + if (!isfunction) { + for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) { + options.insert(E->key()); + } + } + for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) { + options.insert(E->key()); + } + + if (scr->get_base().is_valid()) + scr=scr->get_base().ptr(); + else + scr=NULL; + } + } + } + + + if (!isfunction) { + ObjectTypeDB::get_integer_constant_list(t.obj_type,r_options); + } + List<MethodInfo> mi; + ObjectTypeDB::get_method_list(t.obj_type,&mi); + for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { + + if (E->get().name.begins_with("_")) + continue; + + if (E->get().arguments.size()) + options.insert(E->get().name+"("); + else + options.insert(E->get().name+"()"); + + } + } else { + + + if (t.type==Variant::INPUT_EVENT) { + + //this is hardcoded otherwise it's not obvious + Set<String> exclude; + + for(int i=0;i<InputEvent::TYPE_MAX;i++) { + + InputEvent ie; + ie.type=InputEvent::Type(i); + static const char*evnames[]={ + "# Common", + "# Key", + "# MouseMotion", + "# MouseButton", + "# JoyMotion", + "# JoyButton", + "# ScreenTouch", + "# ScreenDrag", + "# Action" + }; + + r_options->push_back(evnames[i]); + + Variant v = ie; + + if (i==0) { + List<MethodInfo> mi; + v.get_method_list(&mi); + for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { + r_options->push_back(E->get().name+"("); + + } + + } + + List<PropertyInfo> pi; + v.get_property_list(&pi); + + for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) { + + if (i==0) + exclude.insert(E->get().name); + else if (exclude.has(E->get().name)) + continue; + + r_options->push_back(E->get().name); + } + } + return OK; + } else { + if (t.value.get_type()==Variant::NIL) { + Variant::CallError ce; + t.value=Variant::construct(t.type,NULL,0,ce); + } - if (_parse_completion_class(p_base,cl,p_line,r_options,indices.front())) - return OK; - //and the globals x_x? - for(Map<StringName,int>::Element *E=globals.front();E;E=E->next()) { - if (!indices.empty()) { - if (String(E->key())==indices.front()->get()) { - _parse_completion_variant(global_array[E->get()],r_options,indices.front()->next()); + if (!isfunction) { + List<PropertyInfo> pl; + t.value.get_property_list(&pl); + for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + + if (E->get().name.find("/")==-1) + options.insert(E->get().name); + } + } - return OK; + List<MethodInfo> mi; + t.value.get_method_list(&mi); + for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { + if (E->get().arguments.size()) + options.insert(E->get().name+"("); + else + options.insert(E->get().name+"()"); + + } + } + } } - } else { - r_options->push_back(E->key()); - } + + + } break; + case GDParser::COMPLETION_CALL_ARGUMENTS: { + + _find_call_arguments(context,p.get_completion_node(),p.get_completion_line(),p.get_completion_argument_index(),options,r_call_hint); + } break; + case GDParser::COMPLETION_VIRTUAL_FUNC: { + + GDCompletionIdentifier cid = _get_native_class(context); + + if (cid.obj_type!=StringName()) { + List<MethodInfo> vm; + ObjectTypeDB::get_virtual_methods(cid.obj_type,&vm); + for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) { + + MethodInfo &mi=E->get(); + String m = mi.name; + if (m.find(":")!=-1) + m=m.substr(0,m.find(":")); + m+="("; + + if (mi.arguments.size()) { + for(int i=0;i<mi.arguments.size();i++) { + if (i>0) + m+=", "; + String n =mi.arguments[i].name; + if (n.find(":")!=-1) + n=n.substr(0,n.find(":")); + m+=n; + } + } + m+="):"; + + options.insert(m); + } + } + } break; + + + } + + + for(Set<String>::Element *E=options.front();E;E=E->next()) { + r_options->push_back(E->get()); } return OK; } +#else + +Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List<String>* r_options, String &r_call_hint) { + return OK; +} + +#endif + + void GDScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_line) const { diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp index 0d11734bbd..d4b8639c9b 100644 --- a/modules/gdscript/gd_functions.cpp +++ b/modules/gdscript/gd_functions.cpp @@ -71,6 +71,7 @@ const char *GDFunctions::get_func_name(Function p_func) { "randi", "randf", "rand_range", + "seed", "rand_seed", "deg2rad", "rad2deg", @@ -89,12 +90,15 @@ const char *GDFunctions::get_func_name(Function p_func) { "printt", "printerr", "printraw", + "var2str", + "str2var", "range", "load", "inst2dict", "dict2inst", "hash", "print_stack", + "get_inst", }; return _names[p_func]; @@ -326,6 +330,13 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va VALIDATE_ARG_NUM(1); r_ret=Math::random(*p_args[0],*p_args[1]); } break; + case MATH_SEED: { + VALIDATE_ARG_COUNT(1); + VALIDATE_ARG_NUM(0); + uint32_t seed=*p_args[0]; + Math::seed(seed); + r_ret=Variant(); + } break; case MATH_RANDSEED: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); @@ -573,14 +584,27 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va } //str+="\n"; - OS::get_singleton()->print("%s\n",str.utf8().get_data()); + OS::get_singleton()->print("%s",str.utf8().get_data()); r_ret=Variant(); } break; + case VAR_TO_STR: { + VALIDATE_ARG_COUNT(1); + r_ret=p_args[0]->get_construct_string(); + } break; + case STR_TO_VAR: { + VALIDATE_ARG_COUNT(1); + if (p_args[0]->get_type()!=Variant::STRING) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_error.expected=Variant::STRING; + r_ret=Variant(); + return; + } + Variant::construct_from_string(*p_args[0],r_ret); + } break; case GEN_RANGE: { - - switch(p_arg_count) { case 0: { @@ -861,7 +885,6 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va } } - r_ret = gdscr->_new(NULL,0,r_error); } break; @@ -881,6 +904,20 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va }; } break; + case GET_INST: { + + VALIDATE_ARG_COUNT(1); + if (p_args[0]->get_type()!=Variant::INT && p_args[0]->get_type()!=Variant::REAL) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument=0; + r_ret=Variant(); + break; + } + + uint32_t id=*p_args[0]; + r_ret=ObjectDB::get_instance(id); + + } break; case FUNC_MAX: { ERR_FAIL_V(); @@ -1087,7 +1124,7 @@ MethodInfo GDFunctions::get_info(Function p_func) { return mi; } break; case MATH_LERP: { - MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"a"),PropertyInfo(Variant::REAL,"b"), PropertyInfo(Variant::REAL,"c")); + MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"from"),PropertyInfo(Variant::REAL,"to"), PropertyInfo(Variant::REAL,"weight")); mi.return_val.type=Variant::REAL; return mi; } break; @@ -1116,6 +1153,11 @@ MethodInfo GDFunctions::get_info(Function p_func) { mi.return_val.type=Variant::REAL; return mi; } break; + case MATH_SEED: { + MethodInfo mi("seed",PropertyInfo(Variant::REAL,"seed")); + mi.return_val.type=Variant::NIL; + return mi; + } break; case MATH_RANDSEED: { MethodInfo mi("rand_seed",PropertyInfo(Variant::REAL,"seed")); mi.return_val.type=Variant::ARRAY; @@ -1166,6 +1208,8 @@ MethodInfo GDFunctions::get_info(Function p_func) { MethodInfo mi("weakref",PropertyInfo(Variant::OBJECT,"obj")); mi.return_val.type=Variant::OBJECT; + mi.return_val.name="WeakRef"; + return mi; } break; @@ -1173,6 +1217,7 @@ MethodInfo GDFunctions::get_info(Function p_func) { MethodInfo mi("funcref",PropertyInfo(Variant::OBJECT,"instance"),PropertyInfo(Variant::STRING,"funcname")); mi.return_val.type=Variant::OBJECT; + mi.return_val.name="FuncRef"; return mi; } break; @@ -1221,6 +1266,18 @@ MethodInfo GDFunctions::get_info(Function p_func) { return mi; } break; + case VAR_TO_STR: { + MethodInfo mi("var2str",PropertyInfo(Variant::NIL,"var")); + mi.return_val.type=Variant::STRING; + return mi; + + } break; + case STR_TO_VAR: { + + MethodInfo mi("str2var:var",PropertyInfo(Variant::STRING,"string")); + mi.return_val.type=Variant::NIL; + return mi; + } break; case GEN_RANGE: { MethodInfo mi("range",PropertyInfo(Variant::NIL,"...")); @@ -1231,6 +1288,7 @@ MethodInfo GDFunctions::get_info(Function p_func) { MethodInfo mi("load",PropertyInfo(Variant::STRING,"path")); mi.return_val.type=Variant::OBJECT; + mi.return_val.name="Resource"; return mi; } break; case INST2DICT: { @@ -1258,6 +1316,12 @@ MethodInfo GDFunctions::get_info(Function p_func) { return mi; } break; + case GET_INST: { + MethodInfo mi("get_info",PropertyInfo(Variant::INT,"instance_id")); + mi.return_val.type=Variant::OBJECT; + return mi; + } break; + case FUNC_MAX: { ERR_FAIL_V(MethodInfo()); diff --git a/modules/gdscript/gd_functions.h b/modules/gdscript/gd_functions.h index 340763fb8c..4fbfe99228 100644 --- a/modules/gdscript/gd_functions.h +++ b/modules/gdscript/gd_functions.h @@ -67,6 +67,7 @@ public: MATH_RAND, MATH_RANDF, MATH_RANDOM, + MATH_SEED, MATH_RANDSEED, MATH_DEG2RAD, MATH_RAD2DEG, @@ -85,12 +86,15 @@ public: TEXT_PRINT_TABBED, TEXT_PRINTERR, TEXT_PRINTRAW, + VAR_TO_STR, + STR_TO_VAR, GEN_RANGE, RESOURCE_LOAD, INST2DICT, DICT2INST, HASH, PRINT_STACK, + GET_INST, FUNC_MAX }; diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 46eade0b7c..aa2878f9e1 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -30,19 +30,6 @@ #include "print_string.h" #include "io/resource_loader.h" #include "os/file_access.h" -/* TODO: - - *Property reduce constant expressions - *Implement missing operators in variant? - *constructor - */ - -/* - todo: - fix post ++,-- - make sure ++,-- don't work on constant expressions - seems passing parent node as param is not needed - */ template<class T> T* GDParser::alloc_node() { @@ -116,14 +103,20 @@ bool GDParser::_enter_indent_block(BlockNode* p_block) { } } -bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static) { +bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static,bool p_can_codecomplete) { if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) { tokenizer->advance(); } else { + int argidx=0; + while(true) { + if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { + _make_completable_call(argidx); + completion_node=p_parent; + } Node*arg = _parse_expression(p_parent,p_static); if (!arg) @@ -144,6 +137,7 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat } tokenizer->advance(); + argidx++; } else { // something is broken _set_error("Expected ',' or ')'"); @@ -158,6 +152,48 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat } +void GDParser::_make_completable_call(int p_arg) { + + completion_cursor=StringName(); + completion_type=COMPLETION_CALL_ARGUMENTS; + completion_class=current_class; + completion_function=current_function; + completion_line=tokenizer->get_token_line(); + completion_argument=p_arg; + completion_block=current_block; + tokenizer->advance(); + +} + + +bool GDParser::_get_completable_identifier(CompletionType p_type,StringName& identifier) { + + identifier=StringName(); + if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { + identifier=tokenizer->get_token_identifier(); + tokenizer->advance(); + } + if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { + + completion_cursor=identifier; + completion_type=p_type; + completion_class=current_class; + completion_function=current_function; + completion_line=tokenizer->get_token_line(); + completion_block=current_block; + tokenizer->advance(); + + if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { + identifier=identifier.operator String() + tokenizer->get_token_identifier().operator String(); + tokenizer->advance(); + } + + return true; + } + + return false; +} + GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_allow_assign) { @@ -199,6 +235,9 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ tokenizer->advance(); expr=subexpr; + } else if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { + tokenizer->advance(); + continue; //no point in cursor in the middle of expression } else if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) { @@ -225,7 +264,14 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ String path = tokenizer->get_token_constant(); if (!path.is_abs_path() && base_path!="") path=base_path+"/"+path; - path = path.replace("///","//"); + path = path.replace("///","//").simplify_path(); + if (path==self_path) { + + _set_error("Can't preload itself (use 'get_script()')."); + return NULL; + + } + Ref<Resource> res; if (!validating) { @@ -320,12 +366,19 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ Variant::Type bi_type = tokenizer->get_token_type(); tokenizer->advance(2); - if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + + StringName identifier; + + if (_get_completable_identifier(COMPLETION_BUILT_IN_TYPE_CONSTANT,identifier)) { + + completion_built_in_constant=bi_type; + } + + if (identifier==StringName()) { _set_error("Built-in type constant expected after '.'"); return NULL; } - StringName identifier = tokenizer->get_token_identifier(); if (!Variant::has_numeric_constant(bi_type,identifier)) { _set_error("Static constant '"+identifier.operator String()+"' not present in built-in type "+Variant::get_type_name(bi_type)+"."); @@ -335,7 +388,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ ConstantNode *cn = alloc_node<ConstantNode>(); cn->value=Variant::get_numeric_constant_value(bi_type,identifier); expr=cn; - tokenizer->advance(); + } else if (tokenizer->get_token(1)==GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE || tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER || tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC)) { //function or constructor @@ -348,23 +401,35 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ TypeNode *tn = alloc_node<TypeNode>(); tn->vtype=tokenizer->get_token_type(); op->arguments.push_back(tn); + tokenizer->advance(2); } else if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC) { BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>(); bn->function=tokenizer->get_token_built_in_func(); op->arguments.push_back(bn); + tokenizer->advance(2); } else { SelfNode *self = alloc_node<SelfNode>(); op->arguments.push_back(self); + StringName identifier; + if (_get_completable_identifier(COMPLETION_FUNCTION,identifier)) { + + } + IdentifierNode* id = alloc_node<IdentifierNode>(); - id->name=tokenizer->get_token_identifier(); + id->name=identifier; op->arguments.push_back(id); + tokenizer->advance(1); } - tokenizer->advance(2); - if (!_parse_arguments(op,op->arguments,p_static)) + if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { + _make_completable_call(0); + completion_node=op; + + } + if (!_parse_arguments(op,op->arguments,p_static,true)) return NULL; expr=op; @@ -372,10 +437,28 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ } else if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) { //identifier (reference) - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name=tokenizer->get_token_identifier(); - tokenizer->advance(); - expr=id; + const ClassNode* cln = static_cast<const ClassNode*>(get_parse_tree()); + bool bfn = false; + StringName identifier; + if (_get_completable_identifier(COMPLETION_IDENTIFIER,identifier)) { + + } + + for( int i=0; i<cln->constant_expressions.size(); ++i ) { + + if( cln->constant_expressions[i].identifier == identifier ) { + + expr = cln->constant_expressions[i].expression; + bfn = true; + break; + } + } + + if ( !bfn ) { + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name = identifier; + expr = id; + } } else if (/*tokenizer->get_token()==GDTokenizer::TK_OP_ADD ||*/ tokenizer->get_token()==GDTokenizer::TK_OP_SUB || tokenizer->get_token()==GDTokenizer::TK_OP_NOT || tokenizer->get_token()==GDTokenizer::TK_OP_BIT_INVERT) { @@ -577,7 +660,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ expr=dict; - } else if (tokenizer->get_token()==GDTokenizer::TK_PERIOD && tokenizer->get_token(1)==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { + } else if (tokenizer->get_token()==GDTokenizer::TK_PERIOD && (tokenizer->get_token(1)==GDTokenizer::TK_IDENTIFIER || tokenizer->get_token(1)==GDTokenizer::TK_CURSOR) && tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { // parent call tokenizer->advance(); //goto identifier @@ -588,12 +671,16 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ /*SelfNode *self = alloc_node<SelfNode>(); op->arguments.push_back(self); forbidden for now */ + StringName identifier; + if (_get_completable_identifier(COMPLETION_PARENT_FUNCTION,identifier)) { + //indexing stuff + } - IdentifierNode* id = alloc_node<IdentifierNode>(); - id->name=tokenizer->get_token_identifier(); + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name=identifier; op->arguments.push_back(id); - tokenizer->advance(2); + tokenizer->advance(1); if (!_parse_arguments(op,op->arguments,p_static)) return NULL; @@ -628,7 +715,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ //indexing using "." - if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) { + if (tokenizer->get_token(1)!=GDTokenizer::TK_CURSOR && tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer->get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) { _set_error("Expected identifier as member"); return NULL; } else if (tokenizer->get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) { @@ -636,37 +723,67 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ OperatorNode * op = alloc_node<OperatorNode>(); op->op=OperatorNode::OP_CALL; + tokenizer->advance(); + IdentifierNode * id = alloc_node<IdentifierNode>(); - if (tokenizer->get_token(1)==GDTokenizer::TK_BUILT_IN_FUNC ) { + if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_FUNC ) { //small hack so built in funcs don't obfuscate methods - id->name=GDFunctions::get_func_name(tokenizer->get_token_built_in_func(1)); + id->name=GDFunctions::get_func_name(tokenizer->get_token_built_in_func()); + tokenizer->advance(); + } else { - id->name=tokenizer->get_token_identifier(1); + StringName identifier; + if (_get_completable_identifier(COMPLETION_METHOD,identifier)) { + completion_node=op; + //indexing stuff + } + + id->name=identifier; } op->arguments.push_back(expr); // call what op->arguments.push_back(id); // call func //get arguments - tokenizer->advance(3); - if (!_parse_arguments(op,op->arguments,p_static)) + tokenizer->advance(1); + if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) { + _make_completable_call(0); + completion_node=op; + + } + if (!_parse_arguments(op,op->arguments,p_static,true)) return NULL; expr=op; } else { //simple indexing! + + OperatorNode * op = alloc_node<OperatorNode>(); op->op=OperatorNode::OP_INDEX_NAMED; + tokenizer->advance(); + + + StringName identifier; + if (_get_completable_identifier(COMPLETION_INDEX,identifier)) { + + if (identifier==StringName()) { + identifier="@temp"; //so it parses allright + } + completion_node=op; + + //indexing stuff + } IdentifierNode * id = alloc_node<IdentifierNode>(); - id->name=tokenizer->get_token_identifier(1); + id->name=identifier; op->arguments.push_back(expr); op->arguments.push_back(id); expr=op; - tokenizer->advance(2); + } } else if (tokenizer->get_token()==GDTokenizer::TK_BRACKET_OPEN) { @@ -1142,7 +1259,7 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { cn->value=v; return cn; - } else if (op->arguments[0]->type==Node::TYPE_CONSTANT && op->arguments[1]->type==Node::TYPE_IDENTIFIER) { + } /*else if (op->arguments[0]->type==Node::TYPE_CONSTANT && op->arguments[1]->type==Node::TYPE_IDENTIFIER) { ConstantNode *ca = static_cast<ConstantNode*>(op->arguments[0]); IdentifierNode *ib = static_cast<IdentifierNode*>(op->arguments[1]); @@ -1157,10 +1274,31 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { ConstantNode *cn = alloc_node<ConstantNode>(); cn->value=v; return cn; + }*/ + + return op; + + } else if (op->op==OperatorNode::OP_INDEX_NAMED) { + if (op->arguments[0]->type==Node::TYPE_CONSTANT && op->arguments[1]->type==Node::TYPE_IDENTIFIER) { + + ConstantNode *ca = static_cast<ConstantNode*>(op->arguments[0]); + IdentifierNode *ib = static_cast<IdentifierNode*>(op->arguments[1]); + + bool valid; + Variant v = ca->value.get_named(ib->name,&valid); + if (!valid) { + _set_error("invalid index '"+String(ib->name)+"' in constant expression"); + return op; + } + + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value=v; + return cn; } return op; + } //validate assignment (don't assign to cosntant expression @@ -1179,7 +1317,7 @@ GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) { case OperatorNode::OP_ASSIGN_BIT_XOR: { if (op->arguments[0]->type==Node::TYPE_CONSTANT) { - _set_error("Can't assign to constant"); + _set_error("Can't assign to constant",tokenizer->get_token_line()-1); return op; } @@ -1398,6 +1536,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { cf_if->arguments.push_back(condition); cf_if->body = alloc_node<BlockNode>(); + cf_if->body->parent_block=p_block; p_block->sub_blocks.push_back(cf_if->body); if (!_enter_indent_block(cf_if->body)) { @@ -1405,7 +1544,10 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; } + current_block=cf_if->body; _parse_block(cf_if->body,p_static); + current_block=p_block; + if (error_set) return; p_block->statements.push_back(cf_if); @@ -1432,6 +1574,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { tokenizer->advance(); cf_if->body_else=alloc_node<BlockNode>(); + cf_if->body_else->parent_block=p_block; p_block->sub_blocks.push_back(cf_if->body_else); ControlFlowNode *cf_else = alloc_node<ControlFlowNode>(); @@ -1447,6 +1590,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { cf_if->body_else->statements.push_back(cf_else); cf_if=cf_else; cf_if->body=alloc_node<BlockNode>(); + cf_if->body->parent_block=p_block; p_block->sub_blocks.push_back(cf_if->body); @@ -1455,7 +1599,9 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; } + current_block=cf_else->body; _parse_block(cf_else->body,p_static); + current_block=p_block; if (error_set) return; @@ -1471,13 +1617,16 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { tokenizer->advance(); cf_if->body_else=alloc_node<BlockNode>(); + cf_if->body_else->parent_block=p_block; p_block->sub_blocks.push_back(cf_if->body_else); if (!_enter_indent_block(cf_if->body_else)) { p_block->end_line=tokenizer->get_token_line(); return; } + current_block=cf_if->body_else; _parse_block(cf_if->body_else,p_static); + current_block=p_block; if (error_set) return; @@ -1504,6 +1653,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { cf_while->arguments.push_back(condition); cf_while->body = alloc_node<BlockNode>(); + cf_while->body->parent_block=p_block; p_block->sub_blocks.push_back(cf_while->body); if (!_enter_indent_block(cf_while->body)) { @@ -1511,7 +1661,9 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; } + current_block=cf_while->body; _parse_block(cf_while->body,p_static); + current_block=p_block; if (error_set) return; p_block->statements.push_back(cf_while); @@ -1548,6 +1700,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { cf_for->arguments.push_back(container); cf_for->body = alloc_node<BlockNode>(); + cf_for->body->parent_block=p_block; p_block->sub_blocks.push_back(cf_for->body); if (!_enter_indent_block(cf_for->body)) { @@ -1555,7 +1708,10 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; } + current_block=cf_for->body; _parse_block(cf_for->body,p_static); + current_block=p_block; + if (error_set) return; p_block->statements.push_back(cf_for); @@ -1821,7 +1977,9 @@ void GDParser::_parse_class(ClassNode *p_class) { ClassNode *newclass = alloc_node<ClassNode>(); newclass->initializer = alloc_node<BlockNode>(); + newclass->initializer->parent_class=newclass; newclass->name=name; + newclass->owner=p_class; p_class->subclasses.push_back(newclass); @@ -1838,7 +1996,9 @@ void GDParser::_parse_class(ClassNode *p_class) { _set_error("Indented block expected."); return; } + current_class=newclass; _parse_class(newclass); + current_class=p_class; } break; /* this is for functions.... @@ -1867,14 +2027,20 @@ void GDParser::_parse_class(ClassNode *p_class) { } - if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER) { + tokenizer->advance(); + StringName name; + + if (_get_completable_identifier(COMPLETION_VIRTUAL_FUNC,name)) { + + } + + + if (name==StringName()) { _set_error("Expected identifier after 'func' (syntax: 'func <identifier>([arguments]):' )."); return; } - StringName name = tokenizer->get_token_identifier(1); - for(int i=0;i<p_class->functions.size();i++) { if (p_class->functions[i]->name==name) { _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->functions[i]->line)+")."); @@ -1885,7 +2051,7 @@ void GDParser::_parse_class(ClassNode *p_class) { _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->static_functions[i]->line)+")."); } } - tokenizer->advance(2); + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { @@ -1976,6 +2142,7 @@ void GDParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); BlockNode *block = alloc_node<BlockNode>(); + block->parent_class=p_class; if (name=="_init") { @@ -2051,8 +2218,12 @@ void GDParser::_parse_class(ClassNode *p_class) { p_class->functions.push_back(function); - _parse_block(block,_static); + current_function=function; function->body=block; + current_block=block; + _parse_block(block,_static); + current_block=NULL; + //arguments } break; case GDTokenizer::TK_PR_EXPORT: { @@ -2357,83 +2528,120 @@ void GDParser::_parse_class(ClassNode *p_class) { } member.identifier=tokenizer->get_token_identifier(); + member.expression=NULL; member._export.name=member.identifier; + member.line=tokenizer->get_token_line(); tokenizer->advance(); - p_class->variables.push_back(member); + if (tokenizer->get_token()==GDTokenizer::TK_OP_ASSIGN) { - if (tokenizer->get_token()!=GDTokenizer::TK_OP_ASSIGN) { +#ifdef DEBUG_ENABLED + int line = tokenizer->get_token_line(); +#endif + tokenizer->advance(); - if (autoexport) { + Node *subexpr=NULL; - _set_error("Type-less export needs a constant expression assigned to infer type."); + subexpr = _parse_and_reduce_expression(p_class,false); + if (!subexpr) return; - } - break; - } -#ifdef DEBUG_ENABLED - int line = tokenizer->get_token_line(); -#endif - tokenizer->advance(); - Node *subexpr=NULL; + member.expression=subexpr; - subexpr = _parse_and_reduce_expression(p_class,false); - if (!subexpr) - return; + if (autoexport) { + if (subexpr->type==Node::TYPE_ARRAY) { - if (autoexport) { - if (subexpr->type==Node::TYPE_ARRAY) { + member._export.type=Variant::ARRAY; - p_class->variables[p_class->variables.size()-1]._export.type=Variant::ARRAY; + } else if (subexpr->type==Node::TYPE_DICTIONARY) { - } else if (subexpr->type==Node::TYPE_DICTIONARY) { + member._export.type=Variant::DICTIONARY; - p_class->variables[p_class->variables.size()-1]._export.type=Variant::DICTIONARY; + } else { - } else { + if (subexpr->type!=Node::TYPE_CONSTANT) { - if (subexpr->type!=Node::TYPE_CONSTANT) { + _set_error("Type-less export needs a constant expression assigned to infer type."); + return; + } - _set_error("Type-less export needs a constant expression assigned to infer type."); - return; + ConstantNode *cn = static_cast<ConstantNode*>(subexpr); + if (cn->value.get_type()==Variant::NIL) { + + _set_error("Can't accept a null constant expression for infering export type."); + return; + } + member._export.type=cn->value.get_type(); } + } +#ifdef TOOLS_ENABLED + if (subexpr->type==Node::TYPE_CONSTANT && member._export.type!=Variant::NIL) { ConstantNode *cn = static_cast<ConstantNode*>(subexpr); - if (cn->value.get_type()==Variant::NIL) { - - _set_error("Can't accept a null constant expression for infering export type."); - return; + if (cn->value.get_type()!=Variant::NIL) { + member.default_value=cn->value; } - p_class->variables[p_class->variables.size()-1]._export.type=cn->value.get_type(); } - } -#ifdef TOOLS_ENABLED - if (subexpr->type==Node::TYPE_CONSTANT && p_class->variables[p_class->variables.size()-1]._export.type!=Variant::NIL) { +#endif + + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name=member.identifier; + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=OperatorNode::OP_INIT_ASSIGN; + op->arguments.push_back(id); + op->arguments.push_back(subexpr); + +#ifdef DEBUG_ENABLED + NewLineNode *nl = alloc_node<NewLineNode>(); + nl->line=line; + p_class->initializer->statements.push_back(nl); +#endif + p_class->initializer->statements.push_back(op); + + + + } else { + + if (autoexport) { - ConstantNode *cn = static_cast<ConstantNode*>(subexpr); - if (cn->value.get_type()!=Variant::NIL) { - p_class->variables[p_class->variables.size()-1].default_value=cn->value; + _set_error("Type-less export needs a constant expression assigned to infer type."); + return; } + } -#endif + if (tokenizer->get_token()==GDTokenizer::TK_PR_SETGET) { - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->name=member.identifier; + tokenizer->advance(); - OperatorNode *op = alloc_node<OperatorNode>(); - op->op=OperatorNode::OP_ASSIGN; - op->arguments.push_back(id); - op->arguments.push_back(subexpr); + if (tokenizer->get_token()!=GDTokenizer::TK_COMMA) { + //just comma means using only getter + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + _set_error("Expected identifier for setter function after 'notify'."); + } -#ifdef DEBUG_ENABLED - NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line=line; - p_class->initializer->statements.push_back(nl); -#endif - p_class->initializer->statements.push_back(op); + member.setter=tokenizer->get_token_identifier(); + + tokenizer->advance(); + } + + if (tokenizer->get_token()==GDTokenizer::TK_COMMA) { + //there is a getter + tokenizer->advance(); + + if (tokenizer->get_token()!=GDTokenizer::TK_IDENTIFIER) { + _set_error("Expected identifier for getter function after ','."); + } + + member.getter=tokenizer->get_token_identifier(); + tokenizer->advance(); + + } + } + + p_class->variables.push_back(member); _end_statement(); @@ -2531,6 +2739,8 @@ Error GDParser::_parse(const String& p_base_path) { //assume class ClassNode *main_class = alloc_node<ClassNode>(); main_class->initializer = alloc_node<BlockNode>(); + main_class->initializer->parent_class=main_class; + current_class=main_class; _parse_class(main_class); @@ -2546,8 +2756,18 @@ Error GDParser::_parse(const String& p_base_path) { return OK; } -Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path) { +Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path, const String &p_self_path) { + + completion_type=COMPLETION_NONE; + completion_node=NULL; + completion_class=NULL; + completion_function=NULL; + completion_block=NULL; + current_block=NULL; + current_class=NULL; + current_function=NULL; + self_path=p_self_path; GDTokenizerBuffer *tb = memnew( GDTokenizerBuffer ); tb->set_code_buffer(p_bytecode); tokenizer=tb; @@ -2558,9 +2778,19 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p } -Error GDParser::parse(const String& p_code,const String& p_base_path,bool p_just_validate) { +Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_just_validate, const String &p_self_path) { + completion_type=COMPLETION_NONE; + completion_node=NULL; + completion_class=NULL; + completion_function=NULL; + completion_block=NULL; + current_block=NULL; + current_class=NULL; + current_function=NULL; + + self_path=p_self_path; GDTokenizerText *tt = memnew( GDTokenizerText ); tt->set_code(p_code); @@ -2589,6 +2819,16 @@ void GDParser::clear() { head=NULL; list=NULL; + completion_type=COMPLETION_NONE; + completion_node=NULL; + completion_class=NULL; + completion_function=NULL; + completion_block=NULL; + current_block=NULL; + current_class=NULL; + + current_function=NULL; + validating=false; error_set=false; tab_level.clear(); @@ -2602,6 +2842,52 @@ void GDParser::clear() { } + +GDParser::CompletionType GDParser::get_completion_type() { + + return completion_type; +} + +StringName GDParser::get_completion_cursor() { + + return completion_cursor; +} + +int GDParser::get_completion_line() { + + return completion_line; +} + +Variant::Type GDParser::get_completion_built_in_constant(){ + + return completion_built_in_constant; +} + +GDParser::Node *GDParser::get_completion_node(){ + + return completion_node; +} + +GDParser::BlockNode *GDParser::get_completion_block() { + + return completion_block; +} + +GDParser::ClassNode *GDParser::get_completion_class(){ + + return completion_class; +} + +GDParser::FunctionNode *GDParser::get_completion_function(){ + + return completion_function; +} + +int GDParser::get_completion_argument_index() { + + return completion_argument; +} + GDParser::GDParser() { head=NULL; diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 50b84d389a..44e7b55323 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -82,6 +82,10 @@ public: Variant default_value; #endif StringName identifier; + StringName setter; + StringName getter; + int line; + Node *expression; }; struct Constant { StringName identifier; @@ -94,10 +98,11 @@ public: Vector<FunctionNode*> functions; Vector<FunctionNode*> static_functions; BlockNode *initializer; + ClassNode *owner; //Vector<Node*> initializers; int end_line; - ClassNode() { tool=false; type=TYPE_CLASS; extends_used=false; end_line=-1;} + ClassNode() { tool=false; type=TYPE_CLASS; extends_used=false; end_line=-1; owner=NULL;} }; @@ -116,6 +121,8 @@ public: struct BlockNode : public Node { + ClassNode *parent_class; + BlockNode *parent_block; Map<StringName,int> locals; List<Node*> statements; Vector<StringName> variables; @@ -124,7 +131,7 @@ public: //the following is useful for code completion List<BlockNode*> sub_blocks; int end_line; - BlockNode() { type=TYPE_BLOCK; end_line=-1;} + BlockNode() { type=TYPE_BLOCK; end_line=-1; parent_block=NULL; parent_class=NULL; } }; struct TypeNode : public Node { @@ -213,6 +220,7 @@ public: OP_MOD, OP_SHIFT_LEFT, OP_SHIFT_RIGHT, + OP_INIT_ASSIGN, OP_ASSIGN, OP_ASSIGN_ADD, OP_ASSIGN_SUB, @@ -346,6 +354,19 @@ public: }; */ + enum CompletionType { + COMPLETION_NONE, + COMPLETION_BUILT_IN_TYPE_CONSTANT, + COMPLETION_FUNCTION, + COMPLETION_IDENTIFIER, + COMPLETION_PARENT_FUNCTION, + COMPLETION_METHOD, + COMPLETION_CALL_ARGUMENTS, + COMPLETION_INDEX, + COMPLETION_VIRTUAL_FUNC + }; + + private: @@ -370,13 +391,33 @@ private: List<int> tab_level; String base_path; + String self_path; + + + ClassNode *current_class; + FunctionNode *current_function; + BlockNode *current_block; + + bool _get_completable_identifier(CompletionType p_type,StringName& identifier); + void _make_completable_call(int p_arg); + + CompletionType completion_type; + StringName completion_cursor; + bool completion_static; + Variant::Type completion_built_in_constant; + Node *completion_node; + ClassNode *completion_class; + FunctionNode *completion_function; + BlockNode *completion_block; + int completion_line; + int completion_argument; PropertyInfo current_export; void _set_error(const String& p_error, int p_line=-1, int p_column=-1); - bool _parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static); + bool _parse_arguments(Node* p_parent, Vector<Node*>& p_args, bool p_static, bool p_can_codecomplete=false); bool _enter_indent_block(BlockNode *p_block=NULL); bool _parse_newline(); Node* _parse_expression(Node *p_parent,bool p_static,bool p_allow_assign=false); @@ -395,11 +436,24 @@ public: String get_error() const; int get_error_line() const; int get_error_column() const; - Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false); - Error parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path=""); + Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path=""); + Error parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path="",const String& p_self_path=""); const Node *get_parse_tree() const; + //completion info + + CompletionType get_completion_type(); + StringName get_completion_cursor(); + int get_completion_line(); + Variant::Type get_completion_built_in_constant(); + Node *get_completion_node(); + ClassNode *get_completion_class(); + BlockNode *get_completion_block(); + FunctionNode *get_completion_function(); + int get_completion_argument_index(); + + void clear(); GDParser(); ~GDParser(); diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index f0ef69df5b..f13b51c008 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -337,9 +337,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a Variant::evaluate(op,*a,*b,*dst,valid); if (!valid) { - if (false && dst->get_type()==Variant::STRING) { + if (dst->get_type()==Variant::STRING) { //return a string when invalid with the error err_text=*dst; + err_text += " in operator '"+Variant::get_operator_name(op)+"'."; } else { err_text="Invalid operands '"+Variant::get_type_name(a->get_type())+"' and '"+Variant::get_type_name(b->get_type())+"' in operator '"+Variant::get_operator_name(op)+"'."; } @@ -820,7 +821,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a gdfs->state.stack.resize(alloca_size); //copy variant stack for(int i=0;i<_stack_size;i++) { - memnew_placement(&stack[sizeof(Variant)*i],Variant(stack[i])); + memnew_placement(&gdfs->state.stack[sizeof(Variant)*i],Variant(stack[i])); } gdfs->state.stack_size=_stack_size; gdfs->state.self=self; @@ -1440,8 +1441,8 @@ GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Obj if (err.error!=Variant::CallError::CALL_OK) { instance->script=Ref<GDScript>(); + instance->owner->set_script_instance(NULL); instances.erase(p_owner); - memdelete(instance); ERR_FAIL_COND_V(err.error!=Variant::CallError::CALL_OK, NULL); //error consrtucting } @@ -1523,6 +1524,7 @@ void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { placeholders.erase(p_placeholder); } +/* void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { @@ -1537,7 +1539,7 @@ void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { _GDScriptMemberSort ms; ERR_CONTINUE(!scr->member_indices.has(E->key())); - ms.index=scr->member_indices[E->key()]; + ms.index=scr->member_indices[E->key()].index; ms.name=E->key(); msort.push_back(ms); @@ -1563,7 +1565,7 @@ void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) { p_placeholder->update(plist,default_values); -} +}*/ #endif ScriptInstance* GDScript::instance_create(Object *p_this) { @@ -1582,7 +1584,8 @@ ScriptInstance* GDScript::instance_create(Object *p_this) { }*/ PlaceHolderScriptInstance *si = memnew( PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(),Ref<Script>(this),p_this) ); placeholders.insert(si); - _update_placeholder(si); + //_update_placeholder(si); + _update_exports(); return si; #else return NULL; @@ -1623,70 +1626,158 @@ String GDScript::get_source_code() const { } void GDScript::set_source_code(const String& p_code) { + if (source==p_code) + return; source=p_code; +#ifdef TOOLS_ENABLED + source_changed_cache=true; + //print_line("SC CHANGED "+get_path()); +#endif + } +#ifdef TOOLS_ENABLED +void GDScript::_update_exports_values(Map<StringName,Variant>& values, List<PropertyInfo> &propnames) { + + if (base_cache.is_valid()) { + base_cache->_update_exports_values(values,propnames); + } + + for(Map<StringName,Variant>::Element *E=member_default_values_cache.front();E;E=E->next()) { + values[E->key()]=E->get(); + } -void GDScript::_update_exports(Set<PlaceHolderScriptInstance*> *p_instances) { + for (List<PropertyInfo>::Element *E=members_cache.front();E;E=E->next()) { + propnames.push_back(E->get()); + } + +} +#endif + +bool GDScript::_update_exports() { #ifdef TOOLS_ENABLED - String basedir=path; + bool changed=false; - if (basedir=="") - basedir=get_path(); + if (source_changed_cache) { + //print_line("updating source for "+get_path()); + source_changed_cache=false; + changed=true; - if (basedir!="") - basedir=basedir.get_base_dir(); + String basedir=path; - GDParser parser; - Error err = parser.parse(source,basedir,true); - if (err) - return; //do none + if (basedir=="") + basedir=get_path(); - const GDParser::Node* root = parser.get_parse_tree(); - ERR_FAIL_COND(root->type!=GDParser::Node::TYPE_CLASS); + if (basedir!="") + basedir=basedir.get_base_dir(); + GDParser parser; + Error err = parser.parse(source,basedir,true,path); + if (err==OK) { - const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root); + const GDParser::Node* root = parser.get_parse_tree(); + ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,false); - if (c->extends_used && String(c->extends_file)!="") { + const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root); - Ref<GDScript> bf = ResourceLoader::load(c->extends_file); - if (bf.is_valid()) { + if (base_cache.is_valid()) { + base_cache->inheriters_cache.erase(get_instance_ID()); + base_cache=Ref<GDScript>(); + } - bf->_update_exports(p_instances); - } - } + if (c->extends_used && String(c->extends_file)!="" && String(c->extends_file) != get_path()) { - List<PropertyInfo> plist; + String path = c->extends_file; + if (path.is_rel_path()) { - Map<StringName,Variant> default_values; + String base = get_path(); + if (base=="" || base.is_rel_path()) { - for(int i=0;i<c->variables.size();i++) { - if (c->variables[i]._export.type==Variant::NIL) - continue; + ERR_PRINT(("Could not resolve relative path for parent class: "+path).utf8().get_data()); + } else { + path=base.get_base_dir().plus_file(path); + } + } + + Ref<GDScript> bf = ResourceLoader::load(path); + + if (bf.is_valid()) { + + //print_line("parent is: "+bf->get_path()); + base_cache=bf; + bf->inheriters_cache.insert(get_instance_ID()); + + //bf->_update_exports(p_instances,true,false); + + } + } + + members_cache.clear();; + member_default_values_cache.clear(); + + for(int i=0;i<c->variables.size();i++) { + if (c->variables[i]._export.type==Variant::NIL) + continue; + + members_cache.push_back(c->variables[i]._export); + //print_line("found "+c->variables[i]._export.name); + member_default_values_cache[c->variables[i].identifier]=c->variables[i].default_value; + } + } + } else { + //print_line("unchaged is "+get_path()); - plist.push_back(c->variables[i]._export); - default_values[c->variables[i].identifier]=c->variables[i].default_value; } + if (base_cache.is_valid()) { + if (base_cache->_update_exports()) { + changed = true; + } + } + + if (/*changed &&*/ placeholders.size()) { //hm :( + + //print_line("updating placeholders for "+get_path()); + + //update placeholders if any + Map<StringName,Variant> values; + List<PropertyInfo> propnames; + _update_exports_values(values,propnames); - for (Set<PlaceHolderScriptInstance*>::Element *E=p_instances->front();E;E=E->next()) { + for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { - E->get()->update(plist,default_values); + E->get()->update(propnames,values); + } } + + return changed; + #endif + return false; } void GDScript::update_exports() { #ifdef TOOLS_ENABLED - _update_exports(&placeholders); + _update_exports(); + Set<ObjectID> copy=inheriters_cache; //might get modified + + //print_line("update exports for "+get_path()+" ic: "+itos(copy.size())); + for(Set<ObjectID>::Element *E=copy.front();E;E=E->next()) { + Object *id=ObjectDB::get_instance(E->get()); + if (!id) + continue; + GDScript *s=id->cast_to<GDScript>(); + if (!s) + continue; + s->update_exports(); + } #endif } @@ -1718,7 +1809,7 @@ Error GDScript::reload() { valid=false; GDParser parser; - Error err = parser.parse(source,basedir); + Error err = parser.parse(source,basedir,false,path); if (err) { if (ScriptDebugger::get_singleton()) { GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),parser.get_error_line(),"Parser Error: "+parser.get_error()); @@ -1746,10 +1837,10 @@ Error GDScript::reload() { } #ifdef TOOLS_ENABLED - for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { + /*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) { _update_placeholder(E->get()); - } + }*/ #endif return OK; } @@ -1892,7 +1983,7 @@ Error GDScript::load_byte_code(const String& p_path) { valid=false; GDParser parser; - Error err = parser.parse_bytecode(bytecode,basedir); + Error err = parser.parse_bytecode(bytecode,basedir,get_path()); if (err) { _err_print_error("GDScript::load_byte_code",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data()); ERR_FAIL_V(ERR_PARSE_ERROR); @@ -1945,6 +2036,10 @@ Error GDScript::load_source_code(const String& p_path) { } source=s; +#ifdef TOOLS_ENABLED + source_changed_cache=true; +#endif + //print_line("LSC :"+get_path()); path=p_path; return OK; @@ -1961,9 +2056,9 @@ const Map<StringName,GDFunction>& GDScript::debug_get_member_functions() const { StringName GDScript::debug_get_member_by_index(int p_idx) const { - for(const Map<StringName,int>::Element *E=member_indices.front();E;E=E->next()) { + for(const Map<StringName,MemberInfo>::Element *E=member_indices.front();E;E=E->next()) { - if (E->get()==p_idx) + if (E->get().index==p_idx) return E->key(); } @@ -1986,6 +2081,9 @@ GDScript::GDScript() { _base=NULL; _owner=NULL; tool=false; +#ifdef TOOLS_ENABLED + source_changed_cache=false; +#endif } @@ -2002,11 +2100,18 @@ bool GDInstance::set(const StringName& p_name, const Variant& p_value) { //member { - const Map<StringName,int>::Element *E = script->member_indices.find(p_name); + const Map<StringName,GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); if (E) { - members[E->get()]=p_value; + members[E->get().index]=p_value; + if (E->get().setter) { + const Variant *val=&p_value; + Variant::CallError err; + call(E->get().setter,&val,1,err); + if (err.error==Variant::CallError::CALL_OK) { + return true; //function exists, call was successful + } + } return true; - } } @@ -2039,9 +2144,16 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const { while(sptr) { { - const Map<StringName,int>::Element *E = script->member_indices.find(p_name); + const Map<StringName,GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); if (E) { - r_ret=members[E->get()]; + if (E->get().getter) { + Variant::CallError err; + r_ret=const_cast<GDInstance*>(this)->call(E->get().getter,NULL,0,err); + if (err.error==Variant::CallError::CALL_OK) { + return true; + } + } + r_ret=members[E->get().index]; return true; //index found } @@ -2131,7 +2243,7 @@ void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const { _GDScriptMemberSort ms; ERR_CONTINUE(!sptr->member_indices.has(E->key())); - ms.index=sptr->member_indices[E->key()]; + ms.index=sptr->member_indices[E->key()].index; ms.name=E->key(); msort.push_back(ms); @@ -2434,6 +2546,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "if" , "in" , "null" , + "not" , "return" , "self" , "while" , @@ -2441,6 +2554,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "false" , "tool", "var", + "setget", "pass", "and", "or", @@ -2448,6 +2562,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "assert", "yield", "static", + "float", + "int", 0}; @@ -2581,7 +2697,10 @@ Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resour } file->store_string(source); - + if (file->get_error()!=OK && file->get_error()!=ERR_FILE_EOF) { + memdelete(file); + return ERR_CANT_CREATE; + } file->close(); memdelete(file); return OK; diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index 6f0c156d2a..5574b30d44 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -129,6 +129,10 @@ friend class GDCompiler; const char*_func_cname; #endif +#ifdef TOOLS_ENABLED + Vector<StringName> arg_names; +#endif + List<StackDebug> stack_debug; _FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const; @@ -169,6 +173,19 @@ public: _FORCE_INLINE_ bool is_empty() const { return _code_size==0; } int get_argument_count() const { return _argument_count; } + StringName get_argument_name(int p_idx) const { +#ifdef TOOLS_ENABLED + ERR_FAIL_INDEX_V(p_idx,arg_names.size(),StringName()); + return arg_names[p_idx]; +#endif + return StringName(); + + } + Variant get_default_argument(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,default_arguments.size(),Variant()); + return default_arguments[p_idx]; + } + Variant call(GDInstance *p_instance,const Variant **p_args, int p_argcount,Variant::CallError& r_err,CallState *p_state=NULL); GDFunction(); @@ -220,11 +237,18 @@ class GDScript : public Script { bool valid; + struct MemberInfo { + int index; + StringName setter; + StringName getter; + }; friend class GDInstance; friend class GDFunction; friend class GDCompiler; friend class GDFunctions; +friend class GDScriptLanguage; + Variant _static_ref; //used for static call Ref<GDNativeClass> native; Ref<GDScript> base; @@ -234,11 +258,20 @@ friend class GDFunctions; Set<StringName> members; //members are just indices to the instanced script. Map<StringName,Variant> constants; Map<StringName,GDFunction> member_functions; - Map<StringName,int> member_indices; //members are just indices to the instanced script. + Map<StringName,MemberInfo> member_indices; //members are just indices to the instanced script. Map<StringName,Ref<GDScript> > subclasses; #ifdef TOOLS_ENABLED + Map<StringName,Variant> member_default_values; + + List<PropertyInfo> members_cache; + Map<StringName,Variant> member_default_values_cache; + Ref<GDScript> base_cache; + Set<ObjectID> inheriters_cache; + bool source_changed_cache; + void _update_exports_values(Map<StringName,Variant>& values, List<PropertyInfo> &propnames); + #endif Map<StringName,PropertyInfo> member_info; @@ -258,13 +291,13 @@ friend class GDFunctions; #ifdef TOOLS_ENABLED Set<PlaceHolderScriptInstance*> placeholders; - void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); + //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); #endif - void _update_exports(Set<PlaceHolderScriptInstance *> *p_instances); + bool _update_exports(); protected: bool _get(const StringName& p_name,Variant &r_ret) const; @@ -277,6 +310,7 @@ protected: static void _bind_methods(); public: + bool is_valid() const { return valid; } const Map<StringName,Ref<GDScript> >& get_subclasses() const { return subclasses; } const Map<StringName,Variant >& get_constants() const { return constants; } @@ -288,7 +322,7 @@ public: bool is_tool() const { return tool; } Ref<GDScript> get_base() const; - const Map<StringName,int>& debug_get_member_indices() const { return member_indices; } + const Map<StringName,MemberInfo>& debug_get_member_indices() const { return member_indices; } const Map<StringName,GDFunction>& debug_get_member_functions() const; //this is debug only StringName debug_get_member_by_index(int p_idx) const; @@ -472,7 +506,7 @@ public: virtual bool has_named_classes() const; virtual int find_function(const String& p_function,const String& p_code) const; virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const; - virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path,const String& p_keyword, List<String>* r_options); + virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint); virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const; /* DEBUGGER FUNCTIONS */ diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 7a1d6814ba..1979577a17 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -91,6 +91,7 @@ const char* GDTokenizer::token_names[TK_MAX]={ "tool", "static", "export", +"setget", "const", "var", "preload", @@ -109,7 +110,8 @@ const char* GDTokenizer::token_names[TK_MAX]={ "':'", "'\\n'", "Error", -"EOF"}; +"EOF", +"Cursor"}; const char *GDTokenizer::get_token_name(Token p_token) { @@ -237,7 +239,8 @@ void GDTokenizerText::_advance() { while (true) { - bool is_node_path=false; + bool is_node_path = false; + StringMode string_mode=STRING_DOUBLE_QUOTE; switch(GETCHAR(0)) { case 0: @@ -527,24 +530,46 @@ void GDTokenizerText::_advance() { } } break; case '@': - if (CharType(GETCHAR(1))!='"') { + if( CharType(GETCHAR(1))!='"' && CharType(GETCHAR(1))!='\'' ) { _make_error("Unexpected '@'"); return; } INCPOS(1); is_node_path=true; + + case '\'': case '"': { - + + if (GETCHAR(0)=='\'') + string_mode=STRING_SINGLE_QUOTE; + + int i=1; + if (string_mode==STRING_DOUBLE_QUOTE && GETCHAR(i)=='"' && GETCHAR(i+1)=='"') { + i+=2; + string_mode=STRING_MULTILINE; + + } + + String str; while(true) { - if (CharType(GETCHAR(i)==0)) { + if (CharType(GETCHAR(i))==0) { _make_error("Unterminated String"); return; - } else if (CharType(GETCHAR(i)=='"')) { + } else if( string_mode==STRING_DOUBLE_QUOTE && CharType(GETCHAR(i))=='"' ) { break; - } else if (CharType(GETCHAR(i)=='\\')) { + } else if( string_mode==STRING_SINGLE_QUOTE && CharType(GETCHAR(i))=='\'' ) { + break; + } else if( string_mode==STRING_MULTILINE && CharType(GETCHAR(i))=='\"' && CharType(GETCHAR(i+1))=='\"' && CharType(GETCHAR(i+2))=='\"') { + i+=2; + break; + } else if( string_mode!=STRING_MULTILINE && CharType(GETCHAR(i))=='\n') { + _make_error("Unexpected EOL at String."); + return; + + } else if (CharType(GETCHAR(i))=='\\') { //escaped characters... i++; CharType next = GETCHAR(i); @@ -627,6 +652,9 @@ void GDTokenizerText::_advance() { } } break; + case 0xFFFF: { + _make_token(TK_CURSOR); + } break; default: { if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) { @@ -823,6 +851,7 @@ void GDTokenizerText::_advance() { {TK_PR_TOOL,"tool"}, {TK_PR_STATIC,"static"}, {TK_PR_EXPORT,"export"}, + {TK_PR_SETGET,"setget"}, {TK_PR_VAR,"var"}, {TK_PR_PRELOAD,"preload"}, {TK_PR_ASSERT,"assert"}, @@ -1007,7 +1036,7 @@ void GDTokenizerText::advance(int p_amount) { ////////////////////////////////////////////////////////////////////////////////////////////////////// -#define BYTECODE_VERSION 2 +#define BYTECODE_VERSION 3 Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> & p_buffer) { diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h index 1dd538867e..ff59c249a7 100644 --- a/modules/gdscript/gd_tokenizer.h +++ b/modules/gdscript/gd_tokenizer.h @@ -98,6 +98,7 @@ public: TK_PR_TOOL, TK_PR_STATIC, TK_PR_EXPORT, + TK_PR_SETGET, TK_PR_CONST, TK_PR_VAR, TK_PR_PRELOAD, @@ -117,10 +118,18 @@ public: TK_NEWLINE, TK_ERROR, TK_EOF, + TK_CURSOR, //used for code completion TK_MAX }; protected: + + enum StringMode { + STRING_SINGLE_QUOTE, + STRING_DOUBLE_QUOTE, + STRING_MULTILINE + }; + static const char* token_names[TK_MAX]; public: static const char *get_token_name(Token p_token); diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 8b46773502..4470b7ca0c 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -121,16 +121,16 @@ static void register_editor_plugin() { void register_gdscript_types() { + ObjectTypeDB::register_type<GDScript>(); + ObjectTypeDB::register_virtual_type<GDFunctionState>(); script_language_gd=memnew( GDScriptLanguage ); - script_language_gd->init(); + //script_language_gd->init(); ScriptServer::register_language(script_language_gd); - ObjectTypeDB::register_type<GDScript>(); resource_loader_gd=memnew( ResourceFormatLoaderGDScript ); ResourceLoader::add_resource_format_loader(resource_loader_gd); resource_saver_gd=memnew( ResourceFormatSaverGDScript ); ResourceSaver::add_resource_format_saver(resource_saver_gd); - ObjectTypeDB::register_virtual_type<GDFunctionState>(); #ifdef TOOLS_ENABLED diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index d258e26a0e..441b274e33 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -122,7 +122,7 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) { Octant &g = *octant_map[ok]; g.baked=b; - g.bake_instance=VS::get_singleton()->instance_create();; + g.bake_instance=VS::get_singleton()->instance_create();; VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid()); VS::get_singleton()->instance_geometry_set_baked_light(g.bake_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID()); } @@ -418,6 +418,7 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){ Octant *g = memnew( Octant ); g->dirty=true; g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); + PhysicsServer::get_singleton()->body_attach_object_instance_ID(g->static_body,get_instance_ID()); if (is_inside_world()) PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space()); @@ -677,7 +678,7 @@ void GridMap::_octant_clear_baked(const OctantKey &p_key) { g.bake_instance=RID(); g.baked=Ref<Mesh>(); - if (is_inside_scene()) + if (is_inside_tree()) _octant_enter_world(p_key); g.dirty=true; _queue_dirty_map(); @@ -1041,7 +1042,7 @@ void GridMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_clip","enabled","clipabove","floor","axis"),&GridMap::set_clip,DEFVAL(true),DEFVAL(0),DEFVAL(Vector3::AXIS_X)); - ObjectTypeDB::bind_method(_MD("crate_area","id","area"),&GridMap::create_area); + ObjectTypeDB::bind_method(_MD("create_area","id","area"),&GridMap::create_area); ObjectTypeDB::bind_method(_MD("area_get_bounds","area","bounds"),&GridMap::area_get_bounds); ObjectTypeDB::bind_method(_MD("area_set_exterior_portal","area","enable"),&GridMap::area_set_exterior_portal); ObjectTypeDB::bind_method(_MD("area_set_name","area","name"),&GridMap::area_set_name); diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 09e279305c..f2afffd321 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -974,7 +974,7 @@ void GridMapEditor::update_grid() { void GridMapEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { theme_pallete->connect("cell_selected", this,"_item_selected_cbk"); edit_mode->connect("item_selected", this,"_edit_mode_changed"); @@ -983,16 +983,16 @@ void GridMapEditor::_notification(int p_what) { for(int i=0;i<3;i++) { grid[i]=VS::get_singleton()->mesh_create(); - grid_instance[i]=VS::get_singleton()->instance_create2(grid[i],get_scene()->get_root()->get_world()->get_scenario()); + grid_instance[i]=VS::get_singleton()->instance_create2(grid[i],get_tree()->get_root()->get_world()->get_scenario()); } - selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh,get_scene()->get_root()->get_world()->get_scenario()); - duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh,get_scene()->get_root()->get_world()->get_scenario()); + selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh,get_tree()->get_root()->get_world()->get_scenario()); + duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh,get_tree()->get_root()->get_world()->get_scenario()); _update_selection_transform(); _update_duplicate_indicator(); - } else if (p_what==NOTIFICATION_EXIT_SCENE) { + } else if (p_what==NOTIFICATION_EXIT_TREE) { for(int i=0;i<3;i++) { @@ -1025,7 +1025,7 @@ void GridMapEditor::_notification(int p_what) { if (lock_view) { - EditorNode*editor = get_scene()->get_root()->get_child(0)->cast_to<EditorNode>(); + EditorNode*editor = get_tree()->get_root()->get_child(0)->cast_to<EditorNode>(); Plane p; p.normal[edit_axis]=1.0; @@ -1055,7 +1055,7 @@ void GridMapEditor::_update_cursor_instance() { Ref<Mesh> mesh = node->get_theme()->get_item_mesh(selected_pallete); if (!mesh.is_null() && mesh->get_rid().is_valid()) { - cursor_instance=VisualServer::get_singleton()->instance_create2(mesh->get_rid(),get_scene()->get_root()->get_world()->get_scenario()); + cursor_instance=VisualServer::get_singleton()->instance_create2(mesh->get_rid(),get_tree()->get_root()->get_world()->get_scenario()); VisualServer::get_singleton()->instance_set_transform(cursor_instance,cursor_transform); } } @@ -1192,8 +1192,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { undo_redo=p_editor->get_undo_redo(); int mw = EDITOR_DEF("grid_map/palette_min_width",230); - EmptyControl *ec = memnew( EmptyControl); - ec->set_minsize(Size2(mw,0)); + Control *ec = memnew( Control); + ec->set_custom_minimum_size(Size2(mw,0)); add_child(ec); @@ -1222,9 +1222,9 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { options->get_popup()->add_item("Cursor Rotate X",MENU_OPTION_CURSOR_ROTATE_X,KEY_A); options->get_popup()->add_item("Cursor Rotate Y",MENU_OPTION_CURSOR_ROTATE_Y,KEY_S); options->get_popup()->add_item("Cursor Rotate Z",MENU_OPTION_CURSOR_ROTATE_Z,KEY_D); - options->get_popup()->add_item("Cursor Back Rotate X",MENU_OPTION_CURSOR_ROTATE_X,KEY_ALT+KEY_A); - options->get_popup()->add_item("Cursor Back Rotate Y",MENU_OPTION_CURSOR_ROTATE_Y,KEY_ALT+KEY_S); - options->get_popup()->add_item("Cursor Back Rotate Z",MENU_OPTION_CURSOR_ROTATE_Z,KEY_ALT+KEY_D); + options->get_popup()->add_item("Cursor Back Rotate X",MENU_OPTION_CURSOR_ROTATE_X,KEY_MASK_SHIFT+KEY_A); + options->get_popup()->add_item("Cursor Back Rotate Y",MENU_OPTION_CURSOR_ROTATE_Y,KEY_MASK_SHIFT+KEY_S); + options->get_popup()->add_item("Cursor Back Rotate Z",MENU_OPTION_CURSOR_ROTATE_Z,KEY_MASK_SHIFT+KEY_D); options->get_popup()->add_item("Cursor Clear Rotation",MENU_OPTION_CURSOR_CLEAR_ROTATION,KEY_W); options->get_popup()->add_separator(); options->get_popup()->add_check_item("Duplicate Selects",MENU_OPTION_DUPLICATE_SELECTS); diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp index 3c3c8aa98f..887687a37b 100644 --- a/modules/gridmap/register_types.cpp +++ b/modules/gridmap/register_types.cpp @@ -27,16 +27,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_types.h" +#ifndef _3D_DISABLED #include "object_type_db.h" #include "grid_map.h" #include "grid_map_editor_plugin.h" +#endif void register_gridmap_types() { +#ifndef _3D_DISABLED ObjectTypeDB::register_type<GridMap>(); #ifdef TOOLS_ENABLED EditorPlugins::add_by_type<GridMapEditorPlugin>(); #endif +#endif } diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template index 60861db603..d31bdbfa53 100644 --- a/platform/android/AndroidManifest.xml.template +++ b/platform/android/AndroidManifest.xml.template @@ -10,7 +10,7 @@ android:largeScreens="true" android:xlargeScreens="true"/> - <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false"> + <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false" $$ADD_APPATTRIBUTE_CHUNKS$$ > <activity android:name="com.android.godot.Godot" android:label="@string/godot_project_name_string" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" @@ -33,6 +33,7 @@ $$ADD_APPLICATION_CHUNKS$$ </application> <uses-feature android:glEsVersion="0x00020000"/> +$$ADD_PERMISSION_CHUNKS$$ <uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/> <uses-permission android:name="godot.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="godot.ACCESS_FINE_LOCATION"/> diff --git a/platform/android/SCsub b/platform/android/SCsub index 3c55b993ef..6feeb8b365 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -56,6 +56,8 @@ pp_basein = open(abspath+"/AndroidManifest.xml.template","rb") pp_baseout = open(abspath+"/java/AndroidManifest.xml","wb") manifest = pp_basein.read() manifest = manifest.replace("$$ADD_APPLICATION_CHUNKS$$",env.android_manifest_chunk) +manifest = manifest.replace("$$ADD_PERMISSION_CHUNKS$$",env.android_permission_chunk) +manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$",env.android_appattributes_chunk) pp_baseout.write( manifest ) @@ -66,6 +68,6 @@ for x in env.android_module_libraries: shutil.copy(x,abspath+"/java/libs") -env_android.SharedLibrary("#bin/libgodot_android",[android_objects],SHLIBSUFFIX=env["SHLIBSUFFIX"]) +env_android.SharedLibrary("#bin/libgodot",[android_objects],SHLIBSUFFIX=env["SHLIBSUFFIX"]) #env.Command('#bin/libgodot_android.so', '#platform/android/libgodot_android.so', Copy('bin/libgodot_android.so', 'platform/android/libgodot_android.so')) diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp index 857d1a4a54..4c0c095e10 100644 --- a/platform/android/audio_driver_opensl.cpp +++ b/platform/android/audio_driver_opensl.cpp @@ -396,6 +396,14 @@ void AudioDriverOpenSL::finish(){ void AudioDriverOpenSL::set_pause(bool p_pause) { pause=p_pause; + + if (active) { + if (pause) { + (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); + } else { + (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); + } + } } diff --git a/platform/android/detect.py b/platform/android/detect.py index 062cc62b52..5ef405f7b6 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -61,6 +61,7 @@ def configure(env): import methods env.Tool('gcc') env['SPAWN'] = methods.win32_spawn + env['SHLIBSUFFIX'] = '.so' # env.android_source_modules.append("../libs/apk_expansion") env.android_source_modules.append("../libs/google_play_services") @@ -90,7 +91,7 @@ def configure(env): gcc_path=gcc_path+"/darwin-x86_64/bin" #this may be wrong env['SHLINKFLAGS'][1] = '-shared' elif (os.name=="nt"): - gcc_path=gcc_path+"/windows/bin" #this may be wrong + gcc_path=gcc_path+"/windows-x86_64/bin" #this may be wrong @@ -123,11 +124,11 @@ def configure(env): # env['CCFLAGS'] = string.split('-DNO_THREADS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -mthumb -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED ') if env['x86']=='yes': - env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') + env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED') elif env["armv6"]!="no": - env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') + env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED') else: - env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_7__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') + env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_7__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED') env.Append(LDPATH=[ld_path]) env.Append(LIBS=['OpenSLES']) diff --git a/platform/android/dir_access_android.cpp b/platform/android/dir_access_android.cpp index 60bde61fc4..80311e5a08 100644 --- a/platform/android/dir_access_android.cpp +++ b/platform/android/dir_access_android.cpp @@ -79,6 +79,9 @@ bool DirAccessAndroid::current_is_dir() const{ return false; } +bool DirAccessAndroid::current_is_hidden() const{ + return current!="." && current!=".." && current.begins_with("."); +} void DirAccessAndroid::list_dir_end(){ if (aad==NULL) diff --git a/platform/android/dir_access_android.h b/platform/android/dir_access_android.h index a6aead6eb3..57683542fa 100644 --- a/platform/android/dir_access_android.h +++ b/platform/android/dir_access_android.h @@ -52,6 +52,7 @@ public: virtual bool list_dir_begin(); ///< This starts dir listing 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/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index f32e16e7d8..98f20b2636 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -105,6 +105,12 @@ bool DirAccessJAndroid::current_is_dir() const{ return true; } + +bool DirAccessJAndroid::current_is_hidden() const { + + return current!="." && current!=".." && current.begins_with("."); +} + void DirAccessJAndroid::list_dir_end(){ if (id==0) diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h index 958ea34891..0a696506e6 100644 --- a/platform/android/dir_access_jandroid.h +++ b/platform/android/dir_access_jandroid.h @@ -60,6 +60,7 @@ public: virtual bool list_dir_begin(); ///< This starts dir listing 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/platform/android/export/export.cpp b/platform/android/export/export.cpp index aef223470a..8199e7c622 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -184,6 +184,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String cmdline; bool _signed; bool apk_expansion; + bool remove_prev; + bool use_32_fb; String apk_expansion_salt; String apk_expansion_pkey; int orientation; @@ -258,7 +260,9 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& String n=p_name; - if (n=="custom_package/debug") + if (n=="one_click_deploy/clear_previous_install") + remove_prev=p_value; + else if (n=="custom_package/debug") custom_debug_package=p_value; else if (n=="custom_package/release") custom_release_package=p_value; @@ -276,6 +280,8 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& icon=p_value; else if (n=="package/signed") _signed=p_value; + else if (n=="screen/use_32_bits_view") + use_32_fb=p_value; else if (n=="screen/orientation") orientation=p_value; else if (n=="screen/support_small") @@ -321,7 +327,9 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant& bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) const{ String n=p_name; - if (n=="custom_package/debug") + if (n=="one_click_deploy/clear_previous_install") + r_ret=remove_prev; + else if (n=="custom_package/debug") r_ret=custom_debug_package; else if (n=="custom_package/release") r_ret=custom_release_package; @@ -339,6 +347,8 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) r_ret=icon; else if (n=="package/signed") r_ret=_signed; + else if (n=="screen/use_32_bits_view") + r_ret=use_32_fb; else if (n=="screen/orientation") r_ret=orientation; else if (n=="screen/support_small") @@ -378,6 +388,7 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret) void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{ + p_list->push_back( PropertyInfo( Variant::BOOL, "one_click_deploy/clear_previous_install")); p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"apk")); p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"apk")); p_list->push_back( PropertyInfo( Variant::STRING, "command_line/extra_args")); @@ -387,13 +398,15 @@ void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list p_list->push_back( PropertyInfo( Variant::STRING, "package/name") ); p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") ); p_list->push_back( PropertyInfo( Variant::BOOL, "package/signed") ); + p_list->push_back( PropertyInfo( Variant::BOOL, "screen/use_32_bits_view") ); p_list->push_back( PropertyInfo( Variant::INT, "screen/orientation",PROPERTY_HINT_ENUM,"Landscape,Portrait") ); p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_small") ); p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_normal") ); p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_large") ); p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_xlarge") ); - p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_FILE,"keystore") ); + p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_GLOBAL_FILE,"keystore") ); p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) ); + p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_password" ) ); p_list->push_back( PropertyInfo( Variant::BOOL, "apk_expansion/enable" ) ); p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/SALT" ) ); p_list->push_back( PropertyInfo( Variant::STRING, "apk_expansion/public_key",PROPERTY_HINT_MULTILINE_TEXT ) ); @@ -1151,8 +1164,14 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d err = export_project_files(save_apk_file,&ed,false); } + + } + if (use_32_fb) + cl.push_back("-use_depth_32"); + + if (cl.size()) { //add comandline Vector<uint8_t> clf; @@ -1222,7 +1241,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d } if (!FileAccess::exists(keystore)) { - EditorNode::add_io_error("Could not find keytore, unable to export."); + EditorNode::add_io_error("Could not find keystore, unable to export."); return ERR_FILE_CANT_OPEN; } @@ -1231,6 +1250,11 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d args.push_back("SHA1"); args.push_back("-sigalg"); args.push_back("MD5withRSA"); + String tsa_url=EditorSettings::get_singleton()->get("android/timestamping_authority_url"); + if (tsa_url != "") { + args.push_back("-tsa"); + args.push_back(tsa_url); + } args.push_back("-verbose"); args.push_back("-keystore"); args.push_back(keystore); @@ -1448,16 +1472,20 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { return err; } - ep.step("Uninstalling..",1); - - print_line("Uninstalling previous version: "+devices[p_device].name); List<String> args; - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("uninstall"); - args.push_back(package); int rv; - err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); + + if (remove_prev) { + ep.step("Uninstalling..",1); + + print_line("Uninstalling previous version: "+devices[p_device].name); + + args.push_back("-s"); + args.push_back(devices[p_device].id); + args.push_back("uninstall"); + args.push_back(package); + + err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); #if 0 if (err || rv!=0) { EditorNode::add_io_error("Could not install to device."); @@ -1465,6 +1493,8 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { return ERR_CANT_CREATE; } #endif + } + print_line("Installing into device (please wait..): "+devices[p_device].name); ep.step("Installing to Device (please wait..)..",2); @@ -1473,7 +1503,7 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) { args.push_back(devices[p_device].id); args.push_back("install"); args.push_back(export_to); - rv; + err = OS::get_singleton()->execute(adb,args,true,NULL,NULL,&rv); if (err || rv!=0) { EditorNode::add_io_error("Could not install to device."); @@ -1515,6 +1545,8 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() { device_lock = Mutex::create(); quit_request=false; orientation=0; + remove_prev=true; + use_32_fb=true; device_thread=Thread::create(_device_poll_thread,this); devices_changed=true; @@ -1613,6 +1645,7 @@ void register_android_exporter() { //EDITOR_DEF("android/release_keystore",""); //EDITOR_DEF("android/release_username",""); //EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/release_keystore",PROPERTY_HINT_GLOBAL_FILE,"*.keystore")); + EDITOR_DEF("android/timestamping_authority_url",""); Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>( memnew(EditorExportPlatformAndroid) ); EditorImportExport::get_singleton()->add_export_platform(exporter); diff --git a/platform/android/globals/global_defaults.cpp b/platform/android/globals/global_defaults.cpp index 84a586d22d..824a4e3606 100644 --- a/platform/android/globals/global_defaults.cpp +++ b/platform/android/globals/global_defaults.cpp @@ -10,5 +10,5 @@ void register_android_global_defaults() { GLOBAL_DEF("display.Android/driver","GLES2"); // GLOBAL_DEF("rasterizer.Android/trilinear_mipmap_filter",false); - Globals::get_singleton()->set_custom_property_info("display.Android/driver",PropertyInfo(Variant::STRING,"display.Android/driver",PROPERTY_HINT_ENUM,"GLES1,GLES2")); + Globals::get_singleton()->set_custom_property_info("display.Android/driver",PropertyInfo(Variant::STRING,"display.Android/driver",PROPERTY_HINT_ENUM,"GLES2")); } diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index f6cd57f4f3..2abb4cec53 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -109,6 +109,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC private Button mPauseButton; private Button mWiFiSettingsButton; + private boolean use_32_bits=false; private boolean mStatePaused; private int mState; @@ -255,7 +256,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC // ...add to FrameLayout layout.addView(edittext); - mView = new GodotView(getApplication(),io,use_gl2, this); + mView = new GodotView(getApplication(),io,use_gl2,use_32_bits, this); layout.addView(mView,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); mView.setKeepScreenOn(true); @@ -358,7 +359,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC GodotLib.initialize(this,io.needsReloadHooks(),command_line); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); result_callback = null; @@ -399,7 +400,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC for(int i=0;i<command_line.length;i++) { boolean has_extra = i< command_line.length -1; - if (command_line[i].equals("-use_apk_expansion")) { + if (command_line[i].equals("-use_depth_32")) { + use_32_bits=true; + } else if (command_line[i].equals("-use_apk_expansion")) { use_apk_expansion=true; } else if (has_extra && command_line[i].equals("-apk_expansion_md5")) { main_pack_md5=command_line[i+1]; @@ -568,9 +571,24 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC } @Override public void onSensorChanged(SensorEvent event) { - float x = event.values[0]; - float y = event.values[1]; - float z = event.values[2]; + Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); + int displayRotation = display.getRotation(); + + float[] adjustedValues = new float[3]; + final int axisSwap[][] = { + { 1, -1, 0, 1 }, // ROTATION_0 + {-1, -1, 1, 0 }, // ROTATION_90 + {-1, 1, 0, 1 }, // ROTATION_180 + { 1, 1, 1, 0 } }; // ROTATION_270 + + final int[] as = axisSwap[displayRotation]; + adjustedValues[0] = (float)as[0] * event.values[ as[2] ]; + adjustedValues[1] = (float)as[1] * event.values[ as[3] ]; + adjustedValues[2] = event.values[2]; + + float x = adjustedValues[0]; + float y = adjustedValues[1]; + float z = adjustedValues[2]; GodotLib.accelerometer(x,y,z); } diff --git a/platform/android/java/src/com/android/godot/GodotIO.java b/platform/android/java/src/com/android/godot/GodotIO.java index fad489721c..ff0eb5edcc 100644 --- a/platform/android/java/src/com/android/godot/GodotIO.java +++ b/platform/android/java/src/com/android/godot/GodotIO.java @@ -438,8 +438,26 @@ public class GodotIO { try { Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri); - Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(p_uri)); - activity.startActivity(myIntent); + String path = p_uri; + String type=""; + if (path.startsWith("/")) { + //absolute path to filesystem, prepend file:// + path="file://"+path; + if (p_uri.endsWith(".png") || p_uri.endsWith(".jpg") || p_uri.endsWith(".gif") || p_uri.endsWith(".webp")) { + + type="image/*"; + } + } + + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + if (!type.equals("")) { + intent.setDataAndType(Uri.parse(path), type); + } else { + intent.setData(Uri.parse(path)); + } + + activity.startActivity(intent); return 0; } catch (ActivityNotFoundException e) { @@ -557,6 +575,58 @@ public class GodotIO { } } + + public static final int SYSTEM_DIR_DESKTOP=0; + public static final int SYSTEM_DIR_DCIM=1; + public static final int SYSTEM_DIR_DOCUMENTS=2; + public static final int SYSTEM_DIR_DOWNLOADS=3; + public static final int SYSTEM_DIR_MOVIES=4; + public static final int SYSTEM_DIR_MUSIC=5; + public static final int SYSTEM_DIR_PICTURES=6; + public static final int SYSTEM_DIR_RINGTONES=7; + + + public String getSystemDir(int idx) { + + String what=""; + switch(idx) { + case SYSTEM_DIR_DESKTOP: { + //what=Environment.DIRECTORY_DOCUMENTS; + what=Environment.DIRECTORY_DOWNLOADS; + } break; + case SYSTEM_DIR_DCIM: { + what=Environment.DIRECTORY_DCIM; + + } break; + case SYSTEM_DIR_DOCUMENTS: { + what=Environment.DIRECTORY_DOWNLOADS; + //what=Environment.DIRECTORY_DOCUMENTS; + } break; + case SYSTEM_DIR_DOWNLOADS: { + what=Environment.DIRECTORY_DOWNLOADS; + + } break; + case SYSTEM_DIR_MOVIES: { + what=Environment.DIRECTORY_MOVIES; + + } break; + case SYSTEM_DIR_MUSIC: { + what=Environment.DIRECTORY_MUSIC; + } break; + case SYSTEM_DIR_PICTURES: { + what=Environment.DIRECTORY_PICTURES; + } break; + case SYSTEM_DIR_RINGTONES: { + what=Environment.DIRECTORY_RINGTONES; + + } break; + } + + if (what.equals("")) + return ""; + return Environment.getExternalStoragePublicDirectory(what).getAbsolutePath(); + } + protected static final String PREFS_FILE = "device_id.xml"; protected static final String PREFS_DEVICE_ID = "device_id"; diff --git a/platform/android/java/src/com/android/godot/GodotView.java b/platform/android/java/src/com/android/godot/GodotView.java index f62431b94b..bd81b7f9af 100644 --- a/platform/android/java/src/com/android/godot/GodotView.java +++ b/platform/android/java/src/com/android/godot/GodotView.java @@ -71,14 +71,16 @@ public class GodotView extends GLSurfaceView { private static GodotIO io; private static boolean firsttime=true; private static boolean use_gl2=false; + private static boolean use_32=false; private Godot activity; - public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, Godot p_activity) { + public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, boolean p_use_32_bits, Godot p_activity) { super(context); ctx=context; io=p_io; use_gl2=p_use_gl2; + use_32=p_use_32_bits; activity = p_activity; @@ -366,9 +368,17 @@ public class GodotView extends GLSurfaceView { * custom config chooser. See ConfigChooser class definition * below. */ - setEGLConfigChooser( translucent ? - new ConfigChooser(8, 8, 8, 8, depth, stencil) : - new ConfigChooser(5, 6, 5, 0, depth, stencil) ); + + if (use_32) { + setEGLConfigChooser( translucent ? + new ConfigChooser(8, 8, 8, 8, 24, stencil) : + new ConfigChooser(8, 8, 8, 8, 24, stencil) ); + + } else { + setEGLConfigChooser( translucent ? + new ConfigChooser(8, 8, 8, 8, 16, stencil) : + new ConfigChooser(5, 6, 5, 0, 16, stencil) ); + } /* Set the renderer responsible for frame rendering */ setRenderer(new Renderer()); diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index fdc6f1207d..349db08e36 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -45,9 +45,18 @@ static JavaClassWrapper *java_class_wrapper=NULL; static OS_Android *os_android=NULL; -jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) { +struct jvalret { - jvalue v; + jobject obj; + jvalue val; + jvalret() { obj=NULL; } + + +}; + +jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) { + + jvalret v; switch(p_type) { @@ -59,9 +68,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jvalue val; val.z = (bool)(*p_arg); jobject obj = env->NewObjectA(bclass, ctor, &val); - v.l = obj; + v.val.l = obj; + v.obj=obj; + env->DeleteLocalRef(bclass); } else { - v.z=*p_arg; + v.val.z=*p_arg; + }; } break; case Variant::INT: { @@ -73,10 +85,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jvalue val; val.i = (int)(*p_arg); jobject obj = env->NewObjectA(bclass, ctor, &val); - v.l = obj; + v.val.l = obj; + v.obj=obj; + env->DeleteLocalRef(bclass); } else { - v.i=*p_arg; + v.val.i=*p_arg; + }; } break; case Variant::REAL: { @@ -88,17 +103,20 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jvalue val; val.d = (double)(*p_arg); jobject obj = env->NewObjectA(bclass, ctor, &val); - v.l = obj; + v.val.l = obj; + v.obj=obj; + env->DeleteLocalRef(bclass); } else { - v.f=*p_arg; + v.val.f=*p_arg; }; } break; case Variant::STRING: { String s = *p_arg; jstring jStr = env->NewStringUTF(s.utf8().get_data()); - v.l=jStr; + v.val.l=jStr; + v.obj=jStr; } break; case Variant::STRING_ARRAY: { @@ -107,9 +125,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar for(int j=0;j<sarray.size();j++) { - env->SetObjectArrayElement(arr,j,env->NewStringUTF( sarray[j].utf8().get_data() )); + jstring str = env->NewStringUTF( sarray[j].utf8().get_data() ); + env->SetObjectArrayElement(arr,j,str); + env->DeleteLocalRef(str); } - v.l=arr; + v.val.l=arr; + v.obj=arr; } break; @@ -124,27 +145,36 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jobjectArray jkeys = env->NewObjectArray(keys.size(), env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int j=0; j<keys.size(); j++) { - env->SetObjectArrayElement(jkeys, j, env->NewStringUTF(String(keys[j]).utf8().get_data())); + jstring str = env->NewStringUTF(String(keys[j]).utf8().get_data()); + env->SetObjectArrayElement(jkeys, j, str); + env->DeleteLocalRef(str); }; jmethodID set_keys = env->GetMethodID(dclass, "set_keys", "([Ljava/lang/String;)V"); jvalue val; val.l = jkeys; env->CallVoidMethodA(jdict, set_keys, &val); + env->DeleteLocalRef(jkeys); jobjectArray jvalues = env->NewObjectArray(keys.size(), env->FindClass("java/lang/Object"), NULL); for (int j=0; j<keys.size(); j++) { Variant var = dict[keys[j]]; - val = _variant_to_jvalue(env, var.get_type(), &var, true); - env->SetObjectArrayElement(jvalues, j, val.l); + jvalret v = _variant_to_jvalue(env, var.get_type(), &var, true); + env->SetObjectArrayElement(jvalues, j, v.val.l); + if (v.obj) { + env->DeleteLocalRef(v.obj); + } }; jmethodID set_values = env->GetMethodID(dclass, "set_values", "([Ljava/lang/Object;)V"); val.l = jvalues; env->CallVoidMethodA(jdict, set_values, &val); + env->DeleteLocalRef(jvalues); + env->DeleteLocalRef(dclass); - v.l = jdict; + v.val.l = jdict; + v.obj=jdict; } break; case Variant::INT_ARRAY: { @@ -153,7 +183,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jintArray arr = env->NewIntArray(array.size()); DVector<int>::Read r = array.read(); env->SetIntArrayRegion(arr,0,array.size(),r.ptr()); - v.l=arr; + v.val.l=arr; + v.obj=arr; } break; case Variant::RAW_ARRAY: { @@ -161,7 +192,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jbyteArray arr = env->NewByteArray(array.size()); DVector<uint8_t>::Read r = array.read(); env->SetByteArrayRegion(arr,0,array.size(),reinterpret_cast<const signed char*>(r.ptr())); - v.l=arr; + v.val.l=arr; + v.obj=arr; } break; case Variant::REAL_ARRAY: { @@ -170,12 +202,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar jfloatArray arr = env->NewFloatArray(array.size()); DVector<float>::Read r = array.read(); env->SetFloatArrayRegion(arr,0,array.size(),r.ptr()); - v.l=arr; + v.val.l=arr; + v.obj=arr; } break; default: { - v.i = 0; + v.val.i = 0; } break; } @@ -193,8 +226,11 @@ String _get_class_name(JNIEnv * env, jclass cls, bool* array) { jboolean isarr = env->CallBooleanMethod(cls, isArray); (*array) = isarr ? true : false; } + String name = env->GetStringUTFChars( clsName, NULL ); + env->DeleteLocalRef(clsName); + + return name; - return env->GetStringUTFChars( clsName, NULL ); }; @@ -205,6 +241,7 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) { String name = _get_class_name(env, c, &array); //print_line("name is " + name + ", array "+Variant(array)); + print_line("ARGNAME: "+name); if (name == "java.lang.String") { return String::utf8(env->GetStringUTFChars( (jstring)obj, NULL )); @@ -222,6 +259,8 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) { jstring string = (jstring) env->GetObjectArrayElement(arr, i); const char *rawString = env->GetStringUTFChars(string, 0); sarr.push_back(String(rawString)); + env->DeleteLocalRef(string); + } return sarr; @@ -320,30 +359,34 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) { jobjectArray arr = (jobjectArray)obj; int objCount = env->GetArrayLength(arr); - Array varr; + Array varr(true); for (int i=0; i<objCount; i++) { jobject jobj = env->GetObjectArrayElement(arr, i); Variant v = _jobject_to_variant(env, jobj); varr.push_back(v); + env->DeleteLocalRef(jobj); + } return varr; }; - if (name == "com.android.godot.Dictionary") { + if (name == "java.util.HashMap" || name == "com.android.godot.Dictionary") { - Dictionary ret; + Dictionary ret(true); jclass oclass = c; jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;"); jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys); StringArray keys = _jobject_to_variant(env, arr); + env->DeleteLocalRef(arr); jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;"); arr = (jobjectArray)env->CallObjectMethod(obj, get_values); Array vals = _jobject_to_variant(env, arr); + env->DeleteLocalRef(arr); //print_line("adding " + String::num(keys.size()) + " to Dictionary!"); for (int i=0; i<keys.size(); i++) { @@ -351,9 +394,12 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) { ret[keys[i]] = vals[i]; }; + return ret; }; + env->DeleteLocalRef(c); + return Variant(); }; @@ -431,9 +477,13 @@ public: JNIEnv *env = ThreadAndroid::get_env(); //print_line("argcount "+String::num(p_argcount)); + List<jobject> to_erase; for(int i=0;i<p_argcount;i++) { - v[i] = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]); + jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]); + v[i] = vr.val; + if (vr.obj) + to_erase.push_back(vr.obj); } //print_line("calling method!!"); @@ -467,6 +517,7 @@ public: jobject o = env->CallObjectMethodA(instance,E->get().method,v); String str = env->GetStringUTFChars((jstring)o, NULL ); ret=str; + env->DeleteLocalRef(o); } break; case Variant::STRING_ARRAY: { @@ -474,6 +525,7 @@ public: ret = _jobject_to_variant(env, arr); + env->DeleteLocalRef(arr); } break; case Variant::INT_ARRAY: { @@ -487,6 +539,7 @@ public: env->GetIntArrayRegion(arr,0,fCount,w.ptr()); w = DVector<int>::Write(); ret=sarr; + env->DeleteLocalRef(arr); } break; case Variant::REAL_ARRAY: { @@ -500,6 +553,7 @@ public: env->GetFloatArrayRegion(arr,0,fCount,w.ptr()); w = DVector<float>::Write(); ret=sarr; + env->DeleteLocalRef(arr); } break; case Variant::DICTIONARY: { @@ -507,6 +561,7 @@ public: //print_line("call dictionary"); jobject obj = env->CallObjectMethodA(instance, E->get().method, v); ret = _jobject_to_variant(env, obj); + env->DeleteLocalRef(obj); } break; default: { @@ -517,6 +572,10 @@ public: } break; } + while (to_erase.size()) { + env->DeleteLocalRef(to_erase.front()->get()); + to_erase.pop_front(); + } //print_line("success"); return ret; @@ -599,7 +658,7 @@ static jmethodID _showKeyboard=0; static jmethodID _hideKeyboard=0; static jmethodID _setScreenOrientation=0; static jmethodID _getUniqueID=0; - +static jmethodID _getSystemDir=0; static jmethodID _playVideo=0; static jmethodID _isVideoPlaying=0; static jmethodID _pauseVideo=0; @@ -659,6 +718,14 @@ static void _set_screen_orient(int p_orient) { env->CallVoidMethod(godot_io, _setScreenOrientation, p_orient ); }; +static String _get_system_dir(int p_dir) { + + JNIEnv *env = ThreadAndroid::get_env(); + jstring s =(jstring)env->CallObjectMethod(godot_io,_getSystemDir,p_dir); + return String(env->GetStringUTFChars( s, NULL )); +}; + + static void _hide_vk() { JNIEnv* env = ThreadAndroid::get_env(); @@ -738,7 +805,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, _showKeyboard = env->GetMethodID(c,"showKeyboard","(Ljava/lang/String;)V"); _hideKeyboard = env->GetMethodID(c,"hideKeyboard","()V"); _setScreenOrientation = env->GetMethodID(c,"setScreenOrientation","(I)V"); - + _getSystemDir = env->GetMethodID(c,"getSystemDir","(I)Ljava/lang/String;"); _playVideo = env->GetMethodID(c,"playVideo","(Ljava/lang/String;)V"); _isVideoPlaying = env->GetMethodID(c,"isVideoPlaying","()Z"); _pauseVideo = env->GetMethodID(c,"pauseVideo","()V"); @@ -781,7 +848,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, __android_log_print(ANDROID_LOG_INFO,"godot","CMDLINE LEN %i - APK EXPANSION %I\n",cmdlen,int(use_apk_expansion)); - os_android = new OS_Android(_gfx_init_func,env,_open_uri,_get_data_dir,_get_locale, _get_model,_show_vk, _hide_vk,_set_screen_orient,_get_unique_id, _play_video, _is_video_playing, _pause_video, _stop_video,use_apk_expansion); + os_android = new OS_Android(_gfx_init_func,env,_open_uri,_get_data_dir,_get_locale, _get_model,_show_vk, _hide_vk,_set_screen_orient,_get_unique_id, _get_system_dir, _play_video,_is_video_playing, _pause_video, _stop_video,use_apk_expansion); os_android->set_need_reload_hooks(p_need_reload_hook); char wd[500]; @@ -813,10 +880,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env, String vd = Globals::get_singleton()->get("display/driver"); - if (vd.to_upper()=="GLES1") - env->CallVoidMethod(_godot_instance, _on_video_init, (jboolean)false); - else - env->CallVoidMethod(_godot_instance, _on_video_init, (jboolean)true); + env->CallVoidMethod(_godot_instance, _on_video_init, (jboolean)true); __android_log_print(ANDROID_LOG_INFO,"godot","**START"); @@ -866,6 +930,7 @@ static void _initialize_java_modules() { String modules = Globals::get_singleton()->get("android/modules"); Vector<String> mods = modules.split(",",false); + print_line("ANDROID MODULES : " + modules); __android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size()); if (mods.size()) { @@ -1565,6 +1630,8 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env, memnew_placement(&vlist[i], Variant); vlist[i] = v; vptr[i] = &vlist[i]; + env->DeleteLocalRef(obj); + }; Variant::CallError err; @@ -1582,13 +1649,15 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env int count = env->GetArrayLength(params); Variant args[VARIANT_ARG_MAX]; -// print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count)); + //print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count)); for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) { jobject obj = env->GetObjectArrayElement(params, i); if (obj) args[i] = _jobject_to_variant(env, obj); + env->DeleteLocalRef(obj); + // print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type())); }; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 5fad4386fa..f00e9c2d77 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "os_android.h" #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles1/rasterizer_gles1.h" + #include "core/io/file_access_buffered_fa.h" #include "drivers/unix/file_access_unix.h" #include "drivers/unix/dir_access_unix.h" @@ -49,11 +49,11 @@ int OS_Android::get_video_driver_count() const { - return 2; + return 1; } const char * OS_Android::get_video_driver_name(int p_driver) const { - return p_driver==0?"GLES2":"GLES1"; + return "GLES2"; } OS::VideoMode OS_Android::get_default_video_mode() const { @@ -123,13 +123,13 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_ AudioDriverManagerSW::add_driver(&audio_driver_android); - if (use_gl2) { + if (true) { RasterizerGLES2 *rasterizer_gles22=memnew( RasterizerGLES2(false,use_reload_hooks,false,use_reload_hooks ) ); if (gl_extensions) rasterizer_gles22->set_extensions(gl_extensions); rasterizer = rasterizer_gles22; } else { - rasterizer = memnew( RasterizerGLES1(use_reload_hooks, use_reload_hooks) ); + //rasterizer = memnew( RasterizerGLES1(use_reload_hooks, use_reload_hooks) ); } @@ -151,7 +151,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_ sample_manager = memnew( SampleManagerMallocSW ); audio_server = memnew( AudioServerSW(sample_manager) ); - audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,false); + audio_server->set_mixer_params(AudioMixerSW::INTERPOLATION_LINEAR,true); audio_server->init(); spatial_sound_server = memnew( SpatialSoundServerSW ); @@ -291,6 +291,11 @@ void OS_Android::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) p_list->push_back(default_videomode); } +Size2 OS_Android::get_window_size() const { + + return Vector2(default_videomode.width,default_videomode.height); +} + String OS_Android::get_name() { return "Android"; @@ -699,12 +704,19 @@ void OS_Android::native_video_pause() { video_pause_func(); } +String OS_Android::get_system_dir(SystemDir p_dir) const { + + if (get_system_dir_func) + return get_system_dir_func(p_dir); + return String("."); +} + void OS_Android::native_video_stop() { if (video_stop_func) video_stop_func(); } -OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion) { +OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion) { use_apk_expansion=p_use_apk_expansion; @@ -726,6 +738,7 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFu get_locale_func=p_get_locale_func; get_model_func=p_get_model_func; get_unique_id_func=p_get_unique_id; + get_system_dir_func=p_get_sdir_func; video_play_func = p_video_play_func; video_is_playing_func = p_video_is_playing_func; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index bc52a43002..bea5371bbc 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -63,6 +63,7 @@ typedef String (*GetUniqueIDFunc)(); typedef void (*ShowVirtualKeyboardFunc)(const String&); typedef void (*HideVirtualKeyboardFunc)(); typedef void (*SetScreenOrientationFunc)(int); +typedef String (*GetSystemDirFunc)(int); typedef void (*VideoPlayFunc)(const String&); typedef bool (*VideoIsPlayingFunc)(); @@ -98,6 +99,7 @@ private: SpatialSound2DServerSW *spatial_sound_2d_server; PhysicsServer *physics_server; Physics2DServer *physics_2d_server; + #if 0 AudioDriverAndroid audio_driver_android; #else @@ -118,6 +120,7 @@ private: HideVirtualKeyboardFunc hide_virtual_keyboard_func; SetScreenOrientationFunc set_screen_orientation_func; GetUniqueIDFunc get_unique_id_func; + GetSystemDirFunc get_system_dir_func; VideoPlayFunc video_play_func; VideoIsPlayingFunc video_is_playing_func; @@ -167,6 +170,8 @@ public: virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const; + virtual Size2 get_window_size() const; + virtual String get_name(); virtual MainLoop *get_main_loop() const; @@ -203,6 +208,8 @@ public: virtual String get_unique_ID() const; + virtual String get_system_dir(SystemDir p_dir) const; + void process_accelerometer(const Vector3& p_accelerometer); void process_touch(int p_what,int p_pointer, const Vector<TouchPos>& p_points); @@ -210,11 +217,11 @@ public: void init_video_mode(int p_video_width,int p_video_height); virtual Error native_video_play(String p_path, float p_volume); - virtual bool native_video_is_playing(); - virtual void native_video_pause(); - virtual void native_video_stop(); + virtual bool native_video_is_playing(); + virtual void native_video_pause(); + virtual void native_video_stop(); - OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion); + OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func,bool p_use_apk_expansion); ~OS_Android(); }; diff --git a/platform/bb10/SCsub b/platform/bb10/SCsub index 2e8ef47005..24f2b5d242 100644 --- a/platform/bb10/SCsub +++ b/platform/bb10/SCsub @@ -18,13 +18,5 @@ if env['bb10_lgles_override'] == "yes": prog = None -if env["target"]=="release": - prog = env_bps.Program('#platform/bb10/godot_bb10_opt', bb10_lib) -else: - prog = env_bps.Program('#platform/bb10/godot_bb10', bb10_lib) - -import os -fname = os.path.basename(str(prog[0])) - -env.Command('#bin/'+fname, prog, Copy('bin/'+fname, prog[0])) +prog = env_bps.Program('#bin/godot', bb10_lib) diff --git a/platform/bb10/bar/bar-descriptor.xml b/platform/bb10/bar/bar-descriptor.xml index df5d34e077..0ba70b7180 100644 --- a/platform/bb10/bar/bar-descriptor.xml +++ b/platform/bb10/bar/bar-descriptor.xml @@ -1,65 +1,53 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> +<?xml version='1.0' encoding='utf-8' standalone='no'?> <qnx xmlns="http://www.qnx.com/schemas/application/1.0"> - -<!-- BlackBerry® 10 application descriptor file. + <!-- BlackBerry® 10 application descriptor file. Specifies parameters for identifying, installing, and launching native applications on BlackBerry® 10 OS. --> - <!-- A universally unique application identifier. Must be unique across all BlackBerry applications. Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. --> <id>com.godot.game</id> - <!-- The name that is displayed in the BlackBerry application installer. May have multiple values for each language. See samples or xsd schema file. Optional. --> <name>Godot Game</name> - <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade. Values can also be 1-part or 2-part. It is not necessary to have a 3-part value. An updated version of application must have a versionNumber value higher than the previous version. Required. --> <versionNumber>0.0.1</versionNumber> - <!-- Fourth digit segment of the package version. First three segments are taken from the <versionNumber> element. Must be an integer from 0 to 2^16-1 --> <buildId>0</buildId> - <!-- Description, displayed in the BlackBerry application installer. May have multiple values for each language. See samples or xsd schema file. Optional. --> <description>Game made with Godot Engine</description> - <!-- Name of author which is used for signing. Must match the developer name of your development certificate. --> <author>You Name or Company</author> <authorId>authorIDherePlease</authorId> - <!-- Unique author ID assigned by signing authority. Required if using debug tokens. --> <!-- <authorId>ABC1234YjsnUk235h</authorId> --> - <initialWindow> <aspectRatio>landscape</aspectRatio> <autoOrients>false</autoOrients> <systemChrome>none</systemChrome> <transparent>false</transparent> </initialWindow> - <!-- The category where the application appears. Either core.games or core.media. --> <category>core.games</category> <permission>read_device_identifying_information</permission> <permission>access_internet</permission> - <asset path="assets">assets</asset> + <asset path="data.pck">data.pck</asset> <configuration name="Device-Debug"> - <platformArchitecture>armle-v7</platformArchitecture> - <asset path="godot_bb10.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10.qnx.armle</asset> + <platformArchitecture>armle-v7</platformArchitecture> + <asset type="Qnx/Elf" path="godot.bb10.debug.qnx.armle" entry="true">godot.bb10.debug.qnx.armle</asset> </configuration> <configuration name="Device-Release"> - <platformArchitecture>armle-v7</platformArchitecture> - <asset path="godot_bb10_opt.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10_opt.qnx.armle</asset> + <platformArchitecture>armle-v7</platformArchitecture> + <asset type="Qnx/Elf" path="godot.bb10.opt.qnx.armle" entry="true">godot.bb10.opt.qnx.armle</asset> </configuration> <!-- The icon for the application. --> <icon> - <image>icon.png</image> + <image>icon.png</image> </icon> - <!-- Ensure that shared libraries in the package are found at run-time. --> - <env var="LD_LIBRARY_PATH" value="app/native/lib:/usr/lib/qt4/lib"/> - + <env value="app/native/lib:/usr/lib/qt4/lib" var="LD_LIBRARY_PATH"/> </qnx> diff --git a/platform/bb10/detect.py b/platform/bb10/detect.py index 3ddb7a4450..f134a9df19 100644 --- a/platform/bb10/detect.py +++ b/platform/bb10/detect.py @@ -81,8 +81,6 @@ def configure(env): if (env["target"]=="release"): env.Append(CCFLAGS=['-O3','-DRELEASE_BUILD']) - env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX'] - env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX'] elif (env["target"]=="debug"): diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp index d40cb82cdf..7862ecd493 100644 --- a/platform/bb10/export/export.cpp +++ b/platform/bb10/export/export.cpp @@ -321,12 +321,29 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu //BE SUPER CAREFUL WITH THIS PLEASE!!! //BLACKBERRY THIS IS YOUR FAULT FOR NOT MAKING A BETTER WAY!! - if (bar_dir.ends_with("bb10_export")) { - Error err = da->erase_contents_recursive(); - if (err!=OK) { + bool berr = bar_dir.ends_with("bb10_export"); + if (berr) { + if (da->list_dir_begin()) { EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir); - ERR_FAIL_COND_V(err!=OK,err); - } + ERR_FAIL_COND_V(berr,FAILED); + }; + + String f = da->get_next(); + while (f != "") { + + if (f == "." || f == "..") { + f = da->get_next(); + continue; + }; + Error err = da->remove(bar_dir + "/" + f); + if (err != OK) { + EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir); + ERR_FAIL_COND_V(err!=OK,err); + }; + f = da->get_next(); + }; + + da->list_dir_end(); } else { print_line("ARE YOU CRAZY??? THIS IS A SERIOUS BUG HERE!!!"); @@ -405,52 +422,23 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu ret = unzGoToNextFile(pkg); } - ep.step("Finding Files..",1); - - Vector<StringName> files=get_dependencies(false); - ep.step("Adding Files..",2); - da->change_dir(bar_dir); - da->make_dir("assets"); - Error err = da->change_dir("assets"); - ERR_FAIL_COND_V(err,err); - - String asset_dir=da->get_current_dir(); - if (!asset_dir.ends_with("/")) - asset_dir+="/"; - - for(int i=0;i<files.size();i++) { - - String fname=files[i]; - Vector<uint8_t> data = get_exported_file(fname); - /* - FileAccess *f=FileAccess::open(files[i],FileAccess::READ); - if (!f) { - EditorNode::add_io_error("Couldn't read: "+String(files[i])); - } - ERR_CONTINUE(!f); - data.resize(f->get_len()); - f->get_buffer(data.ptr(),data.size()); -*/ - String dst_path=fname; - dst_path=dst_path.replace_first("res://",asset_dir); - - da->make_dir_recursive(dst_path.get_base_dir()); - - ep.step("Adding File: "+String(files[i]).get_file(),3+i*100/files.size()); - - FileAccessRef fr = FileAccess::open(dst_path,FileAccess::WRITE); - fr->store_buffer(data.ptr(),data.size()); + FileAccess* dst = FileAccess::open(bar_dir+"/data.pck", FileAccess::WRITE); + if (!dst) { + EditorNode::add_io_error("Can't copy executable file to:\n "+p_path); + return ERR_FILE_CANT_WRITE; } - + save_pack(dst, false, 1024); + dst->close(); + memdelete(dst); ep.step("Creating BAR Package..",104); String bb_packager=EditorSettings::get_singleton()->get("blackberry/host_tools"); bb_packager=bb_packager.plus_file("blackberry-nativepackager"); if (OS::get_singleton()->get_name()=="Windows") - bb_packager+=".exe"; + bb_packager+=".bat"; if (!FileAccess::exists(bb_packager)) { @@ -482,7 +470,7 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu int ec; - err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec); + Error err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec); if (err!=OK) return err; @@ -493,7 +481,6 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu } - bool EditorExportPlatformBB10::poll_devices() { bool dc=devices_changed; @@ -537,7 +524,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) { bb_deploy=bb_deploy.plus_file("blackberry-deploy"); bool windows = OS::get_singleton()->get_name()=="Windows"; if (windows) - bb_deploy+=".exe"; + bb_deploy+=".bat"; if (!FileAccess::exists(bb_deploy)) { OS::get_singleton()->delay_usec(3000000); @@ -639,7 +626,7 @@ Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) { String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools"); bb_deploy=bb_deploy.plus_file("blackberry-deploy"); if (OS::get_singleton()->get_name()=="Windows") - bb_deploy+=".exe"; + bb_deploy+=".bat"; if (!FileAccess::exists(bb_deploy)) { EditorNode::add_io_error("Blackberry Deploy not found:\n"+bb_deploy); diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp index ff43a68b1d..d89033b1df 100644 --- a/platform/bb10/os_bb10.cpp +++ b/platform/bb10/os_bb10.cpp @@ -619,7 +619,7 @@ OSBB10::OSBB10() { printf("godot bb10!\n"); getcwd(launch_dir, sizeof(launch_dir)); printf("launch dir %s\n", launch_dir); - chdir("app/native/assets"); + chdir("app/native"); launch_dir_ptr = launch_dir; } diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 9fc90bc84e..d495e3b5fc 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -25,8 +25,6 @@ env_ios = env.Clone(); if env['ios_gles22_override'] == "yes": env_ios.Append(CPPFLAGS=['-DGLES2_OVERRIDE']) -if env['ios_GLES1_override'] == "yes": - env_ios.Append(CPPFLAGS=['-DGLES1_OVERRIDE']) if env['ios_appirater'] == "yes": env_ios.Append(CPPFLAGS=['-DAPPIRATER_ENABLED']) diff --git a/platform/iphone/app_delegate.h b/platform/iphone/app_delegate.h index db641b1f78..9437e04738 100644 --- a/platform/iphone/app_delegate.h +++ b/platform/iphone/app_delegate.h @@ -31,12 +31,14 @@ #import "view_controller.h" @interface AppDelegate : NSObject <UIApplicationDelegate, UIAccelerometerDelegate, GLViewDelegate> { - UIWindow *window; + //@property (strong, nonatomic) UIWindow *window; ViewController* view_controller; UIAccelerationValue accel[3]; UIAccelerationValue last_accel[3]; }; +@property (strong, nonatomic) UIWindow *window; + + (ViewController*)getViewController; @end diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index 76c2d06080..fe11b672ac 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -65,6 +65,8 @@ Error _shell_open(String p_uri) { @implementation AppDelegate +@synthesize window; + extern int gargc; extern char** gargv; extern int iphone_main(int, int, int, char**); @@ -82,13 +84,11 @@ static int frame_count = 0; switch (frame_count) { case 0: { - - int backingWidth; - int backingHeight; - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); - - iphone_main(backingWidth, backingHeight, gargc, gargv); + int backingWidth; + int backingHeight; + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); + OS::VideoMode vm; vm.fullscreen = true; @@ -127,7 +127,7 @@ static int frame_count = 0; OSIPhone::get_singleton()->set_unique_ID(String::utf8([uuid UTF8String])); - }; // break; + }; break; /* case 1: { ++frame_count; @@ -154,7 +154,7 @@ static int frame_count = 0; [Appirater appLaunched:YES app_id:aid]; #endif - }; // break; fallthrough + }; break; // no fallthrough default: { @@ -196,6 +196,13 @@ static int frame_count = 0; //glView.autoresizesSubviews = YES; //[glView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth]; + int backingWidth; + int backingHeight; + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); + + iphone_main(backingWidth, backingHeight, gargc, gargv); + view_controller = [[ViewController alloc] init]; view_controller.view = glView; window.rootViewController = view_controller; @@ -260,6 +267,9 @@ static int frame_count = 0; if (OS::get_singleton()->get_main_loop()) OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); [view_controller.view stopAnimation]; + if (OS::get_singleton()->native_video_is_playing()) { + OSIPhone::get_singleton()->native_video_focus_out(); + }; } - (void)applicationWillEnterForeground:(UIApplication *)application @@ -286,6 +296,9 @@ static int frame_count = 0; if (OS::get_singleton()->get_main_loop()) OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); [view_controller.view startAnimation]; // FIXME: resume seems to be recommended elsewhere + if (OSIPhone::get_singleton()->native_video_is_playing()) { + OSIPhone::get_singleton()->native_video_unpause(); + }; } - (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration { diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index c25742a854..fb57876a83 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -21,12 +21,11 @@ def get_opts(): return [ ('IPHONEPLATFORM', 'name of the iphone platform', 'iPhoneOS'), ('IPHONEPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'), - ('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS7.0'), + ('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS'), ('IPHONESDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/${IOS_SDK_VERSION}.sdk/'), ('game_center', 'Support for game center', 'yes'), ('store_kit', 'Support for in-app store', 'yes'), ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'), - ('ios_GLES1_override', 'Force legacy GLES (1.1) on iOS', 'no'), ('ios_appirater', 'Enable Appirater', 'no'), ('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'), ] @@ -54,20 +53,18 @@ def configure(env): env['AR'] = 'ar' import string - #env['CCFLAGS'] = string.split('-arch armv7 -Wall -fno-strict-aliasing -fno-common -D__IPHONE_OS_VERSION_MIN_REQUIRED=20000 -isysroot $IPHONESDK -fvisibility=hidden -mmacosx-version-min=10.5 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\" -DNO_THUMB') - env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -isysroot $IPHONESDK') - - -#/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang++ fno-objc-arc -arch armv7 -fmessage-length=0 -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -v -Os -ffast-math -DSTOREKIT_ENABLED -DIPHONE_ENABLED -DUNIX_ENABLED -DGLES2_ENABLED -DNO_THREADS -DMODULE_GRIDMAP_ENABLED -DMUSEPACK_ENABLED -DOLD_SCENE_FORMAT_ENABLED -DSQUIRREL_ENABLED -DVORBIS_ENABLED -DTHEORA_ENABLED -DPNG_ENABLED -DDDS_ENABLED -DPVR_ENABLED -DJPG_ENABLED -DSPEEX_ENABLED -DTOOLS_ENABLED -DGDSCRIPT_ENABLED -DMINIZIP_ENABLED -DXML_ENABLED -Icore -Icore/math -Itools -Idrivers -I. -Iplatform/iphone -Iplatform/iphone/include -Iplatform/iphone/scoreloop/SDKs -I/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework/Headers -Iscript/squirrel/src -Iscript/vorbis script/gdscript/gd_script.cpp -#/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang -x objective-c -arch armv7 -fmessage-length=0 -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -std=gnu99 -fobjc-arc -Wno-trigraphs -fpascal-strings -Os -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -iquote /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-generated-files.hmap -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-own-target-headers.hmap -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-all-target-headers.hmap -iquote /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-project-headers.hmap -I/Users/red/test2/build/Release-iphoneos/include -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/DerivedSources/armv7 -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/DerivedSources -F/Users/red/test2/build/Release-iphoneos -DNS_BLOCK_ASSERTIONS=1 -include /var/folders/LX/LXYXHTeSHSqbkhuPJRIsuE+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/test2-Prefix-dvdhnltoisfpmyalexovdrmfyeky/test2-Prefix.pch -MMD -MT dependencies -MF /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/Objects-normal/armv7/main.d -c /Users/red/test2/test2/main.m -o /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/Objects-normal/armv7/main.o - - - - + if (env["bits"]=="64"): + #env['CCFLAGS'] = string.split('-arch arm64 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -miphoneos-version-min=5.1.1 -Wmost -Wno-four-char-constants -Wno-unknown-pragmas -Wno-invalid-offsetof -ffast-math -m64 -DDEBUG -D_DEBUG -MMD -MT dependencies -isysroot $IPHONESDK') + env['CCFLAGS'] = string.split('-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -MMD -MT dependencies -miphoneos-version-min=5.1.1 -isysroot $IPHONESDK') + env.Append(CPPFLAGS=['-DNEED_LONG_INT']) + env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON']) + else: + env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -isysroot $IPHONESDK') - env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3', + if (env["bits"]=="64"): + env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1', '-isysroot', '$IPHONESDK', - #'-mmacosx-version-min=10.5', + #'-stdlib=libc++', '-framework', 'Foundation', '-framework', 'UIKit', '-framework', 'CoreGraphics', @@ -79,6 +76,25 @@ def configure(env): '-framework', 'Security', #'-framework', 'AdSupport', '-framework', 'MediaPlayer', + '-framework', 'AVFoundation', + '-framework', 'CoreMedia', + ]) + else: + env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3', + '-isysroot', '$IPHONESDK', + '-framework', 'Foundation', + '-framework', 'UIKit', + '-framework', 'CoreGraphics', + '-framework', 'OpenGLES', + '-framework', 'QuartzCore', + '-framework', 'CoreAudio', + '-framework', 'AudioToolbox', + '-framework', 'SystemConfiguration', + '-framework', 'Security', + #'-framework', 'AdSupport', + '-framework', 'MediaPlayer', + '-framework', 'AVFoundation', + '-framework', 'CoreMedia', ]) if env['game_center'] == 'yes': @@ -93,8 +109,8 @@ def configure(env): if (env["target"]=="release"): - env.Append(CCFLAGS=['-Os', '-ffast-math', '-DNS_BLOCK_ASSERTIONS=1','-Wall']) - env.Append(LINKFLAGS=['-Os', '-ffast-math']) + env.Append(CCFLAGS=['-O3', '-ffast-math', '-DNS_BLOCK_ASSERTIONS=1','-Wall']) + env.Append(LINKFLAGS=['-O3', '-ffast-math']) elif env["target"] == "release_debug": env.Append(CCFLAGS=['-Os', '-ffast-math', '-DNS_BLOCK_ASSERTIONS=1','-Wall','-DDEBUG_ENABLED']) @@ -113,7 +129,7 @@ def configure(env): env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate' - env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DGLES1_ENABLED', '-DMPC_FIXED_POINT']) + env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DMPC_FIXED_POINT']) if env['ios_exceptions'] == 'yes': env.Append(CPPFLAGS=['-fexceptions']) else: @@ -126,4 +142,4 @@ def configure(env): env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) -# /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c-header -arch armv7s -fmessage-length=0 -std=gnu99 -fobjc-arc -Wno-trigraphs -fpascal-strings -Os -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-implicit-atomic-properties -Wno-receiver-is-weak -Wduplicate-method-match -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-shorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk -Wprotocol -Wdeprecated-declarations -g -fvisibility=hidden -Wno-sign-conversion "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -iquote /Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-generated-files.hmap -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-own-target-headers.hmap -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-all-target-headers.hmap -iquote /Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-project-headers.hmap -I/Users/lucasgondolo/test/build/Release-iphoneos/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/DerivedSources/armv7s -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/DerivedSources -F/Users/lucasgondolo/test/build/Release-iphoneos -DNS_BLOCK_ASSERTIONS=1 --serialize-diagnostics /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.dia -c /Users/lucasgondolo/test/test/test-Prefix.pch -o /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.pth -MMD -MT dependencies -MF /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.d + diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h index 3e6181ab90..04334991fd 100755 --- a/platform/iphone/gl_view.h +++ b/platform/iphone/gl_view.h @@ -32,6 +32,9 @@ #import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/glext.h> #import <MediaPlayer/MediaPlayer.h> +#import <AVFoundation/AVFoundation.h> + +#define USE_CADISPLAYLINK 1 //iOS version 3.1+ is required @protocol GLViewDelegate; @@ -50,8 +53,14 @@ // OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) GLuint depthRenderbuffer; +#if USE_CADISPLAYLINK + // CADisplayLink available on 3.1+ synchronizes the animation timer & drawing with the refresh rate of the display, only supports animation intervals of 1/60 1/30 & 1/15 + CADisplayLink *displayLink; +#else // An animation timer that, when animation is started, will periodically call -drawView at the given rate. NSTimer *animationTimer; +#endif + NSTimeInterval animationInterval; // Delegate to do our drawing, called by -drawView, which can be called manually or via the animation timer. @@ -66,6 +75,13 @@ @property(nonatomic, assign) id<GLViewDelegate> delegate; +// AVPlayer-related properties +@property(strong, nonatomic) AVAsset *avAsset; +@property(strong, nonatomic) AVPlayerItem *avPlayerItem; +@property(strong, nonatomic) AVPlayer *avPlayer; +@property(strong, nonatomic) AVPlayerLayer *avPlayerLayer; + +// Old videoplayer properties @property(strong, nonatomic) MPMoviePlayerController *moviePlayerController; @property(strong, nonatomic) UIWindow *backgroundWindow; @@ -85,6 +101,8 @@ - (BOOL)createFramebuffer; - (void)destroyFramebuffer; +- (void)audioRouteChangeListenerCallback:(NSNotification*)notification; + @property NSTimeInterval animationInterval; @end diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm index 06b679c305..3d6c48ffaf 100755 --- a/platform/iphone/gl_view.mm +++ b/platform/iphone/gl_view.mm @@ -52,6 +52,7 @@ static GLView* _instance = NULL; static bool video_found_error = false; static bool video_playing = false; static float video_previous_volume = 0.0f; +static CMTime video_current_time; void _show_keyboard(String p_existing) { keyboard_text = p_existing; @@ -65,6 +66,7 @@ void _hide_keyboard() { keyboard_text = ""; }; +/* bool _play_video(String p_path, float p_volume) { float player_volume = p_volume * AudioServer::get_singleton()->get_singleton()->get_stream_global_volume_scale(); @@ -96,24 +98,116 @@ bool _play_video(String p_path, float p_volume) { return true; } +*/ + +bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { + p_path = Globals::get_singleton()->globalize_path(p_path); + + NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease]; + //NSURL *file_url = [NSURL fileURLWithPath:file_path]; + + _instance.avAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:file_path]]; + _instance.avPlayerItem =[[AVPlayerItem alloc]initWithAsset:_instance.avAsset]; + [_instance.avPlayerItem addObserver:_instance forKeyPath:@"status" options:0 context:nil]; + + _instance.avPlayer = [[AVPlayer alloc]initWithPlayerItem:_instance.avPlayerItem]; + _instance.avPlayerLayer =[AVPlayerLayer playerLayerWithPlayer:_instance.avPlayer]; + + [_instance.avPlayer addObserver:_instance forKeyPath:@"status" options:0 context:nil]; + [[NSNotificationCenter defaultCenter] addObserver:_instance + selector:@selector(playerItemDidReachEnd:) + name:AVPlayerItemDidPlayToEndTimeNotification + object:[_instance.avPlayer currentItem]]; + + [_instance.avPlayer addObserver:_instance forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0]; + + [_instance.avPlayerLayer setFrame:_instance.bounds]; + [_instance.layer addSublayer:_instance.avPlayerLayer]; + [_instance.avPlayer play]; + + AVMediaSelectionGroup *audioGroup = [_instance.avAsset mediaSelectionGroupForMediaCharacteristic: AVMediaCharacteristicAudible]; + + NSMutableArray *allAudioParams = [NSMutableArray array]; + for (id track in audioGroup.options) + { + NSString* language = [[track locale] localeIdentifier]; + NSLog(@"subtitle lang: %@", language); + + if ([language isEqualToString:[NSString stringWithUTF8String:p_audio_track.utf8()]]) + { + AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters]; + [audioInputParams setVolume:p_volume atTime:kCMTimeZero]; + [audioInputParams setTrackID:[track trackID]]; + [allAudioParams addObject:audioInputParams]; + + AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; + [audioMix setInputParameters:allAudioParams]; + + [_instance.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup: audioGroup]; + [_instance.avPlayer.currentItem setAudioMix:audioMix]; + + break; + } + } + + AVMediaSelectionGroup *subtitlesGroup = [_instance.avAsset mediaSelectionGroupForMediaCharacteristic: AVMediaCharacteristicLegible]; + NSArray *useableTracks = [AVMediaSelectionGroup mediaSelectionOptionsFromArray:subtitlesGroup.options withoutMediaCharacteristics:[NSArray arrayWithObject:AVMediaCharacteristicContainsOnlyForcedSubtitles]]; + + for (id track in useableTracks) + { + NSString* language = [[track locale] localeIdentifier]; + NSLog(@"subtitle lang: %@", language); + + if ([language isEqualToString:[NSString stringWithUTF8String:p_subtitle_track.utf8()]]) + { + [_instance.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup: subtitlesGroup]; + break; + } + } + + video_playing = true; + + return true; +} bool _is_video_playing() { //NSInteger playback_state = _instance.moviePlayerController.playbackState; - return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying; + //return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying; //if (video_found_error) // return false; //return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying); + + return video_playing || (_instance.avPlayer.rate > 0 && !_instance.avPlayer.error); } void _pause_video() { - [_instance.moviePlayerController pause]; + //[_instance.moviePlayerController pause]; + video_current_time = _instance.avPlayer.currentTime; + [_instance.avPlayer pause]; video_playing = false; } +void _focus_out_video() { + printf("focus out pausing video\n"); + [_instance.avPlayer pause]; +}; + +void _unpause_video() { + + [_instance.avPlayer play]; + video_playing = true; + + //video_current_time = kCMTimeZero; +}; + void _stop_video() { - [_instance.moviePlayerController stop]; - [_instance.moviePlayerController.view removeFromSuperview]; + //[_instance.moviePlayerController stop]; + //[_instance.moviePlayerController.view removeFromSuperview]; //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume]; + + [_instance.avPlayer pause]; + [_instance.avPlayerLayer removeFromSuperlayer]; + _instance.avPlayer = nil; video_playing = false; } @@ -215,11 +309,7 @@ static void clear_touches() { nil]; // Create our EAGLContext, and if successful make it current and create our framebuffer. -#ifdef GLES1_OVERRIDE - context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; -#else context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; -#endif if(!context || ![EAGLContext setCurrentContext:context] || ![self createFramebuffer]) { @@ -325,7 +415,24 @@ static void clear_touches() { return; active = TRUE; printf("start animation!\n"); +#if USE_CADISPLAYLINK + // Approximate frame rate + // assumes device refreshes at 60 fps + int frameInterval = (int) floor(animationInterval * 60.0f); + + displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView)]; + [displayLink setFrameInterval:frameInterval]; + + // Setup DisplayLink in main thread + [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; +#else animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES]; +#endif + + if (video_playing) + { + _unpause_video(); + } } - (void)stopAnimation @@ -334,16 +441,30 @@ static void clear_touches() { return; active = FALSE; printf("******** stop animation!\n"); +#if USE_CADISPLAYLINK + [displayLink invalidate]; + displayLink = nil; +#else [animationTimer invalidate]; animationTimer = nil; +#endif clear_touches(); + + if (video_playing) + { + // save position + } } - (void)setAnimationInterval:(NSTimeInterval)interval { animationInterval = interval; +#if USE_CADISPLAYLINK + if(displayLink) +#else if(animationTimer) +#endif { [self stopAnimation]; [self startAnimation]; @@ -353,6 +474,17 @@ static void clear_touches() { // Updates the OpenGL view when the timer fires - (void)drawView { +#if USE_CADISPLAYLINK + // Pause the CADisplayLink to avoid recursion + [displayLink setPaused: YES]; + + // Process all input events + while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource); + + // We are good to go, resume the CADisplayLink + [displayLink setPaused: NO]; +#endif + if (!active) { printf("draw view not active!\n"); return; @@ -375,9 +507,11 @@ static void clear_touches() { glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES]; +#ifdef DEBUG_ENABLED GLenum err = glGetError(); if(err) NSLog(@"%x error", err); +#endif } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -478,6 +612,39 @@ static void clear_touches() { printf("inserting text with character %i\n", character[0]); }; +- (void)audioRouteChangeListenerCallback:(NSNotification*)notification +{ + printf("*********** route changed!%i\n"); + NSDictionary *interuptionDict = notification.userInfo; + + NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; + + switch (routeChangeReason) { + + case AVAudioSessionRouteChangeReasonNewDeviceAvailable: + NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable"); + NSLog(@"Headphone/Line plugged in"); + break; + + case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: + NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable"); + NSLog(@"Headphone/Line was pulled. Resuming video play...."); + if (_is_video_playing) { + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_instance.avPlayer play]; // NOTE: change this line according your current player implementation + NSLog(@"resumed play"); + }); + }; + break; + + case AVAudioSessionRouteChangeReasonCategoryChange: + // called at start - also when other audio wants to play + NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange"); + break; + } +} + // When created via code however, we get initWithFrame -(id)initWithFrame:(CGRect)frame @@ -493,6 +660,11 @@ static void clear_touches() { init_touches(); self. multipleTouchEnabled = YES; + printf("******** adding observer for sound routing changes\n"); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) + name:AVAudioSessionRouteChangeNotification + object:nil]; + //self.autoresizesSubviews = YES; //[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth]; @@ -523,6 +695,44 @@ static void clear_touches() { [super dealloc]; } +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object + change:(NSDictionary *)change context:(void *)context { + + if (object == _instance.avPlayerItem && [keyPath isEqualToString:@"status"]) { + if (_instance.avPlayerItem.status == AVPlayerStatusFailed || _instance.avPlayer.status == AVPlayerStatusFailed) { + _stop_video(); + video_found_error = true; + } + + if(_instance.avPlayer.status == AVPlayerStatusReadyToPlay && + _instance.avPlayerItem.status == AVPlayerItemStatusReadyToPlay && + CMTIME_COMPARE_INLINE(video_current_time, ==, kCMTimeZero)) { + + //NSLog(@"time: %@", video_current_time); + + [_instance.avPlayer seekToTime:video_current_time]; + video_current_time = kCMTimeZero; + } + } + + if (object == _instance.avPlayer && [keyPath isEqualToString:@"rate"]) { + NSLog(@"Player playback rate changed: %.5f", _instance.avPlayer.rate); + if (_is_video_playing() && _instance.avPlayer.rate == 0.0 && !_instance.avPlayer.error) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_instance.avPlayer play]; // NOTE: change this line according your current player implementation + NSLog(@"resumed play"); + }); + + NSLog(@" . . . PAUSED (or just started)"); + } + } +} + +- (void)playerItemDidReachEnd:(NSNotification *)notification { + _stop_video(); +} + +/* - (void)moviePlayBackDidFinish:(NSNotification*)notification { @@ -557,5 +767,6 @@ static void clear_touches() { //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume]; video_playing = false; } +*/ @end diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 2ef732183b..06b48318ec 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -31,7 +31,7 @@ #include "os_iphone.h" #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles1/rasterizer_gles1.h" + #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" @@ -40,6 +40,7 @@ #include "audio_driver_iphone.h" #include "core/os/dir_access.h" +#include "core/os/file_access.h" #include "core/globals.h" #include "sem_iphone.h" @@ -51,7 +52,7 @@ int OSIPhone::get_video_driver_count() const { const char * OSIPhone::get_video_driver_name(int p_driver) const { - return "openglES"; + return "GLES2"; }; OSIPhone* OSIPhone::get_singleton() { @@ -77,7 +78,7 @@ void OSIPhone::set_data_dir(String p_dir) { DirAccess* da = DirAccess::open(p_dir); data_dir = da->get_current_dir(); - + printf("setting data dir to %ls from %ls\n", data_dir.c_str(), p_dir.c_str()); memdelete(da); }; @@ -105,13 +106,9 @@ void OSIPhone::initialize(const VideoMode& p_desired,int p_video_driver,int p_au supported_orientations |= ((GLOBAL_DEF("video_mode/allow_vertical", false)?1:0) << PortraitDown); supported_orientations |= ((GLOBAL_DEF("video_mode/allow_vertical_flipped", false)?1:0) << PortraitUp); -#ifdef GLES1_OVERRIDE - rasterizer = memnew( RasterizerGLES1 ); -#else rasterizer_gles22 = memnew( RasterizerGLES2(false, false, false) ); rasterizer = rasterizer_gles22; rasterizer_gles22->set_base_framebuffer(gl_view_base_fb); -#endif visual_server = memnew( VisualServerRaster(rasterizer) ); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { @@ -211,14 +208,16 @@ void OSIPhone::key(uint32_t p_key, bool p_pressed) { void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick, bool p_use_as_mouse) { - InputEvent ev; - ev.type = InputEvent::SCREEN_TOUCH; - ev.ID = ++last_event_id; - ev.screen_touch.index=p_idx; - ev.screen_touch.pressed=p_pressed; - ev.screen_touch.x=p_x; - ev.screen_touch.y=p_y; - queue_event(ev); + if (!GLOBAL_DEF("debug/disable_touch", false)) { + InputEvent ev; + ev.type = InputEvent::SCREEN_TOUCH; + ev.ID = ++last_event_id; + ev.screen_touch.index=p_idx; + ev.screen_touch.pressed=p_pressed; + ev.screen_touch.x=p_x; + ev.screen_touch.y=p_y; + queue_event(ev); + }; if (p_use_as_mouse) { @@ -234,6 +233,7 @@ void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_ ev.mouse_button.x = ev.mouse_button.global_x = p_x; ev.mouse_button.y = ev.mouse_button.global_y = p_y; + input->set_mouse_pos(Point2(ev.mouse_motion.x,ev.mouse_motion.y)); ev.mouse_button.button_index = BUTTON_LEFT; ev.mouse_button.doubleclick = p_doubleclick; ev.mouse_button.pressed = p_pressed; @@ -246,15 +246,18 @@ void OSIPhone::mouse_button(int p_idx, int p_x, int p_y, bool p_pressed, bool p_ void OSIPhone::mouse_move(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, bool p_use_as_mouse) { - InputEvent ev; - ev.type=InputEvent::SCREEN_DRAG; - ev.ID = ++last_event_id; - ev.screen_drag.index=p_idx; - ev.screen_drag.x=p_x; - ev.screen_drag.y=p_y; - ev.screen_drag.relative_x = p_x - p_prev_x; - ev.screen_drag.relative_y = p_y - p_prev_y; - queue_event(ev); + if (!GLOBAL_DEF("debug/disable_touch", false)) { + + InputEvent ev; + ev.type=InputEvent::SCREEN_DRAG; + ev.ID = ++last_event_id; + ev.screen_drag.index=p_idx; + ev.screen_drag.x=p_x; + ev.screen_drag.y=p_y; + ev.screen_drag.relative_x = p_x - p_prev_x; + ev.screen_drag.relative_y = p_y - p_prev_y; + queue_event(ev); + }; if (p_use_as_mouse) { InputEvent ev; @@ -471,6 +474,11 @@ String OSIPhone::get_name() { return "iOS"; }; +Size2 OSIPhone::get_window_size() const { + + return Vector2(video_mode.width, video_mode.height); +} + bool OSIPhone::has_touchscreen_ui_hint() const { return true; @@ -485,13 +493,22 @@ String OSIPhone::get_locale() const { return locale_code; } -extern bool _play_video(String p_path, float p_volume); +extern bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); extern bool _is_video_playing(); extern void _pause_video(); +extern void _unpause_video(); extern void _stop_video(); - -Error OSIPhone::native_video_play(String p_path, float p_volume) { - if ( _play_video(p_path, p_volume) ) +extern void _focus_out_video(); + +Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { + FileAccess* f = FileAccess::open(p_path, FileAccess::READ); + bool exists = f && f->is_open(); + printf("file exists for %ls, %i, %p\n", p_path.c_str(), (int)exists, f); + if (f) + memdelete(f); + if (!exists) + return FAILED; + if ( _play_video(p_path, p_volume, p_audio_track, p_subtitle_track) ) return OK; return FAILED; } @@ -505,6 +522,14 @@ void OSIPhone::native_video_pause() { _pause_video(); } +void OSIPhone::native_video_unpause() { + _unpause_video(); +}; + +void OSIPhone::native_video_focus_out() { + _focus_out_video(); +}; + void OSIPhone::native_video_stop() { if (native_video_is_playing()) _stop_video(); diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 14b46816e9..2585a26479 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -167,6 +167,8 @@ public: virtual void hide_virtual_keyboard(); virtual void set_cursor_shape(CursorShape p_shape); + + virtual Size2 get_window_size() const; virtual bool has_touchscreen_ui_hint() const; @@ -184,9 +186,11 @@ public: void set_unique_ID(String p_ID); String get_unique_ID() const; - virtual Error native_video_play(String p_path, float p_volume); + virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); virtual bool native_video_is_playing() const; virtual void native_video_pause(); + virtual void native_video_unpause(); + virtual void native_video_focus_out(); virtual void native_video_stop(); OSIPhone(int width, int height); diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h index df50d30f40..3d6300d8e0 100644 --- a/platform/iphone/platform_config.h +++ b/platform/iphone/platform_config.h @@ -28,5 +28,6 @@ /*************************************************************************/ #include <alloca.h> #define GLES2_INCLUDE_H <ES2/gl.h> -#define GLES1_INCLUDE_H <ES1/gl.h> + +#define PLATFORM_REFCOUNT diff --git a/platform/iphone/platform_refcount.h b/platform/iphone/platform_refcount.h new file mode 100644 index 0000000000..45391e651a --- /dev/null +++ b/platform/iphone/platform_refcount.h @@ -0,0 +1,18 @@ +#include "safe_refcount.h" + +#ifdef IPHONE_ENABLED + +#define REFCOUNT_T int +#define REFCOUNT_GET_T int const volatile& + +#include <libkern/OSAtomic.h> + +inline int atomic_conditional_increment(volatile int* v) { + return (*v==0)? 0 : OSAtomicIncrement32(v); +} + +inline int atomic_decrement(volatile int* v) { + return OSAtomicDecrement32(v); +} + +#endif diff --git a/platform/isim/SCsub b/platform/isim/SCsub index e7de935b2e..2bd65cb49b 100644 --- a/platform/isim/SCsub +++ b/platform/isim/SCsub @@ -25,8 +25,6 @@ env_ios = env.Clone(); if env['ios_gles22_override'] == "yes": env_ios.Append(CPPFLAGS=['-DGLES2_OVERRIDE']) -if env['ios_GLES1_override'] == "yes": - env_ios.Append(CPPFLAGS=['-DGLES1_OVERRIDE']) if env['ios_appirater'] == "yes": env_ios.Append(CPPFLAGS=['-DAPPIRATER_ENABLED']) @@ -34,11 +32,4 @@ if env['ios_appirater'] == "yes": obj = env_ios.Object('#platform/iphone/godot_iphone.cpp') prog = None -if env["target"]=="release": - prog = env_ios.Program('#bin/godot_opt', [obj] + iphone_lib) - #action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM" - #env.AddPostAction(prog, action) -else: - prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) - #action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM" - #env.AddPostAction(prog, action) +prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) diff --git a/platform/isim/detect.py b/platform/isim/detect.py index c89ca81167..bd0fd2fea3 100644 --- a/platform/isim/detect.py +++ b/platform/isim/detect.py @@ -22,7 +22,7 @@ def get_opts(): return [ ('ISIMPLATFORM', 'name of the iphone platform', 'iPhoneSimulator'), ('ISIMPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Platforms/${ISIMPLATFORM}.platform'), - ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}7.0.sdk'), + ('ISIMSDK', 'path to the iphone SDK', '$ISIMPATH/Developer/SDKs/${ISIMPLATFORM}.sdk'), ('game_center', 'Support for game center', 'yes'), ('store_kit', 'Support for in-app store', 'yes'), ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'), @@ -34,9 +34,7 @@ def get_opts(): def get_flags(): return [ - ('lua', 'no'), ('tools', 'yes'), - ('nedmalloc', 'no'), ('webp', 'yes'), ] @@ -46,10 +44,6 @@ def configure(env): env.Append(CPPPATH=['#platform/iphone']) - env['OBJSUFFIX'] = ".isim.o" - env['LIBSUFFIX'] = ".isim.a" - env['PROGSUFFIX'] = ".isim" - env['ENV']['PATH'] = env['ISIMPATH']+"/Developer/usr/bin/:"+env['ENV']['PATH'] env['CC'] = '$ISIMPATH/Developer/usr/bin/gcc' @@ -66,14 +60,18 @@ def configure(env): '-Xlinker', '-objc_abi_version', '-Xlinker', '2', + '-framework', 'AudioToolbox', + '-framework', 'AVFoundation', + '-framework', 'CoreAudio', + '-framework', 'CoreGraphics', + '-framework', 'CoreMedia', '-framework', 'Foundation', + '-framework', 'Security', '-framework', 'UIKit', - '-framework', 'IOKit', - '-framework', 'CoreGraphics', + '-framework', 'MediaPlayer', '-framework', 'OpenGLES', '-framework', 'QuartzCore', - '-framework', 'AudioToolbox', - '-framework', 'MediaPlayer', + '-framework', 'SystemConfiguration', '-F$ISIMSDK', ]) @@ -83,8 +81,6 @@ def configure(env): env.Append(CCFLAGS=['-O3', '-ffast-math']) env.Append(LINKFLAGS=['-O3', '-ffast-math']) - env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX'] - env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX'] elif (env["target"]=="debug"): @@ -99,8 +95,6 @@ def configure(env): env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6' env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate' - env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fno-exceptions']) + env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-fexceptions']) - if env['lua'] == "yes": - env.Append(CCFLAGS=['-DLUA_USE_FLOAT']) diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 845b2e3395..947a637fb9 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -10,9 +10,9 @@ def get_name(): def can_build(): - import os - if (not os.environ.has_key("EMSCRIPTEN_ROOT")): - return False + import os + if (not os.environ.has_key("EMSCRIPTEN_ROOT")): + return False return True def get_opts(): @@ -36,6 +36,7 @@ def get_flags(): ('squish', 'no'), ('speex', 'no'), ('old_scenes', 'no'), + ('etc1', 'no'), # ('default_gui_theme', 'no'), #('builtin_zlib', 'no'), @@ -44,33 +45,36 @@ def get_flags(): def configure(env): - - env.Append(CPPPATH=['#platform/javascript']) - + em_path=os.environ["EMSCRIPTEN_ROOT"] - + env['ENV']['PATH'] = em_path+":"+env['ENV']['PATH'] env['CC'] = em_path+'/emcc' env['CXX'] = em_path+'/emcc' - env['AR'] = em_path+"/emar" - env['RANLIB'] = em_path+"/emranlib" + #env['AR'] = em_path+"/emar" + env['AR'] = em_path+"/emcc" + env['ARFLAGS'] = "-o" + +# env['RANLIB'] = em_path+"/emranlib" + env['RANLIB'] = em_path + "/emcc" + env['OBJSUFFIX'] = '.bc' + env['LIBSUFFIX'] = '.bc' + env['CCCOM'] = "$CC -o $TARGET $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES" + env['CXXCOM'] = "$CC -o $TARGET $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES" # env.Append(LIBS=['c','m','stdc++','log','GLESv1_CM','GLESv2']) # env["LINKFLAGS"]= string.split(" -g --sysroot="+ld_sysroot+" -Wl,--no-undefined -Wl,-z,noexecstack ") if (env["target"]=="release"): - env.Append(CCFLAGS=['-O2']) - elif (env["target"]=="release_debug"): - env.Append(CCFLAGS=['-O2','-DDEBUG_ENABLED']) - elif (env["target"]=="debug"): env.Append(CCFLAGS=['-D_DEBUG', '-Wall', '-O2', '-DDEBUG_ENABLED']) + #env.Append(CCFLAGS=['-D_DEBUG', '-Wall', '-g4', '-DDEBUG_ENABLED']) env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC']) env.Append(CPPFLAGS=["-fno-exceptions",'-DNO_SAFE_CAST','-fno-rtti']) @@ -84,10 +88,11 @@ def configure(env): lzma_binpath = em_path+"/third_party/lzma.js/lzma-native" lzma_decoder = em_path+"/third_party/lzma.js/lzma-decoder.js" lzma_dec = "LZMA.decompress" - env.Append(LINKFLAGS=['--compression',lzma_binpath+","+lzma_decoder+","+lzma_dec]) env.Append(LINKFLAGS=['-s','ASM_JS=1']) env.Append(LINKFLAGS=['-O2']) - - + #env.Append(LINKFLAGS=['-g4']) + + #print "CCCOM is:", env.subst('$CCCOM') + #print "P: ", env['p'], " Platofrm: ", env['platform'] diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 581df84925..4c8d8a4205 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -230,6 +230,12 @@ OS::VideoMode OS_JavaScript::get_video_mode(int p_screen) const { return default_videomode; } + +Size2 OS_JavaScript::get_window_size() const { + + return Vector2(default_videomode.width,default_videomode.height); +} + void OS_JavaScript::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const { p_list->push_back(default_videomode); diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index dfc93d3ff0..2e9c8e14c2 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -127,6 +127,7 @@ public: virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const; + virtual Size2 get_window_size() const; virtual String get_name(); virtual MainLoop *get_main_loop() const; diff --git a/platform/nacl/os_nacl.cpp b/platform/nacl/os_nacl.cpp index d97195c50d..65f66b0354 100644 --- a/platform/nacl/os_nacl.cpp +++ b/platform/nacl/os_nacl.cpp @@ -64,7 +64,7 @@ int OSNacl::get_video_driver_count() const { }; const char * OSNacl::get_video_driver_name(int p_driver) const { - return "gles2"; + return "GLES2"; }; OS::VideoMode OSNacl::get_default_video_mode() const { diff --git a/platform/osx/audio_driver_osx.cpp b/platform/osx/audio_driver_osx.cpp index 8f28e8ff63..638ac7e504 100644 --- a/platform/osx/audio_driver_osx.cpp +++ b/platform/osx/audio_driver_osx.cpp @@ -101,7 +101,16 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon, AudioBuffer *abuf; AudioDriverOSX* ad = (AudioDriverOSX*)inRefCon; - if (!ad->active) { + bool mix = true; + + if (!ad->active) + mix = false; + else if (ad->mutex) { + mix = ad->mutex->try_lock() == OK; + }; + + + if (!mix) { for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) { abuf = &ioData->mBuffers[i]; zeromem(abuf->mData, abuf->mDataByteSize); @@ -120,9 +129,9 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon, while (frames_left) { int frames = MIN(frames_left, ad->buffer_frames); - ad->lock(); + //ad->lock(); ad->audio_server_process(frames, ad->samples_in); - ad->unlock(); + //ad->unlock(); for(int i = 0; i < frames * ad->channels; i++) { @@ -134,6 +143,9 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon, }; }; + if (ad->mutex) + ad->mutex->unlock(); + return 0; }; @@ -149,12 +161,27 @@ AudioDriverSW::OutputFormat AudioDriverOSX::get_output_format() const { return OUTPUT_STEREO; }; -void AudioDriverOSX::lock() {}; -void AudioDriverOSX::unlock() {}; +void AudioDriverOSX::lock() { + if (active && mutex) + mutex->lock(); +}; +void AudioDriverOSX::unlock() { + if (active && mutex) + mutex->unlock(); +}; void AudioDriverOSX::finish() { memdelete_arr(samples_in); }; +AudioDriverOSX::AudioDriverOSX() { + + mutex=Mutex::create();//NULL; +}; + +AudioDriverOSX::~AudioDriverOSX() { + +}; + #endif diff --git a/platform/osx/audio_driver_osx.h b/platform/osx/audio_driver_osx.h index daa388fb86..c0336eb816 100644 --- a/platform/osx/audio_driver_osx.h +++ b/platform/osx/audio_driver_osx.h @@ -39,6 +39,7 @@ class AudioDriverOSX : public AudioDriverSW { AudioComponentInstance audio_unit; bool active; + Mutex *mutex; int channels; int32_t* samples_in; @@ -64,6 +65,9 @@ public: virtual void lock(); virtual void unlock(); virtual void finish(); + + AudioDriverOSX(); + ~AudioDriverOSX(); }; #endif diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 1b32838525..5703cbc546 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -78,12 +78,15 @@ def configure(env): env.Append(LIBS=['pthread']) #env.Append(CPPFLAGS=['-F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-mmacosx-version-min=10.4']) #env.Append(LINKFLAGS=['-mmacosx-version-min=10.4', '-isysroot', '/Developer/SDKs/MacOSX10.4u.sdk', '-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk']) - env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit','-lz']) + env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit','-lz']) if (env["CXX"]=="clang++"): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env["CC"]="clang" env["LD"]="clang++" + if (env["colored"]=="yes"): + if sys.stdout.isatty(): + env.Append(CPPFLAGS=["-fcolor-diagnostics"]) import methods diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 5df85bca2a..9ffd4fc3f8 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -99,6 +99,13 @@ public: CursorShape cursor_shape; MouseMode mouse_mode; + + bool minimized; + bool maximized; + bool zoomed; + Vector<Rect2> screens; + int current_screen; + Rect2 restore_rect; protected: virtual int get_video_driver_count() const; @@ -112,16 +119,13 @@ protected: virtual void set_main_loop( MainLoop * p_main_loop ); virtual void delete_main_loop(); - public: - - - - static OS_OSX* singleton; + void wm_minimized(bool p_minimized); + virtual String get_name(); virtual void set_cursor_shape(CursorShape p_shape); @@ -133,6 +137,8 @@ public: virtual Point2 get_mouse_pos() const; virtual int get_mouse_button_state() const; virtual void set_window_title(const String& p_title); + + virtual Size2 get_window_size() const; virtual void set_icon(const Image& p_icon); @@ -156,8 +162,28 @@ public: virtual String get_executable_path() const; + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + virtual void move_window_to_foreground(); + virtual int get_screen_count() const; + virtual int get_current_screen() const; + virtual void set_current_screen(int p_screen); + virtual Point2 get_screen_position(int p_screen=0); + virtual Point2 get_window_position() const; + virtual void set_window_position(const Point2& p_position); + 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; + Size2 get_screen_size(int p_screen); + + void run(); void set_mouse_mode(MouseMode p_mode); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 643c287c95..a20263f9b2 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -27,6 +27,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #import <Cocoa/Cocoa.h> + +#include <Carbon/Carbon.h> #include <IOKit/IOKitLib.h> #include <IOKit/IOCFPlugIn.h> #include <IOKit/hid/IOHIDLib.h> @@ -225,19 +227,6 @@ static int button_mask=0; // centerCursor(window); } -- (void)windowDidMiniaturize:(NSNotification *)notification -{ - // _GodotInputWindowIconify(window, GL_TRUE); -} - -- (void)windowDidDeminiaturize:(NSNotification *)notification -{ - //if (window->monitor) -// enterFullscreenMode(window); - - // _GodotInputWindowIconify(window, GL_FALSE); -} - - (void)windowDidBecomeKey:(NSNotification *)notification { // _GodotInputWindowFocus(window, GL_TRUE); @@ -254,6 +243,21 @@ static int button_mask=0; OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); } +- (void)windowDidMiniaturize:(NSNotification*)notification +{ + OS_OSX::singleton->wm_minimized(true); + if (OS_OSX::singleton->get_main_loop()) + OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); +}; + +- (void)windowDidDeminiaturize:(NSNotification*)notification +{ + + OS_OSX::singleton->wm_minimized(false); + if (OS_OSX::singleton->get_main_loop()) + OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); +}; + @end @interface GodotContentView : NSView @@ -694,7 +698,7 @@ static int translateKey(unsigned int key) ev.type=InputEvent::KEY; ev.key.pressed=true; ev.key.mod=translateFlags([event modifierFlags]); - ev.key.scancode = translateKey([event keyCode]); + ev.key.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode])); ev.key.echo = [event isARepeat]; NSString* characters = [event characters]; @@ -740,7 +744,7 @@ static int translateKey(unsigned int key) ev.type=InputEvent::KEY; ev.key.pressed=false; ev.key.mod=translateFlags([event modifierFlags]); - ev.key.scancode = translateKey([event keyCode]); + ev.key.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode])); OS_OSX::singleton->push_input(ev); @@ -835,11 +839,24 @@ void OS_OSX::initialize_core() { } +static bool keyboard_layout_dirty = true; +static void keyboardLayoutChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { + keyboard_layout_dirty = true; +} + void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { /*** OSX INITIALIZATION ***/ /*** OSX INITIALIZATION ***/ /*** OSX INITIALIZATION ***/ + + keyboard_layout_dirty = true; + + // Register to be notified on keyboard layout changes + CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), + NULL, keyboardLayoutChanged, + kTISNotifySelectedKeyboardInputSourceChanged, NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); window_delegate = [[GodotWindowDelegate alloc] init]; @@ -888,7 +905,7 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi unsigned int attributeCount = 0; // OS X needs non-zero color size, so set resonable values - int colorBits = 24; + int colorBits = 32; // Fail if a robustness strategy was requested @@ -1003,10 +1020,20 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi _ensure_data_dir(); + NSArray *screenArray = [NSScreen screens]; + printf("nscreen count %i\n", (int)[screenArray count]); + for (int i=0; i<[screenArray count]; i++) { + NSRect nsrect = [[screenArray objectAtIndex: i] visibleFrame]; + screens.push_back(Rect2(nsrect.origin.x, nsrect.origin.y, nsrect.size.width, nsrect.size.height)); + printf("added screen %i\n", screens.size()); + }; + restore_rect = Rect2(get_window_position(), get_window_size()); } void OS_OSX::finalize() { + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); + } void OS_OSX::set_main_loop( MainLoop * p_main_loop ) { @@ -1076,8 +1103,19 @@ void OS_OSX::warp_mouse_pos(const Point2& p_to) { mouse_y = p_to.y; } else{ //set OS position - CGPoint lMouseWarpPos = {p_to.x, p_to.y}; + /* this code has not been tested, please be a kind soul and fix it if it fails! */ + + //local point in window coords + NSPoint localPoint = { p_to.x, p_to.y }; + + NSPoint pointInWindow = [window_view convertPoint:localPoint toView:nil]; + NSPoint pointOnScreen = [[window_view window] convertRectToScreen:(NSRect){.origin=pointInWindow}].origin; + + //point in scren coords + CGPoint lMouseWarpPos = { pointOnScreen.x, pointOnScreen.y}; + + //do the warping CGEventSourceRef lEventRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0); CGAssociateMouseAndMouseCursorPosition(false); @@ -1203,7 +1241,10 @@ void OS_OSX::swap_buffers() { } +void OS_OSX::wm_minimized(bool p_minimized) { + minimized = p_minimized; +}; void OS_OSX::set_video_mode(const VideoMode& p_video_mode,int p_screen) { @@ -1217,6 +1258,119 @@ void OS_OSX::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons } + +int OS_OSX::get_screen_count() const { + + return screens.size(); +}; + +int OS_OSX::get_current_screen() const { + + return current_screen; +}; + +void OS_OSX::set_current_screen(int p_screen) { + + current_screen = p_screen; +}; + +Point2 OS_OSX::get_screen_position(int p_screen) { + + ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2()); + return screens[p_screen].pos; +}; + +Size2 OS_OSX::get_screen_size(int p_screen) { + + ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2()); + return screens[p_screen].size; +}; + +Point2 OS_OSX::get_window_position() const { + + return Size2([window_object frame].origin.x, [window_object frame].origin.y); +}; + + +void OS_OSX::set_window_position(const Point2& p_position) { + + [window_object setFrame:NSMakeRect(p_position.x, p_position.y, [window_object frame].size.width, [window_object frame].size.height) display:YES]; +}; + +Size2 OS_OSX::get_window_size() const { + + return Size2([window_object frame].size.width, [window_object frame].size.height); +}; + +void OS_OSX::set_window_size(const Size2 p_size) { + + NSRect frame = [window_object frame]; + [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, p_size.x, p_size.y) display:YES]; +}; + +void OS_OSX::set_window_fullscreen(bool p_enabled) { + + [window_object performZoom:nil]; + zoomed = p_enabled; +}; + +bool OS_OSX::is_window_fullscreen() const { + + if ( [window_object respondsToSelector:@selector(isZoomed)] ) + return [window_object isZoomed]; + + return zoomed; +}; + +void OS_OSX::set_window_resizable(bool p_enabled) { + + if (p_enabled) + [window_object setStyleMask:[window_object styleMask] | NSResizableWindowMask ]; + else + [window_object setStyleMask:[window_object styleMask] & ~NSResizableWindowMask ]; +}; + +bool OS_OSX::is_window_resizable() const { + + return [window_object styleMask] & NSResizableWindowMask; +}; + +void OS_OSX::set_window_minimized(bool p_enabled) { + + if (p_enabled) + [window_object performMiniaturize:nil]; + else + [window_object deminiaturize:nil]; +}; + +bool OS_OSX::is_window_minimized() const { + + if ( [window_object respondsToSelector:@selector(isMiniaturized)]) + return [window_object isMiniaturized]; + + return minimized; +}; + + +void OS_OSX::set_window_maximized(bool p_enabled) { + + if (p_enabled) { + restore_rect = Rect2(get_window_position(), get_window_size()); + [window_object setFrame:[[[NSScreen screens] objectAtIndex:current_screen] visibleFrame] display:YES]; + } else { + set_window_size(restore_rect.size); + set_window_position(restore_rect.pos); + }; + maximized = p_enabled; +}; + +bool OS_OSX::is_window_maximized() const { + + // don't know + return maximized; +}; + + void OS_OSX::move_window_to_foreground() { [window_object orderFrontRegardless]; @@ -1241,6 +1395,83 @@ String OS_OSX::get_executable_path() const { } +// Returns string representation of keys, if they are printable. +// +static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) { + + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + if (!currentKeyboard) + return nil; + + CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + if (!layoutData) + return nil; + + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); + + OSStatus err; + CFMutableStringRef output = CFStringCreateMutable(NULL, 0); + + for (int i=0; i<length; ++i) { + + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; + + err = UCKeyTranslate(keyboardLayout, + keyCode[i], + kUCKeyActionDisplay, + 0, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &keysDown, + sizeof(chars) / sizeof(chars[0]), + &realLength, + chars); + + if (err != noErr) { + CFRelease(output); + return nil; + } + + CFStringAppendCharacters(output, chars, 1); + } + + //CFStringUppercase(output, NULL); + + return (NSString *)output; +} +OS::LatinKeyboardVariant OS_OSX::get_latin_keyboard_variant() const { + + static LatinKeyboardVariant layout = LATIN_KEYBOARD_QWERTY; + + if (keyboard_layout_dirty) { + + layout = LATIN_KEYBOARD_QWERTY; + + CGKeyCode keys[] = {kVK_ANSI_Q, kVK_ANSI_W, kVK_ANSI_E, kVK_ANSI_R, kVK_ANSI_T, kVK_ANSI_Y}; + NSString *test = createStringForKeys(keys, 6); + + if ([test isEqualToString:@"qwertz"]) { + layout = LATIN_KEYBOARD_QWERTZ; + } else if ([test isEqualToString:@"azerty"]) { + layout = LATIN_KEYBOARD_AZERTY; + } else if ([test isEqualToString:@"qzerty"]) { + layout = LATIN_KEYBOARD_QZERTY; + } else if ([test isEqualToString:@"',.pyf"]) { + layout = LATIN_KEYBOARD_DVORAK; + } else if ([test isEqualToString:@"xvlcwk"]) { + layout = LATIN_KEYBOARD_NEO; + } + + [test release]; + + keyboard_layout_dirty = false; + return layout; + } + + return layout; +} void OS_OSX::process_events() { @@ -1368,5 +1599,9 @@ OS_OSX::OS_OSX() { last_id=1; cursor_shape=CURSOR_ARROW; + current_screen = 0; + maximized = false; + minimized = false; + zoomed = false; } diff --git a/platform/server/detect.py b/platform/server/detect.py index 24b36d3188..e2d64c6545 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -40,6 +40,9 @@ def configure(env): env["CC"]="clang" env["CXX"]="clang++" env["LD"]="clang++" + if (env["colored"]=="yes"): + if sys.stdout.isatty(): + env.Append(CXXFLAGS=["-fcolor-diagnostics"]) is64=sys.maxsize > 2**32 diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 7bc8f61744..1aabf5337b 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -56,7 +56,6 @@ void OS_Server::initialize(const VideoMode& p_desired,int p_video_driver,int p_a args=OS::get_singleton()->get_cmdline_args(); current_videomode=p_desired; main_loop=NULL; - rasterizer = memnew( RasterizerDummy ); @@ -163,6 +162,12 @@ OS::VideoMode OS_Server::get_video_mode(int p_screen) const { return current_videomode; } + +Size2 OS_Server::get_window_size() const { + + return Vector2(current_videomode.width,current_videomode.height) ; +} + void OS_Server::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const { diff --git a/platform/server/os_server.h b/platform/server/os_server.h index fcf96253ad..f8d346ce48 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -109,6 +109,8 @@ public: virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const; + virtual Size2 get_window_size() const; + virtual void move_window_to_foreground(); void run(); diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 08a775e689..a77428e954 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -7,6 +7,7 @@ common_win=[ "ctxgl_procaddr.cpp", "key_mapping_win.cpp", "tcp_server_winsock.cpp", + "packet_peer_udp_winsock.cpp", "stream_peer_winsock.cpp", ] diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 63fb5a47a5..9cdf04797c 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -1,4 +1,90 @@ -
+#
+# tested on | Windows native | Linux cross-compilation
+# ------------------------+-------------------+---------------------------
+# MSVS C++ 2010 Express | WORKS | n/a
+# Mingw-w64 | WORKS | WORKS
+# Mingw-w32 | WORKS | WORKS
+# MinGW | WORKS | untested
+#
+#####
+# Notes about MSVS C++ :
+#
+# - MSVC2010-Express compiles to 32bits only.
+#
+#####
+# Notes about Mingw-w64 and Mingw-w32 under Windows :
+#
+# - both can be installed using the official installer :
+# http://mingw-w64.sourceforge.net/download.php#mingw-builds
+#
+# - if you want to compile both 32bits and 64bits, don't forget to
+# run the installer twice to install them both.
+#
+# - install them into a path that does not contain spaces
+# ( example : "C:/Mingw-w32", "C:/Mingw-w64" )
+#
+# - if you want to compile faster using the "-j" option, don't forget
+# to install the appropriate version of the Pywin32 python extension
+# available from : http://sourceforge.net/projects/pywin32/files/
+#
+# - before running scons, you must add into the environment path
+# the path to the "/bin" directory of the Mingw version you want
+# to use :
+#
+# set PATH=C:/Mingw-w32/bin;%PATH%
+#
+# - then, scons should be able to detect gcc.
+# - Mingw-w32 only compiles 32bits.
+# - Mingw-w64 only compiles 64bits.
+#
+# - it is possible to add them both at the same time into the PATH env,
+# if you also define the MINGW32_PREFIX and MINGW64_PREFIX environment
+# variables.
+# For instance, you could store that set of commands into a .bat script
+# that you would run just before scons :
+#
+# set PATH=C:\mingw-w32\bin;%PATH%
+# set PATH=C:\mingw-w64\bin;%PATH%
+# set MINGW32_PREFIX=C:\mingw-w32\bin\
+# set MINGW64_PREFIX=C:\mingw-w64\bin\
+#
+#####
+# Notes about Mingw, Mingw-w64 and Mingw-w32 under Linux :
+#
+# - default toolchain prefixes are :
+# "i586-mingw32msvc-" for MinGW
+# "i686-w64-mingw32-" for Mingw-w32
+# "x86_64-w64-mingw32-" for Mingw-w64
+#
+# - if both MinGW and Mingw-w32 are installed on your system
+# Mingw-w32 should take the priority over MinGW.
+#
+# - it is possible to manually override prefixes by defining
+# the MINGW32_PREFIX and MINGW64_PREFIX environment variables.
+#
+#####
+# Notes about Mingw under Windows :
+#
+# - this is the MinGW version from http://mingw.org/
+# - install it into a path that does not contain spaces
+# ( example : "C:/MinGW" )
+# - several DirectX headers might be missing. You can copy them into
+# the C:/MinGW/include" directory from this page :
+# https://code.google.com/p/mingw-lib/source/browse/trunk/working/avcodec_to_widget_5/directx_include/
+# - before running scons, add the path to the "/bin" directory :
+# set PATH=C:/MinGW/bin;%PATH%
+# - scons should be able to detect gcc.
+#
+
+#####
+# TODO :
+#
+# - finish to cleanup this script to remove all the remains of previous hacks and workarounds
+# - make it work with the Windows7 SDK that is supposed to enable 64bits compilation for MSVC2010-Express
+# - confirm it works well with other Visual Studio versions.
+# - update the wiki about the pywin32 extension required for the "-j" option under Windows.
+# - update the wiki to document MINGW32_PREFIX and MINGW64_PREFIX
+#
import os
@@ -13,50 +99,70 @@ def get_name(): def can_build():
-
if (os.name=="nt"):
#building natively on windows!
if (os.getenv("VSINSTALLDIR")):
return True
else:
- print("MSVC Not detected, attempting mingw.")
+ print("\nMSVC not detected, attempting Mingw.")
+ mingw32 = ""
+ mingw64 = ""
+ if ( os.getenv("MINGW32_PREFIX") ) :
+ mingw32 = os.getenv("MINGW32_PREFIX")
+ if ( os.getenv("MINGW64_PREFIX") ) :
+ mingw64 = os.getenv("MINGW64_PREFIX")
+
+ test = "gcc --version > NUL 2>&1"
+ if os.system(test)!= 0 and os.system(mingw32+test)!=0 and os.system(mingw64+test)!=0 :
+ print("- could not detect gcc.")
+ print("Please, make sure a path to a Mingw /bin directory is accessible into the environment PATH.\n")
+ return False
+ else:
+ print("- gcc detected.")
+
return True
-
-
if (os.name=="posix"):
mingw = "i586-mingw32msvc-"
- mingw64 = "i686-w64-mingw32-"
+ mingw64 = "x86_64-w64-mingw32-"
+ mingw32 = "i686-w64-mingw32-"
+
if (os.getenv("MINGW32_PREFIX")):
- mingw=os.getenv("MINGW32_PREFIX")
+ mingw32=os.getenv("MINGW32_PREFIX")
+ mingw = mingw32
if (os.getenv("MINGW64_PREFIX")):
mingw64=os.getenv("MINGW64_PREFIX")
-
- if os.system(mingw+"gcc --version >/dev/null") == 0 or os.system(mingw64+"gcc --version >/dev/null") ==0:
+
+ test = "gcc --version >/dev/null"
+ if os.system(mingw+test) == 0 or os.system(mingw64+test) ==0 or os.system(mingw32+test) ==0 :
return True
-
-
return False
def get_opts():
mingw=""
+ mingw32=""
mingw64=""
- if (os.name!="nt"):
+ if ( os.name == "posix" ):
mingw = "i586-mingw32msvc-"
- mingw64 = "i686-w64-mingw32-"
- if (os.getenv("MINGW32_PREFIX")):
- mingw=os.getenv("MINGW32_PREFIX")
- if (os.getenv("MINGW64_PREFIX")):
- mingw64=os.getenv("MINGW64_PREFIX")
+ mingw32 = "i686-w64-mingw32-"
+ mingw64 = "x86_64-w64-mingw32-"
+
+ if os.system(mingw32+"gcc --version >/dev/null") != 0 :
+ mingw32 = mingw
+
+ if (os.getenv("MINGW32_PREFIX")):
+ mingw32=os.getenv("MINGW32_PREFIX")
+ mingw = mingw32
+ if (os.getenv("MINGW64_PREFIX")):
+ mingw64=os.getenv("MINGW64_PREFIX")
return [
- ('mingw_prefix','Mingw Prefix',mingw),
+ ('mingw_prefix','Mingw Prefix',mingw32),
('mingw_prefix_64','Mingw Prefix 64 bits',mingw64),
- ('mingw64_for_32','Use Mingw 64 for 32 Bits Build',"no"),
]
def get_flags():
@@ -64,7 +170,7 @@ def get_flags(): return [
('freetype','builtin'), #use builtin freetype
('openssl','builtin'), #use builtin openssl
- ('theora','no'), #use builtin openssl
+ ('theora','no'),
]
@@ -113,9 +219,9 @@ def configure(env): env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
- env.Append(CCFLAGS=['/DGLES1_ENABLED'])
+
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
- LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32']
+ LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI','Shlwapi', 'wsock32', 'shell32','advapi32']
env.Append(LINKFLAGS=[p+env["LIBSUFFIX"] for p in LIBS])
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
@@ -135,33 +241,64 @@ def configure(env): env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"])
env['ENV'] = os.environ;
else:
+
+ # Workaround for MinGW. See:
+ # http://www.scons.org/wiki/LongCmdLinesOnWin32
+ if (os.name=="nt"):
+ import subprocess
+
+ def mySubProcess(cmdline,env):
+ #print "SPAWNED : " + cmdline
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
+ data, err = proc.communicate()
+ rv = proc.wait()
+ if rv:
+ print "====="
+ print err
+ print "====="
+ return rv
+
+ def mySpawn(sh, escape, cmd, args, env):
+
+ newargs = ' '.join(args[1:])
+ cmdline = cmd + " " + newargs
+
+ rv=0
+ if len(cmdline) > 32000 and cmd.endswith("ar") :
+ cmdline = cmd + " " + args[1] + " " + args[2] + " "
+ for i in range(3,len(args)) :
+ rv = mySubProcess( cmdline + args[i], env )
+ if rv :
+ break
+ else:
+ rv = mySubProcess( cmdline, env )
+
+ return rv
+
+ env['SPAWN'] = mySpawn
+
#build using mingw
if (os.name=="nt"):
env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes
else:
- env["PROGSUFFIX"]=env["PROGSUFFIX"]+".exe"
+ env["PROGSUFFIX"]=env["PROGSUFFIX"]+".exe" # for linux cross-compilation
mingw_prefix=""
if (env["bits"]=="default"):
env["bits"]="32"
- use64=False
if (env["bits"]=="32"):
-
- if (env["mingw64_for_32"]=="yes"):
- env.Append(CCFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-m32'])
- env.Append(LINKFLAGS=['-static-libgcc'])
- env.Append(LINKFLAGS=['-static-libstdc++'])
- mingw_prefix=env["mingw_prefix_64"];
- else:
- mingw_prefix=env["mingw_prefix"];
-
-
+ env.Append(LINKFLAGS=['-static'])
+ env.Append(LINKFLAGS=['-static-libgcc'])
+ env.Append(LINKFLAGS=['-static-libstdc++'])
+ mingw_prefix=env["mingw_prefix"];
else:
- mingw_prefix=env["mingw_prefix_64"];
env.Append(LINKFLAGS=['-static'])
+ mingw_prefix=env["mingw_prefix_64"];
nulstr=""
@@ -172,10 +309,10 @@ def configure(env): - if os.system(mingw_prefix+"gcc --version"+nulstr)!=0:
- #not really super consistent but..
- print("Can't find Windows compiler: "+mingw_prefix)
- sys.exit(255)
+ # if os.system(mingw_prefix+"gcc --version"+nulstr)!=0:
+ # #not really super consistent but..
+ # print("Can't find Windows compiler: "+mingw_prefix)
+ # sys.exit(255)
if (env["target"]=="release"):
@@ -207,8 +344,18 @@ def configure(env): env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
- env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLEW_ENABLED'])
- env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
+ env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLEW_ENABLED'])
+ env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','shlwapi','wsock32','kernel32'])
+
+ # if (env["bits"]=="32"):
+# # env.Append(LIBS=['gcc_s'])
+ # #--with-arch=i686
+ # env.Append(CPPFLAGS=['-march=i686'])
+ # env.Append(LINKFLAGS=['-march=i686'])
+
+
+
+
#'d3dx9d'
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
env.Append(LINKFLAGS=['-g'])
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 81a96ccb13..93275b3d54 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles1/rasterizer_gles1.h" + #include "os_windows.h" #include "drivers/nedmalloc/memory_pool_static_nedmalloc.h" #include "drivers/unix/memory_pool_static_malloc.h" @@ -45,14 +45,27 @@ #include "servers/visual/visual_server_wrap_mt.h" #include "tcp_server_winsock.h" +#include "packet_peer_udp_winsock.h" #include "stream_peer_winsock.h" #include "os/pc_joystick_map.h" #include "lang_table.h" #include "os/memory_pool_dynamic_prealloc.h" #include "globals.h" #include "io/marshalls.h" + +#include "shlobj.h" +#include <regstr.h> + static const WORD MAX_CONSOLE_LINES = 1500; +extern "C" { +#ifdef _MSC_VER + _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +#else + __attribute__((visibility("default"))) DWORD NvOptimusEnablement = 0x00000001; +#endif +} + //#define STDOUT_FILE extern HINSTANCE godot_hinstance; @@ -126,11 +139,11 @@ void RedirectIOToConsole() { int OS_Windows::get_video_driver_count() const { - return 2; + return 1; } const char * OS_Windows::get_video_driver_name(int p_driver) const { - return p_driver==0?"GLES2":"GLES1"; + return "GLES2"; } OS::VideoMode OS_Windows::get_default_video_mode() const { @@ -158,6 +171,8 @@ void OS_Windows::initialize_core() { last_button_state=0; //RedirectIOToConsole(); + maximized=false; + minimized=false; ThreadWindows::make_default(); SemaphoreWindows::make_default(); @@ -173,6 +188,7 @@ void OS_Windows::initialize_core() { TCPServerWinsock::make_default(); StreamPeerWinsock::make_default(); + PacketPeerUDPWinsock::make_default(); mempool_static = new MemoryPoolStaticMalloc; #if 1 @@ -407,6 +423,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { case WM_RBUTTONUP: case WM_MOUSEWHEEL: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: /*case WM_XBUTTONDOWN: case WM_XBUTTONUP: */{ @@ -460,6 +477,12 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { mb.button_index=1; mb.doubleclick = true; } break; + case WM_RBUTTONDBLCLK: { + + mb.pressed=true; + mb.button_index=2; + mb.doubleclick = true; + } break; case WM_MOUSEWHEEL: { mb.pressed=true; @@ -581,10 +604,11 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); + // Make sure we don't include modifiers for the modifier key itself. KeyEvent ke; - ke.mod_state.shift=shift_mem; - ke.mod_state.alt=alt_mem; - ke.mod_state.control=control_mem; + ke.mod_state.shift= (wParam != VK_SHIFT) ? shift_mem : false; + ke.mod_state.alt= (! (wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false; + ke.mod_state.control= (wParam != VK_CONTROL) ? control_mem : false; ke.mod_state.meta=meta_mem; ke.uMsg=uMsg; @@ -672,6 +696,53 @@ LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { } + +String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps) +{ + char buffer [256]; + char OEM [256]; + HKEY hKey; + DWORD sz; + int res; + + _snprintf(buffer, sizeof(buffer), "%s\\%s\\%s", + REGSTR_PATH_JOYCONFIG, jcaps.szRegKey, + REGSTR_KEY_JOYCURR ); + res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey); + if (res != ERROR_SUCCESS) + { + res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey); + if (res != ERROR_SUCCESS) + return ""; + } + + sz = sizeof(OEM); + _snprintf( buffer, sizeof(buffer), "Joystick%d%s", id + 1, REGSTR_VAL_JOYOEMNAME); + res = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEM, &sz); + RegCloseKey ( hKey ); + if (res != ERROR_SUCCESS) + return ""; + + _snprintf( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEM); + res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey); + if (res != ERROR_SUCCESS) + { + res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey); + if (res != ERROR_SUCCESS) + return ""; + } + + + sz = sizeof(buffer); + res = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buffer, + &sz); + RegCloseKey(hKey); + if (res != ERROR_SUCCESS) + return ""; + + return String(buffer); +} + void OS_Windows::probe_joysticks() { static uint32_t last_attached = 0; @@ -713,7 +784,13 @@ void OS_Windows::probe_joysticks() { JOYCAPS jcaps; MMRESULT res = joyGetDevCaps(JOYSTICKID1 + i, &jcaps, sizeof(jcaps)); if (res == JOYERR_NOERROR) { - joy.name = jcaps.szPname; + String name = get_joystick_name(JOYSTICKID1 + i, jcaps); + if ( name == "") + joy.name = jcaps.szPname; + else + joy.name = name; + + }; }; @@ -928,7 +1005,7 @@ void OS_Windows::process_joysticks() { if ( (joysticks[i].last_buttons & (1<<j)) != (jinfo.dwButtons & (1<<j)) ) { - ievent.joy_button.button_index = _pc_joystick_get_native_button(j); + ievent.joy_button.button_index = j; //_pc_joystick_get_native_button(j); ievent.joy_button.pressed = jinfo.dwButtons & 1<<j; ievent.ID = ++last_id; input->parse_input_event(ievent); @@ -939,6 +1016,23 @@ void OS_Windows::process_joysticks() { }; }; + +BOOL CALLBACK OS_Windows::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + OS_Windows *self=(OS_Windows*)OS::get_singleton(); + MonitorInfo minfo; + minfo.hMonitor=hMonitor; + minfo.hdcMonitor=hdcMonitor; + minfo.rect.pos.x=lprcMonitor->left; + minfo.rect.pos.y=lprcMonitor->top; + minfo.rect.size.x=lprcMonitor->right - lprcMonitor->left; + minfo.rect.size.y=lprcMonitor->bottom - lprcMonitor->top; + + self->monitor_info.push_back(minfo); + + return TRUE; +} + + void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { @@ -977,13 +1071,20 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ } + EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,0); + + print_line("DETECTED MONITORS: "+itos(monitor_info.size())); + pre_fs_valid=true; if (video_mode.fullscreen) { DEVMODE current; memset(¤t,0,sizeof(current)); EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t); + + WindowRect.right = current.dmPelsWidth; + WindowRect.bottom = current.dmPelsHeight; - DEVMODE dmScreenSettings; +/* DEVMODE dmScreenSettings; memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); dmScreenSettings.dmSize=sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = video_mode.width; @@ -995,7 +1096,8 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ if (err!=DISP_CHANGE_SUCCESSFUL) { video_mode.fullscreen=false; - } + }*/ + pre_fs_valid=false; } DWORD dwExStyle; @@ -1366,9 +1468,13 @@ void OS_Windows::warp_mouse_pos(const Point2& p_to) { old_y=p_to.y; } else { - SetCursorPos(p_to.x, p_to.y); - } + POINT p; + p.x=p_to.x; + p.y=p_to.y; + ClientToScreen(hWnd,&p); + SetCursorPos(p.x,p.y); + } } Point2 OS_Windows::get_mouse_pos() const { @@ -1388,8 +1494,9 @@ void OS_Windows::set_window_title(const String& p_title) { void OS_Windows::set_video_mode(const VideoMode& p_video_mode,int p_screen) { - + } + OS::VideoMode OS_Windows::get_video_mode(int p_screen) const { return video_mode; @@ -1399,6 +1506,251 @@ void OS_Windows::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) } +int OS_Windows::get_screen_count() const { + + return monitor_info.size(); +} +int OS_Windows::get_current_screen() const{ + + HMONITOR monitor = MonitorFromWindow(hWnd,MONITOR_DEFAULTTONEAREST); + for(int i=0;i<monitor_info.size();i++) { + if (monitor_info[i].hMonitor==monitor) + return i; + } + + return 0; +} +void OS_Windows::set_current_screen(int p_screen){ + + ERR_FAIL_INDEX(p_screen,monitor_info.size()); + + Vector2 ofs = get_window_position() - get_screen_position(get_current_screen()); + set_window_position(ofs+get_screen_position(p_screen)); + +} + +Point2 OS_Windows::get_screen_position(int p_screen) const{ + + ERR_FAIL_INDEX_V(p_screen,monitor_info.size(),Point2()); + return Vector2( monitor_info[p_screen].rect.pos ); + +} +Size2 OS_Windows::get_screen_size(int p_screen) const{ + + ERR_FAIL_INDEX_V(p_screen,monitor_info.size(),Point2()); + return Vector2( monitor_info[p_screen].rect.size ); + +} +Point2 OS_Windows::get_window_position() const{ + + RECT r; + GetWindowRect(hWnd,&r); + return Point2(r.left,r.top); +} +void OS_Windows::set_window_position(const Point2& p_position){ + + RECT r; + GetWindowRect(hWnd,&r); + MoveWindow(hWnd,p_position.x,p_position.y,r.right-r.left,r.bottom-r.top,TRUE); + +} +Size2 OS_Windows::get_window_size() const{ + + RECT r; + GetClientRect(hWnd,&r); + return Vector2(r.right-r.left,r.bottom-r.top); + +} +void OS_Windows::set_window_size(const Size2 p_size){ + + video_mode.width=p_size.width; + video_mode.height=p_size.height; + + if (video_mode.fullscreen) { + return; + } + + + RECT crect; + GetClientRect(hWnd,&crect); + + RECT rect; + GetWindowRect(hWnd,&rect); + int dx = (rect.right-rect.left)-(crect.right-crect.left); + int dy = (rect.bottom-rect.top)-(crect.bottom-crect.top); + + rect.right=rect.left+p_size.width+dx; + rect.bottom=rect.top+p_size.height+dy; + + + //print_line("PRE: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top)); + + /*if (video_mode.resizable) { + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); + } else { + AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE); + }*/ + + //print_line("POST: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top)); + + MoveWindow(hWnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE); + +} +void OS_Windows::set_window_fullscreen(bool p_enabled){ + + if (video_mode.fullscreen==p_enabled) + return; + + + + if (p_enabled) { + + + if (pre_fs_valid) { + GetWindowRect(hWnd,&pre_fs_rect); + //print_line("A: "+itos(pre_fs_rect.left)+","+itos(pre_fs_rect.top)+","+itos(pre_fs_rect.right-pre_fs_rect.left)+","+itos(pre_fs_rect.bottom-pre_fs_rect.top)); + //MapWindowPoints(hWnd, GetParent(hWnd), (LPPOINT) &pre_fs_rect, 2); + //print_line("B: "+itos(pre_fs_rect.left)+","+itos(pre_fs_rect.top)+","+itos(pre_fs_rect.right-pre_fs_rect.left)+","+itos(pre_fs_rect.bottom-pre_fs_rect.top)); + } + + + int cs = get_current_screen(); + Point2 pos = get_screen_position(cs); + Size2 size = get_screen_size(cs); + + /* r.left = pos.x; + r.top = pos.y; + r.bottom = pos.y+size.y; + r.right = pos.x+size.x; +*/ + SetWindowLongPtr(hWnd, GWL_STYLE, + WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE); + MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE); + + video_mode.fullscreen=true; + + + } else { + + RECT rect; + + if (pre_fs_valid) { + rect=pre_fs_rect; + } else { + rect.left=0; + rect.right=video_mode.width; + rect.top=0; + rect.bottom=video_mode.height; + } + + + + if (video_mode.resizable) { + + SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); + //AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); + MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); + } else { + + SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE); + //AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE); + MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); + } + + video_mode.fullscreen=false; + pre_fs_valid=true; +/* + DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + DWORD dwStyle=WS_OVERLAPPEDWINDOW; + if (!video_mode.resizable) { + dwStyle &= ~WS_THICKFRAME; + dwStyle &= ~WS_MAXIMIZEBOX; + } + AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle); + video_mode.fullscreen=false; + video_mode.width=pre_fs_rect.right-pre_fs_rect.left; + video_mode.height=pre_fs_rect.bottom-pre_fs_rect.top; +*/ + } + +// MoveWindow(hWnd,r.left,r.top,p_size.x,p_size.y,TRUE); + + +} +bool OS_Windows::is_window_fullscreen() const{ + + return video_mode.fullscreen; +} +void OS_Windows::set_window_resizable(bool p_enabled){ + + if (video_mode.resizable==p_enabled) + return; +/* + GetWindowRect(hWnd,&pre_fs_rect); + DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + DWORD dwStyle=WS_OVERLAPPEDWINDOW; + if (!p_enabled) { + dwStyle &= ~WS_THICKFRAME; + dwStyle &= ~WS_MAXIMIZEBOX; + } + AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle); + */ + + if (!video_mode.fullscreen) { + if (p_enabled) { + SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); + } else { + SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE); + + } + + RECT rect; + GetWindowRect(hWnd,&rect); + MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); + } + + video_mode.resizable=p_enabled; + +} +bool OS_Windows::is_window_resizable() const{ + + return video_mode.resizable; +} +void OS_Windows::set_window_minimized(bool p_enabled){ + + if (p_enabled) { + maximized=false; + minimized=true; + ShowWindow(hWnd,SW_MINIMIZE); + } else { + ShowWindow(hWnd,SW_RESTORE); + maximized=false; + minimized=false; + } +} +bool OS_Windows::is_window_minimized() const{ + + return minimized; + +} +void OS_Windows::set_window_maximized(bool p_enabled){ + + if (p_enabled) { + maximized=true; + minimized=false; + ShowWindow(hWnd,SW_MAXIMIZE); + } else { + ShowWindow(hWnd,SW_RESTORE); + maximized=false; + minimized=false; + } +} +bool OS_Windows::is_window_maximized() const{ + + return maximized; +} + + void OS_Windows::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) { HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE); @@ -1489,7 +1841,7 @@ OS::Date OS_Windows::get_date() const { OS::Time OS_Windows::get_time() const { SYSTEMTIME systemtime; - GetSystemTime(&systemtime); + GetLocalTime(&systemtime); Time time; time.hour=systemtime.wHour; @@ -1700,7 +2052,7 @@ String OS_Windows::get_executable_path() const { wchar_t bufname[4096]; GetModuleFileNameW(NULL,bufname,4096); String s= bufname; - print_line("EXEC PATHPó: "+s); + print_line("EXEC PATHP¨®: "+s); return s; } @@ -1786,6 +2138,7 @@ String OS_Windows::get_stdin_string(bool p_block) { void OS_Windows::move_window_to_foreground() { SetForegroundWindow(hWnd); + BringWindowToTop(hWnd); } @@ -1870,7 +2223,46 @@ MainLoop *OS_Windows::get_main_loop() const { return main_loop; } +String OS_Windows::get_system_dir(SystemDir p_dir) const { + + int id; + + + + switch(p_dir) { + case SYSTEM_DIR_DESKTOP: { + id=CSIDL_DESKTOPDIRECTORY; + } break; + case SYSTEM_DIR_DCIM: { + id=CSIDL_MYPICTURES; + } break; + case SYSTEM_DIR_DOCUMENTS: { + id=0x000C; + } break; + case SYSTEM_DIR_DOWNLOADS: { + id=0x000C ; + } break; + case SYSTEM_DIR_MOVIES: { + id=CSIDL_MYVIDEO; + } break; + case SYSTEM_DIR_MUSIC: { + id=CSIDL_MYMUSIC; + } break; + case SYSTEM_DIR_PICTURES: { + id=CSIDL_MYPICTURES; + } break; + case SYSTEM_DIR_RINGTONES: { + id=CSIDL_MYMUSIC; + } break; + } + + WCHAR szPath[MAX_PATH]; + HRESULT res = SHGetFolderPathW(NULL,id,NULL,0,szPath); + ERR_FAIL_COND_V(res!=S_OK,String()); + return String(szPath); + +} String OS_Windows::get_data_dir() const { String an = Globals::get_singleton()->get("application/name"); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 4b16637143..4995adc874 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -86,7 +86,7 @@ class OS_Windows : public OS { uint64_t ticks_start; uint64_t ticks_per_second; - bool minimized; + bool old_invalid; bool outside; int old_x,old_y; @@ -130,6 +130,7 @@ class OS_Windows : public OS { int joystick_count; Joystick joysticks[JOYSTICKS_MAX]; + Size2 window_rect; VideoMode video_mode; MainLoop *main_loop; @@ -187,6 +188,7 @@ protected: void probe_joysticks(); void process_joysticks(); void process_key_events(); + String get_joystick_name( int id, JOYCAPS jcaps); struct ProcessInfo { @@ -195,6 +197,23 @@ protected: }; Map<ProcessID, ProcessInfo>* process_map; + struct MonitorInfo { + HMONITOR hMonitor; + HDC hdcMonitor; + Rect2 rect; + + + }; + + bool pre_fs_valid; + RECT pre_fs_rect; + Vector<MonitorInfo> monitor_info; + bool maximized; + bool minimized; + + static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); + + public: LRESULT WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -217,6 +236,24 @@ public: virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_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; + virtual MainLoop *get_main_loop() const; virtual String get_name(); @@ -249,6 +286,8 @@ public: virtual void move_window_to_foreground(); virtual String get_data_dir() const; + virtual String get_system_dir(SystemDir p_dir) const; + virtual void release_rendering_thread(); virtual void make_rendering_thread(); diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp new file mode 100644 index 0000000000..aff92b8fc8 --- /dev/null +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -0,0 +1,202 @@ +#include "packet_peer_udp_winsock.h" + +#include <winsock2.h> + +int PacketPeerUDPWinsock::get_available_packet_count() const { + + Error err = const_cast<PacketPeerUDPWinsock*>(this)->_poll(false); + if (err!=OK) + return 0; + + return queue_count; +} + +Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{ + + Error err = const_cast<PacketPeerUDPWinsock*>(this)->_poll(false); + if (err!=OK) + return err; + if (queue_count==0) + return ERR_UNAVAILABLE; + + uint32_t size; + rb.read((uint8_t*)&packet_ip.host,4,true); + rb.read((uint8_t*)&packet_port,4,true); + rb.read((uint8_t*)&size,4,true); + rb.read(packet_buffer,size,true); + --queue_count; + *r_buffer=packet_buffer; + r_buffer_size=size; + return OK; + +} +Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){ + + int sock = _get_socket(); + ERR_FAIL_COND_V( sock == -1, FAILED ); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(peer_port); + addr.sin_addr = *((struct in_addr*)&peer_addr.host); + + + _set_blocking(true); + + errno = 0; + int err; + while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + + if (WSAGetLastError() != WSAEWOULDBLOCK) { + return FAILED; + }; + } + + return OK; +} + +int PacketPeerUDPWinsock::get_max_packet_size() const{ + + return 512; // uhm maybe not +} + + +void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) { + //am no windows expert + //hope this is the right thing + + if (blocking==p_blocking) + return; + + blocking=p_blocking; + unsigned long par = blocking?0:1; + if (ioctlsocket(sockfd, FIONBIO, &par)) { + perror("setting non-block mode"); + //close(); + //return -1; + }; +} + +Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size){ + + close(); + int sock = _get_socket(); + if (sock == -1 ) + return ERR_CANT_CREATE; + sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(p_port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + close(); + return ERR_UNAVAILABLE; + } + + blocking=true; + + printf("UDP Connection listening on port %i\n", p_port); + rb.resize(nearest_shift(p_recv_buffer_size)); + return OK; +} + +void PacketPeerUDPWinsock::close(){ + + if (sockfd != -1) + ::closesocket(sockfd); + sockfd=-1; + rb.resize(8); + queue_count=0; +} + + +Error PacketPeerUDPWinsock::wait() { + + return _poll(true); +} +Error PacketPeerUDPWinsock::_poll(bool p_wait) { + + + _set_blocking(p_wait); + + + struct sockaddr_in from = {0}; + int len = sizeof(struct sockaddr_in); + int ret; + while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), 0, (struct sockaddr*)&from, &len)) > 0) { + rb.write((uint8_t*)&from.sin_addr, 4); + uint32_t port = ntohs(from.sin_port); + rb.write((uint8_t*)&port, 4); + rb.write((uint8_t*)&ret, 4); + rb.write(recv_buffer, ret); + + len = sizeof(struct sockaddr_in); + ++queue_count; + }; + + + if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) ) { + close(); + return FAILED; + }; + + + return OK; +} + +bool PacketPeerUDPWinsock::is_listening() const{ + + return sockfd!=-1; +} + +IP_Address PacketPeerUDPWinsock::get_packet_address() const { + + return packet_ip; +} + +int PacketPeerUDPWinsock::get_packet_port() const{ + + return packet_port; +} + +int PacketPeerUDPWinsock::_get_socket() { + + if (sockfd != -1) + return sockfd; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ERR_FAIL_COND_V( sockfd == -1, -1 ); + //fcntl(sockfd, F_SETFL, O_NONBLOCK); + + return sockfd; +} + + +void PacketPeerUDPWinsock::set_send_address(const IP_Address& p_address,int p_port) { + + peer_addr=p_address; + peer_port=p_port; +} + +void PacketPeerUDPWinsock::make_default() { + + PacketPeerUDP::_create = PacketPeerUDPWinsock::_create; +}; + + +PacketPeerUDP* PacketPeerUDPWinsock::_create() { + + return memnew(PacketPeerUDPWinsock); +}; + + +PacketPeerUDPWinsock::PacketPeerUDPWinsock() { + + sockfd=-1; + packet_port=0; + queue_count=0; + peer_port=0; +} + +PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { + + close(); +} diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h new file mode 100644 index 0000000000..34dbcbee91 --- /dev/null +++ b/platform/windows/packet_peer_udp_winsock.h @@ -0,0 +1,56 @@ +#ifndef PACKET_PEER_UDP_WINSOCK_H +#define PACKET_PEER_UDP_WINSOCK_H + +#include "io/packet_peer_udp.h" +#include "ring_buffer.h" + +class PacketPeerUDPWinsock : public PacketPeerUDP { + + + enum { + PACKET_BUFFER_SIZE=65536 + }; + + mutable RingBuffer<uint8_t> rb; + uint8_t recv_buffer[PACKET_BUFFER_SIZE]; + mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; + IP_Address packet_ip; + int packet_port; + mutable int queue_count; + int sockfd; + + IP_Address peer_addr; + int peer_port; + + _FORCE_INLINE_ int _get_socket(); + + static PacketPeerUDP* _create(); + + bool blocking; + void _set_blocking(bool p_blocking); + + Error _poll(bool p_wait); + +public: + + virtual int get_available_packet_count() const; + virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const; + virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size); + + virtual int get_max_packet_size() const; + + virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual void close(); + virtual Error wait(); + virtual bool is_listening() const; + + virtual IP_Address get_packet_address() const; + virtual int get_packet_port() const; + + virtual void set_send_address(const IP_Address& p_address,int p_port); + + static void make_default(); + PacketPeerUDPWinsock(); + ~PacketPeerUDPWinsock(); +}; +#endif // PACKET_PEER_UDP_WINSOCK_H diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h index 7bc3e42833..a7e7f9c370 100644 --- a/platform/windows/platform_config.h +++ b/platform/windows/platform_config.h @@ -31,5 +31,5 @@ //#include <alloca.h> //#endif #define GLES2_INCLUDE_H "gl_context/glew.h" -#define GLES1_INCLUDE_H "gl_context/glew.h" + diff --git a/platform/winrt/SCsub b/platform/winrt/SCsub index 07e2ba81a6..2ea8cbd0de 100644 --- a/platform/winrt/SCsub +++ b/platform/winrt/SCsub @@ -8,4 +8,4 @@ files = [ 'os_winrt.cpp', ] -env.Program('#bin/godot_rt', files) +env.Program('#bin/godot', files) diff --git a/platform/winrt/app.cpp b/platform/winrt/app.cpp index e3213d574a..662229b04e 100644 --- a/platform/winrt/app.cpp +++ b/platform/winrt/app.cpp @@ -5,6 +5,8 @@ #include "app.h"
#include "main/main.h"
+#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
@@ -70,8 +72,9 @@ void App::Initialize(CoreApplicationView^ applicationView) }
// Called when the CoreWindow object is created (or re-created).
-void App::SetWindow(CoreWindow^ window)
+void App::SetWindow(CoreWindow^ p_window)
{
+ window = p_window;
window->VisibilityChanged +=
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
@@ -89,23 +92,230 @@ void App::SetWindow(CoreWindow^ window) pointerVisualizationSettings->IsBarrelButtonFeedbackEnabled = false;
#endif
- // The CoreWindow has been created, so EGL can be initialized.
+
+ window->PointerPressed +=
+ ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerPressed);
+
+ window->PointerMoved +=
+ ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerMoved);
+
+ window->PointerReleased +=
+ ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerReleased);
+
+ //window->PointerWheelChanged +=
+ // ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerWheelChanged);
+
+
+
+ char* args[] = {"-path", "game", NULL};
+ Main::setup("winrt", 2, args, false);
+
+ // The CoreWindow has been created, so EGL can be initialized.
ContextEGL* context = memnew(ContextEGL(window));
os->set_gl_context(context);
- UpdateWindowSize(Size(window->Bounds.Width, window->Bounds.Height));
+ UpdateWindowSize(Size(window->Bounds.Width, window->Bounds.Height));
+
+ Main::setup2();
+}
+
+static int _get_button(Windows::UI::Input::PointerPoint ^pt) {
+
+ using namespace Windows::UI::Input;
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ return BUTTON_LEFT;
+#else
+ switch (pt->Properties->PointerUpdateKind)
+ {
+ case PointerUpdateKind::LeftButtonPressed:
+ case PointerUpdateKind::LeftButtonReleased:
+ return BUTTON_LEFT;
+
+ case PointerUpdateKind::RightButtonPressed:
+ case PointerUpdateKind::RightButtonReleased:
+ return BUTTON_RIGHT;
+
+ case PointerUpdateKind::MiddleButtonPressed:
+ case PointerUpdateKind::MiddleButtonReleased:
+ return BUTTON_MIDDLE;
+
+ case PointerUpdateKind::XButton1Pressed:
+ case PointerUpdateKind::XButton1Released:
+ return BUTTON_WHEEL_UP;
+
+ case PointerUpdateKind::XButton2Pressed:
+ case PointerUpdateKind::XButton2Released:
+ return BUTTON_WHEEL_DOWN;
+
+ default:
+ break;
+ }
+#endif
+
+ return 0;
+};
+
+static bool _is_touch(Windows::UI::Input::PointerPoint ^pointerPoint) {
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ return true;
+#else
+ using namespace Windows::Devices::Input;
+ switch (pointerPoint->PointerDevice->PointerDeviceType) {
+ case PointerDeviceType::Touch:
+ case PointerDeviceType::Pen:
+ return true;
+ default:
+ return false;
+ }
+#endif
}
+
+static Windows::Foundation::Point _get_pixel_position(CoreWindow^ window, Windows::Foundation::Point rawPosition, OS* os) {
+
+ Windows::Foundation::Point outputPosition;
+
+ // Compute coordinates normalized from 0..1.
+ // If the coordinates need to be sized to the SDL window,
+ // we'll do that after.
+ #if 1 || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+ outputPosition.X = rawPosition.X / window->Bounds.Width;
+ outputPosition.Y = rawPosition.Y / window->Bounds.Height;
+ #else
+ switch (DisplayProperties::CurrentOrientation)
+ {
+ case DisplayOrientations::Portrait:
+ outputPosition.X = rawPosition.X / window->Bounds.Width;
+ outputPosition.Y = rawPosition.Y / window->Bounds.Height;
+ break;
+ case DisplayOrientations::PortraitFlipped:
+ outputPosition.X = 1.0f - (rawPosition.X / window->Bounds.Width);
+ outputPosition.Y = 1.0f - (rawPosition.Y / window->Bounds.Height);
+ break;
+ case DisplayOrientations::Landscape:
+ outputPosition.X = rawPosition.Y / window->Bounds.Height;
+ outputPosition.Y = 1.0f - (rawPosition.X / window->Bounds.Width);
+ break;
+ case DisplayOrientations::LandscapeFlipped:
+ outputPosition.X = 1.0f - (rawPosition.Y / window->Bounds.Height);
+ outputPosition.Y = rawPosition.X / window->Bounds.Width;
+ break;
+ default:
+ break;
+ }
+ #endif
+
+ OS::VideoMode vm = os->get_video_mode();
+ outputPosition.X *= vm.width;
+ outputPosition.Y *= vm.height;
+
+ return outputPosition;
+};
+
+static int _get_finger(uint32_t p_touch_id) {
+
+ return p_touch_id % 31; // for now
+};
+
+void App::pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed) {
+
+ Windows::UI::Input::PointerPoint ^point = args->CurrentPoint;
+ Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os);
+ int but = _get_button(point);
+ if (_is_touch(point)) {
+
+ InputEvent event;
+ event.type = InputEvent::SCREEN_TOUCH;
+ event.device = 0;
+ event.screen_touch.pressed = p_pressed;
+ event.screen_touch.x = pos.X;
+ event.screen_touch.y = pos.Y;
+ event.screen_touch.index = _get_finger(point->PointerId);
+
+ last_touch_x[event.screen_touch.index] = pos.X;
+ last_touch_y[event.screen_touch.index] = pos.Y;
+
+ os->input_event(event);
+ if (event.screen_touch.index != 0)
+ return;
+
+ }; // fallthrought of sorts
+
+ InputEvent event;
+ event.type = InputEvent::MOUSE_BUTTON;
+ event.device = 0;
+ event.mouse_button.pressed = p_pressed;
+ event.mouse_button.button_index = but;
+ event.mouse_button.x = pos.X;
+ event.mouse_button.y = pos.Y;
+ event.mouse_button.global_x = pos.X;
+ event.mouse_button.global_y = pos.Y;
+
+ last_touch_x[31] = pos.X;
+ last_touch_y[31] = pos.Y;
+
+ os->input_event(event);
+};
+
+
+void App::OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
+
+ pointer_event(sender, args, true);
+};
+
+
+void App::OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
+
+ pointer_event(sender, args, false);
+};
+
+void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
+
+ Windows::UI::Input::PointerPoint ^point = args->CurrentPoint;
+ Windows::Foundation::Point pos = _get_pixel_position(window, point->Position, os);
+
+ if (_is_touch(point)) {
+
+ InputEvent event;
+ event.type = InputEvent::SCREEN_DRAG;
+ event.device = 0;
+ event.screen_drag.x = pos.X;
+ event.screen_drag.y = pos.Y;
+ event.screen_drag.index = _get_finger(point->PointerId);
+ event.screen_drag.relative_x = event.screen_drag.x - last_touch_x[event.screen_drag.index];
+ event.screen_drag.relative_y = event.screen_drag.y - last_touch_y[event.screen_drag.index];
+
+ os->input_event(event);
+ if (event.screen_drag.index != 0)
+ return;
+
+ }; // fallthrought of sorts
+
+ InputEvent event;
+ event.type = InputEvent::MOUSE_MOTION;
+ event.device = 0;
+ event.mouse_motion.x = pos.X;
+ event.mouse_motion.y = pos.Y;
+ event.mouse_motion.global_x = pos.X;
+ event.mouse_motion.global_y = pos.Y;
+ event.mouse_motion.relative_x = pos.X - last_touch_x[31];
+ event.mouse_motion.relative_y = pos.Y - last_touch_y[31];
+
+ os->input_event(event);
+
+};
+
+
// Initializes scene resources
void App::Load(Platform::String^ entryPoint)
{
- char** args = {NULL};
- Main::setup("winrt", 0, args);
+ //char* args[] = {"-test", "render", NULL};
+ //Main::setup("winrt", 2, args);
}
// This method is called after the window becomes active.
void App::Run()
{
-
if (Main::start())
os->run();
}
@@ -147,16 +357,29 @@ void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ ar // On Windows Phone 8.1, the window size changes when the device is rotated.
// The default framebuffer will not be automatically resized when this occurs.
// It is therefore up to the app to handle rotation-specific logic in its rendering code.
+ //os->screen_size_changed();
+ UpdateWindowSize(args->Size);
#endif
}
void App::UpdateWindowSize(Size size)
{
- /*
- DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
- Size pixelSize(ConvertDipsToPixels(size.Width, currentDisplayInformation->LogicalDpi), ConvertDipsToPixels(size.Height, currentDisplayInformation->LogicalDpi));
-
+ float dpi;
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
+ DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
+ dpi = currentDisplayInformation->LogicalDpi;
+#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ dpi = DisplayProperties::LogicalDpi;
+#endif
+ Size pixelSize(ConvertDipsToPixels(size.Width, dpi), ConvertDipsToPixels(size.Height, dpi));
+
mWindowWidth = static_cast<GLsizei>(pixelSize.Width);
mWindowHeight = static_cast<GLsizei>(pixelSize.Height);
- */
+
+ OS::VideoMode vm;
+ vm.width = mWindowWidth;
+ vm.height = mWindowHeight;
+ vm.fullscreen = true;
+ vm.resizable = false;
+ os->set_video_mode(vm);
}
diff --git a/platform/winrt/app.h b/platform/winrt/app.h index a67b936cdf..7926465ff8 100644 --- a/platform/winrt/app.h +++ b/platform/winrt/app.h @@ -32,6 +32,12 @@ namespace $ext_safeprojectname$ void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
+ void pointer_event(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args, bool p_pressed);
+ void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
+ void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
+ void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
+
+
void UpdateWindowSize(Windows::Foundation::Size size);
void InitializeEGL(Windows::UI::Core::CoreWindow^ window);
void CleanupEGL();
@@ -44,8 +50,12 @@ namespace $ext_safeprojectname$ EGLDisplay mEglDisplay;
EGLContext mEglContext;
EGLSurface mEglSurface;
-
+
+ CoreWindow^ window;
OSWinrt* os;
- };
+
+ int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse
+ int last_touch_y[32];
+ };
}
diff --git a/platform/winrt/detect.py b/platform/winrt/detect.py index 00913b0ade..d97d974a19 100644 --- a/platform/winrt/detect.py +++ b/platform/winrt/detect.py @@ -3,6 +3,7 @@ import os
import sys
+import string
def is_active():
@@ -29,55 +30,127 @@ def get_flags(): def configure(env):
env.Append(CPPPATH=['#platform/winrt', '#platform/winrt/include'])
+ arch = ""
- env['OBJSUFFIX'] = ".rt" + env['OBJSUFFIX']
- env['LIBSUFFIX'] = ".rt" + env['LIBSUFFIX']
+ if os.getenv('PLATFORM') == "ARM":
- env.Append(LIBPATH=['#platform/winrt/x64/lib'])
+ # compiler commandline
+ # debug: /Yu"pch.h" /MP /GS /analyze- /W3 /wd"4453" /wd"28204" /Zc:wchar_t /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.WindowsPhone\" /I"Generated Files\" /I"ARM\Debug\" /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.Shared\" /ZW:nostdlib /Zi /Gm- /Od /sdl /Fd"ARM\Debug\vc120.pdb" /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /D "_DEBUG" /errorReport:prompt /WX- /Zc:forScope /RTC1 /ZW /Gd /Oy- /MDd /Fa"ARM\Debug\" /EHsc /nologo /Fo"ARM\Debug\" /Fp"ARM\Debug\App2.WindowsPhone.pch"
+ # release: /Yu"pch.h" /MP /GS /GL /analyze- /W3 /wd"4453" /wd"28204" /Gy /Zc:wchar_t /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.WindowsPhone\" /I"Generated Files\" /I"ARM\Release\" /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.Shared\" /ZW:nostdlib /Zi /Gm- /O2 /sdl /Fd"ARM\Release\vc120.pdb" /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /ZW /Gd /Oy- /Oi /MD /Fa"ARM\Release\" /EHsc /nologo /Fo"ARM\Release\" /Fp"ARM\Release\App2.WindowsPhone.pch"
- if (env["target"]=="release"):
+ # linker commandline
+ # debug: /OUT:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.exe" /MANIFEST:NO /NXCOMPAT /PDB:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.pdb" /DYNAMICBASE "WindowsPhoneCore.lib" "RuntimeObject.lib" "PhoneAppModelHost.lib" /DEBUG /MACHINE:ARM /NODEFAULTLIB:"kernel32.lib" /NODEFAULTLIB:"ole32.lib" /WINMD /APPCONTAINER /INCREMENTAL /PGD:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.pgd" /WINMDFILE:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.winmd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"ARM\Debug\App2.WindowsPhone.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
+ # release: /OUT:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.exe" /MANIFEST:NO /LTCG /NXCOMPAT /PDB:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.pdb" /DYNAMICBASE "WindowsPhoneCore.lib" "RuntimeObject.lib" "PhoneAppModelHost.lib" /DEBUG /MACHINE:ARM /NODEFAULTLIB:"kernel32.lib" /NODEFAULTLIB:"ole32.lib" /WINMD /APPCONTAINER /OPT:REF /PGD:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.pgd" /WINMDFILE:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.winmd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"ARM\Release\App2.WindowsPhone.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
- env.Append(CCFLAGS=['/O2'])
- env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
- env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
+ arch = "arm"
- elif (env["target"]=="test"):
+ env.Append(LINKFLAGS=['/INCREMENTAL:NO', '/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "WindowsPhoneCore.lib", "RuntimeObject.lib", "PhoneAppModelHost.lib", "/DEBUG", "/MACHINE:ARM", '/NODEFAULTLIB:"kernel32.lib"', '/NODEFAULTLIB:"ole32.lib"', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1'])
+ env.Append(LIBPATH=['#platform/winrt/ARM/lib'])
- env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
- env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+ env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /analyze- /Zc:wchar_t /Zi /Gm- /Od /fp:precise /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /DWINDOWSPHONE_ENABLED /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /RTC1 /Gd /EHsc /nologo'))
+ env.Append(CXXFLAGS=string.split('/ZW'))
- elif (env["target"]=="debug"):
+ if (env["target"]=="release"):
- env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO','/O1'])
- env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
- env.Append(LINKFLAGS=['/DEBUG'])
+ env.Append(CCFLAGS=['/O2'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
- elif (env["target"]=="profile"):
+ elif (env["target"]=="test"):
- env.Append(CCFLAGS=['-g','-pg'])
- env.Append(LINKFLAGS=['-pg'])
+ env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
- env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc'])
- env.Append(CXXFLAGS=['/TP', '/ZW'])
- env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
- #env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+ env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG'])
+
+ elif (env["target"]=="profile"):
+
+ env.Append(CCFLAGS=['-g','-pg'])
+ env.Append(LINKFLAGS=['-pg'])
+
+
+ env['ENV'] = os.environ;
+ # fix environment for windows phone 8.1
+ env['ENV']['WINDOWSPHONEKITDIR'] = env['ENV']['WINDOWSPHONEKITDIR'].replace("8.0", "8.1") # wtf
+ env['ENV']['INCLUDE'] = env['ENV']['INCLUDE'].replace("8.0", "8.1")
+ env['ENV']['LIB'] = env['ENV']['LIB'].replace("8.0", "8.1")
+ env['ENV']['PATH'] = env['ENV']['PATH'].replace("8.0", "8.1")
+ env['ENV']['LIBPATH'] = env['ENV']['LIBPATH'].replace("8.0\\Windows Metadata", "8.1\\References\\CommonConfiguration\\Neutral")
+
+ else:
+
+ arch = "x64"
+ env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "kernel32.lib", '/MACHINE:X64', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1'])
+
+ env.Append(LIBPATH=['#platform/winrt/x64/lib'])
+
+
+ if (env["target"]=="release"):
+
+ env.Append(CCFLAGS=['/O2'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
+ env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
+
+ elif (env["target"]=="test"):
+
+ env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+ env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG'])
+
+ elif (env["target"]=="profile"):
+
+ env.Append(CCFLAGS=['-g','-pg'])
+ env.Append(LINKFLAGS=['-pg'])
+
+
+ env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /Zc:wchar_t /Gm- /Od /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo'))
+ env.Append(CXXFLAGS=string.split('/ZW'))
+ env.Append(CCFLAGS=['/AI', os.environ['VCINSTALLDIR']+'\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR']+'\\References\\CommonConfiguration\\Neutral'])
+ env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000'])
+
+ env['ENV'] = os.environ;
+
+
+ env["PROGSUFFIX"]="."+arch+env["PROGSUFFIX"]
+ env["OBJSUFFIX"]="."+arch+env["OBJSUFFIX"]
+ env["LIBSUFFIX"]="."+arch+env["LIBSUFFIX"]
+
+
+ #env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc'])
+ #env.Append(CXXFLAGS=['/TP', '/ZW'])
+ #env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
+ ##env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
env.Append(CCFLAGS=['/DWINRT_ENABLED'])
env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
- env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000'])
env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
#env.Append(CCFLAGS=['/DWIN32'])
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
#env.Append(CCFLAGS=['/DGLES1_ENABLED'])
- env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32'])
-
+
+ LIBS=[
+ #'winmm',
+ 'libEGL',
+ 'libGLESv2',
+ 'libANGLE',
+ #'kernel32','ole32','user32', 'advapi32'
+ ]
+ env.Append(LINKFLAGS=[p+".lib" for p in LIBS])
+
import methods
env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
- env['ENV'] = os.environ;
-
+#/c/Program Files (x86)/Windows Phone Kits/8.1/lib/ARM/WindowsPhoneCore.lib
diff --git a/platform/winrt/gl_context_egl.cpp b/platform/winrt/gl_context_egl.cpp index ca592c5d19..fd9fbe406f 100644 --- a/platform/winrt/gl_context_egl.cpp +++ b/platform/winrt/gl_context_egl.cpp @@ -1,5 +1,7 @@ #include "gl_context_egl.h" +#include "EGL/eglext.h" + using namespace Platform; void ContextEGL::release_current() { @@ -22,6 +24,14 @@ int ContextEGL::get_window_height() { return height; }; +void ContextEGL::reset() { + + cleanup(); + + window = CoreWindow::GetForCurrentThread(); + initialize(); +}; + void ContextEGL::swap_buffers() { if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE) @@ -63,7 +73,23 @@ Error ContextEGL::initialize() { try { - display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + const EGLint displayAttributes[] = + { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, + EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, + EGL_NONE, + }; + + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT")); + + if (!eglGetPlatformDisplayEXT) + { + throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT"); + } + + display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes); + if (display == EGL_NO_DISPLAY) { throw Exception::CreateException(E_FAIL, L"Failed to get default EGL display"); diff --git a/platform/winrt/gl_context_egl.h b/platform/winrt/gl_context_egl.h index 56bf654ee5..ca3760e723 100644 --- a/platform/winrt/gl_context_egl.h +++ b/platform/winrt/gl_context_egl.h @@ -32,6 +32,7 @@ public: virtual void swap_buffers(); virtual Error initialize(); + void reset(); void cleanup(); diff --git a/platform/winrt/include/EGL/eglext.h b/platform/winrt/include/EGL/eglext.h index 9828628e75..459ecf4a3d 100644 --- a/platform/winrt/include/EGL/eglext.h +++ b/platform/winrt/include/EGL/eglext.h @@ -432,31 +432,38 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #define EGL_ANGLE_direct3d_display 1
#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
-#define EGL_D3D11_FL9_3_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-4)
#endif /* EGL_ANGLE_direct3d_display */
#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+#ifndef EGL_ANGLE_surface_d3d_render_to_back_buffer
+#define EGL_ANGLE_surface_d3d_render_to_back_buffer 1
+#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B
+#define EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER 0x320C
+#endif /* EGL_ANGLE_surface_d3d_render_to_back_buffer */
+
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
-#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205
#endif /* EGL_ANGLE_platform_angle */
#ifndef EGL_ANGLE_platform_angle_d3d
#define EGL_ANGLE_platform_angle_d3d 1
-#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
#endif /* EGL_ANGLE_platform_angle_d3d */
#ifndef EGL_ANGLE_platform_angle_opengl
#define EGL_ANGLE_platform_angle_opengl 1
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ARM_pixmap_multisample_discard
diff --git a/platform/winrt/include/EGL/eglplatform.h b/platform/winrt/include/EGL/eglplatform.h index d2e30bddbe..b0e88f94d4 100644 --- a/platform/winrt/include/EGL/eglplatform.h +++ b/platform/winrt/include/EGL/eglplatform.h @@ -76,12 +76,12 @@ typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
-#if defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeWindowType;
#else
typedef HWND EGLNativeWindowType;
-#endif // defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#endif
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
diff --git a/platform/winrt/include/GLSLANG/ShaderLang.h b/platform/winrt/include/GLSLANG/ShaderLang.h index 86bf221c90..d925b88f24 100644 --- a/platform/winrt/include/GLSLANG/ShaderLang.h +++ b/platform/winrt/include/GLSLANG/ShaderLang.h @@ -27,6 +27,10 @@ #include "KHR/khrplatform.h"
+#include <map>
+#include <string>
+#include <vector>
+
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
@@ -39,20 +43,20 @@ typedef unsigned int GLenum; }
// Must be included after GLenum proxy typedef
+// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
#include "ShaderVars.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
// Version number for shader translation API.
// It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 129
+#define ANGLE_SH_VERSION 132
typedef enum {
SH_GLES2_SPEC = 0x8B40,
SH_WEBGL_SPEC = 0x8B41,
+ SH_GLES3_SPEC = 0x8B86,
+ SH_WEBGL2_SPEC = 0x8B87,
+
// The CSS Shaders spec is a subset of the WebGL spec.
//
// In both CSS vertex and fragment shaders, ANGLE:
@@ -84,31 +88,6 @@ typedef enum { SH_HLSL11_OUTPUT = 0x8B48
} ShShaderOutput;
-typedef enum {
- SH_PRECISION_HIGHP = 0x5001,
- SH_PRECISION_MEDIUMP = 0x5002,
- SH_PRECISION_LOWP = 0x5003,
- SH_PRECISION_UNDEFINED = 0
-} ShPrecisionType;
-
-typedef enum {
- SH_INFO_LOG_LENGTH = 0x8B84,
- SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH
- SH_ACTIVE_UNIFORMS = 0x8B86,
- SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
- SH_ACTIVE_ATTRIBUTES = 0x8B89,
- SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
- SH_VARYINGS = 0x8BBB,
- SH_VARYING_MAX_LENGTH = 0x8BBC,
- SH_MAPPED_NAME_MAX_LENGTH = 0x6000,
- SH_NAME_MAX_LENGTH = 0x6001,
- SH_HASHED_NAME_MAX_LENGTH = 0x6002,
- SH_HASHED_NAMES_COUNT = 0x6003,
- SH_SHADER_VERSION = 0x6004,
- SH_RESOURCES_STRING_LENGTH = 0x6005,
- SH_OUTPUT_TYPE = 0x6006
-} ShShaderInfo;
-
// Compile options.
typedef enum {
SH_VALIDATE = 0,
@@ -188,6 +167,11 @@ typedef enum { // This flag scalarizes vec/ivec/bvec/mat constructor args.
// It is intended as a workaround for Linux/Mac driver bugs.
SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000,
+
+ // This flag overwrites a struct name with a unique prefix.
+ // It is intended as a workaround for drivers that do not handle
+ // struct scopes correctly, including all Mac drivers and Linux AMD.
+ SH_REGENERATE_STRUCT_NAMES = 0x80000,
} ShCompileOptions;
// Defines alternate strategies for implementing array index clamping.
@@ -202,14 +186,14 @@ typedef enum { //
// Driver must call this first, once, before doing any other
// compiler operations.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
//
-COMPILER_EXPORT int ShInitialize();
+COMPILER_EXPORT bool ShInitialize();
//
// Driver should call this at shutdown.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
//
-COMPILER_EXPORT int ShFinalize();
+COMPILER_EXPORT bool ShFinalize();
// The 64 bits hash function. The first parameter is the input string; the
// second parameter is the string length.
@@ -240,6 +224,12 @@ typedef struct int EXT_frag_depth;
int EXT_shader_texture_lod;
+ // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
+ // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
+ // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
+ // function. This applies to Tegra K1 devices.
+ int NV_draw_buffers;
+
// Set to 1 if highp precision is supported in the fragment language.
// Default is 0.
int FragmentPrecisionHigh;
@@ -268,8 +258,10 @@ typedef struct //
// Initialize built-in resources with minimum expected values.
+// Parameters:
+// resources: The object to initialize. Will be comparable with memcmp.
//
-COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
+COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
//
// ShHandle held by but opaque to the driver. It is allocated,
@@ -278,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); //
// If handle creation fails, 0 will be returned.
//
-typedef void* ShHandle;
+typedef void *ShHandle;
//
-// Returns the a concatenated list of the items in ShBuiltInResources as a string.
+// Returns the a concatenated list of the items in ShBuiltInResources as a
+// null-terminated string.
// This function must be updated whenever ShBuiltInResources is changed.
// Parameters:
// handle: Specifies the handle of the compiler to be used.
-// outStringLen: Specifies the size of the buffer, in number of characters. The size
-// of the buffer required to store the resources string can be obtained
-// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH.
-// outStr: Returns a null-terminated string representing all the built-in resources.
-COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr);
+COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
//
// Driver calls these to create and destroy compiler objects.
@@ -307,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler( sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
- const ShBuiltInResources* resources);
+ const ShBuiltInResources *resources);
COMPILER_EXPORT void ShDestruct(ShHandle handle);
//
// Compiles the given shader source.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
// Parameters:
// handle: Specifies the handle of compiler to be used.
// shaderStrings: Specifies an array of pointers to null-terminated strings
@@ -334,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle); // SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
-COMPILER_EXPORT int ShCompile(
+COMPILER_EXPORT bool ShCompile(
const ShHandle handle,
- const char* const shaderStrings[],
+ const char * const shaderStrings[],
size_t numStrings,
- int compileOptions
- );
+ int compileOptions);
-// Returns a parameter from a compiled shader.
-// Parameters:
-// handle: Specifies the compiler
-// pname: Specifies the parameter to query.
-// The following parameters are defined:
-// SH_INFO_LOG_LENGTH: the number of characters in the information log
-// including the null termination character.
-// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
-// including the null termination character.
-// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
-// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
-// variable name including the null
-// termination character.
-// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
-// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
-// variable name including the null
-// termination character.
-// SH_VARYINGS: the number of varying variables.
-// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
-// including the null termination character.
-// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
-// the null termination character.
-// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
-// null termination character.
-// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the
-// null termination character.
-// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile.
-// SH_SHADER_VERSION: the version of the shader language
-// SH_OUTPUT_TYPE: the currently set language output type
-//
-// params: Requested parameter
-COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
- ShShaderInfo pname,
- size_t* params);
+// Return the version of the shader language.
+COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
-// Returns nul-terminated information log for a compiled shader.
+// Return the currently set language output type.
+COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType(
+ const ShHandle handle);
+
+// Returns null-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
-// infoLog: Specifies an array of characters that is used to return
-// the information log. It is assumed that infoLog has enough memory
-// to accomodate the information log. The size of the buffer required
-// to store the returned information log can be obtained by calling
-// ShGetInfo with SH_INFO_LOG_LENGTH.
-COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
+COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle);
// Returns null-terminated object code for a compiled shader.
// Parameters:
// handle: Specifies the compiler
-// infoLog: Specifies an array of characters that is used to return
-// the object code. It is assumed that infoLog has enough memory to
-// accomodate the object code. The size of the buffer required to
-// store the returned object code can be obtained by calling
-// ShGetInfo with SH_OBJECT_CODE_LENGTH.
-COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
-
-// Returns information about a shader variable.
-// Parameters:
-// handle: Specifies the compiler
-// variableType: Specifies the variable type; options include
-// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
-// index: Specifies the index of the variable to be queried.
-// length: Returns the number of characters actually written in the string
-// indicated by name (excluding the null terminator) if a value other
-// than NULL is passed.
-// size: Returns the size of the variable.
-// type: Returns the data type of the variable.
-// precision: Returns the precision of the variable.
-// staticUse: Returns 1 if the variable is accessed in a statement after
-// pre-processing, whether or not run-time flow of control will
-// cause that statement to be executed.
-// Returns 0 otherwise.
-// name: Returns a null terminated string containing the name of the
-// variable. It is assumed that name has enough memory to accormodate
-// the variable name. The size of the buffer required to store the
-// variable name can be obtained by calling ShGetInfo with
-// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
-// SH_VARYING_MAX_LENGTH.
-// mappedName: Returns a null terminated string containing the mapped name of
-// the variable, It is assumed that mappedName has enough memory
-// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
-// mapped name. If the name is not mapped, then name and mappedName
-// are the same.
-COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
- ShShaderInfo variableType,
- int index,
- size_t* length,
- int* size,
- sh::GLenum* type,
- ShPrecisionType* precision,
- int* staticUse,
- char* name,
- char* mappedName);
-
-// Returns information about a name hashing entry from the latest compile.
+COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle);
+
+// Returns a (original_name, hash) map containing all the user defined
+// names in the shader, including variable names, function names, struct
+// names, and struct field names.
// Parameters:
// handle: Specifies the compiler
-// index: Specifies the index of the name hashing entry to be queried.
-// name: Returns a null terminated string containing the user defined name.
-// It is assumed that name has enough memory to accomodate the name.
-// The size of the buffer required to store the user defined name can
-// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH.
-// hashedName: Returns a null terminated string containing the hashed name of
-// the uniform variable, It is assumed that hashedName has enough
-// memory to accomodate the name. The size of the buffer required
-// to store the name can be obtained by calling ShGetInfo with
-// SH_HASHED_NAME_MAX_LENGTH.
-COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle,
- int index,
- char* name,
- char* hashedName);
+COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
+ const ShHandle handle);
// Shader variable inspection.
// Returns a pointer to a list of variables of the designated type.
@@ -470,17 +372,17 @@ typedef struct int size;
} ShVariableInfo;
-// Returns 1 if the passed in variables pack in maxVectors following
+// Returns true if the passed in variables pack in maxVectors following
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
-// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
+// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// flag above.
// Parameters:
// maxVectors: the available rows of registers.
// varInfoArray: an array of variable info (types and sizes).
// varInfoArraySize: the size of the variable array.
-COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
+COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits(
int maxVectors,
- ShVariableInfo* varInfoArray,
+ ShVariableInfo *varInfoArray,
size_t varInfoArraySize);
// Gives the compiler-assigned register for an interface block.
@@ -491,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( // interfaceBlockName: Specifies the interface block
// indexOut: output variable that stores the assigned register
COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
- const char *interfaceBlockName,
+ const std::string &interfaceBlockName,
unsigned int *indexOut);
// Gives the compiler-assigned register for uniforms in the default
@@ -503,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, // interfaceBlockName: Specifies the uniform
// indexOut: output variable that stores the assigned register
COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
- const char *uniformName,
+ const std::string &uniformName,
unsigned int *indexOut);
-#ifdef __cplusplus
-}
-#endif
-
#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/platform/winrt/include/GLSLANG/ShaderVars.h b/platform/winrt/include/GLSLANG/ShaderVars.h index 03ddf956f1..dc452b0cf4 100644 --- a/platform/winrt/include/GLSLANG/ShaderVars.h +++ b/platform/winrt/include/GLSLANG/ShaderVars.h @@ -15,6 +15,7 @@ #include <algorithm>
// Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum
+// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
namespace sh
{
@@ -39,7 +40,7 @@ enum BlockLayoutType // Note: we must override the copy constructor and assignment operator so we can
// work around excessive GCC binary bloating:
// See https://code.google.com/p/angleproject/issues/detail?id=697
-struct ShaderVariable
+struct COMPILER_EXPORT ShaderVariable
{
ShaderVariable();
ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
@@ -49,6 +50,22 @@ struct ShaderVariable bool isArray() const { return arraySize > 0; }
unsigned int elementCount() const { return std::max(1u, arraySize); }
+ bool isStruct() const { return !fields.empty(); }
+
+ // All of the shader's variables are described using nested data
+ // structures. This is needed in order to disambiguate similar looking
+ // types, such as two structs containing the same fields, but in
+ // different orders. "findInfoByMappedName" provides an easy query for
+ // users to dive into the data structure and fetch the unique variable
+ // instance corresponding to a dereferencing chain of the top-level
+ // variable.
+ // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
+ // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
+ // in |originalName|, based on the assumption that |this| defines 'a'.
+ // If no match is found, return false.
+ bool findInfoByMappedName(const std::string &mappedFullName,
+ const ShaderVariable **leafVar,
+ std::string* originalFullName) const;
GLenum type;
GLenum precision;
@@ -56,58 +73,97 @@ struct ShaderVariable std::string mappedName;
unsigned int arraySize;
bool staticUse;
+ std::vector<ShaderVariable> fields;
+ std::string structName;
+
+ protected:
+ bool isSameVariableAtLinkTime(const ShaderVariable &other,
+ bool matchPrecision) const;
+
+ bool operator==(const ShaderVariable &other) const;
+ bool operator!=(const ShaderVariable &other) const
+ {
+ return !operator==(other);
+ }
};
-struct Uniform : public ShaderVariable
+struct COMPILER_EXPORT Uniform : public ShaderVariable
{
Uniform();
~Uniform();
Uniform(const Uniform &other);
Uniform &operator=(const Uniform &other);
-
- bool isStruct() const { return !fields.empty(); }
-
- std::vector<Uniform> fields;
+ bool operator==(const Uniform &other) const;
+ bool operator!=(const Uniform &other) const
+ {
+ return !operator==(other);
+ }
+
+ // Decide whether two uniforms are the same at shader link time,
+ // assuming one from vertex shader and the other from fragment shader.
+ // See GLSL ES Spec 3.00.3, sec 4.3.5.
+ bool isSameUniformAtLinkTime(const Uniform &other) const;
};
-struct Attribute : public ShaderVariable
+struct COMPILER_EXPORT Attribute : public ShaderVariable
{
Attribute();
~Attribute();
Attribute(const Attribute &other);
Attribute &operator=(const Attribute &other);
+ bool operator==(const Attribute &other) const;
+ bool operator!=(const Attribute &other) const
+ {
+ return !operator==(other);
+ }
int location;
};
-struct InterfaceBlockField : public ShaderVariable
+struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
{
InterfaceBlockField();
~InterfaceBlockField();
InterfaceBlockField(const InterfaceBlockField &other);
InterfaceBlockField &operator=(const InterfaceBlockField &other);
+ bool operator==(const InterfaceBlockField &other) const;
+ bool operator!=(const InterfaceBlockField &other) const
+ {
+ return !operator==(other);
+ }
+
+ // Decide whether two InterfaceBlock fields are the same at shader
+ // link time, assuming one from vertex shader and the other from
+ // fragment shader.
+ // See GLSL ES Spec 3.00.3, sec 4.3.7.
+ bool isSameInterfaceBlockFieldAtLinkTime(
+ const InterfaceBlockField &other) const;
- bool isStruct() const { return !fields.empty(); }
-
- bool isRowMajorMatrix;
- std::vector<InterfaceBlockField> fields;
+ bool isRowMajorLayout;
};
-struct Varying : public ShaderVariable
+struct COMPILER_EXPORT Varying : public ShaderVariable
{
Varying();
~Varying();
- Varying(const Varying &other);
+ Varying(const Varying &otherg);
Varying &operator=(const Varying &other);
+ bool operator==(const Varying &other) const;
+ bool operator!=(const Varying &other) const
+ {
+ return !operator==(other);
+ }
- bool isStruct() const { return !fields.empty(); }
+ // Decide whether two varyings are the same at shader link time,
+ // assuming one from vertex shader and the other from fragment shader.
+ // See GLSL ES Spec 3.00.3, sec 4.3.9.
+ bool isSameVaryingAtLinkTime(const Varying &other) const;
InterpolationType interpolation;
- std::vector<Varying> fields;
- std::string structName;
+ bool isInvariant;
};
-struct InterfaceBlock
+struct COMPILER_EXPORT InterfaceBlock
{
InterfaceBlock();
~InterfaceBlock();
@@ -116,6 +172,7 @@ struct InterfaceBlock std::string name;
std::string mappedName;
+ std::string instanceName;
unsigned int arraySize;
BlockLayoutType layout;
bool isRowMajorLayout;
diff --git a/platform/winrt/include/angle_windowsstore.h b/platform/winrt/include/angle_windowsstore.h new file mode 100644 index 0000000000..fe587bf269 --- /dev/null +++ b/platform/winrt/include/angle_windowsstore.h @@ -0,0 +1,37 @@ +//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_windowsstore.h:
+
+#ifndef ANGLE_WINDOWSSTORE_H_
+#define ANGLE_WINDOWSSTORE_H_
+
+// The following properties can be set on the CoreApplication to support additional
+// ANGLE configuration options.
+//
+// The Visual Studio sample templates provided with this version of ANGLE have examples
+// of how to set these property values.
+
+//
+// Property: EGLNativeWindowTypeProperty
+// Type: IInspectable
+// Description: Set this property to specify the window type to use for creating a surface.
+// If this property is missing, surface creation will fail.
+//
+const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
+
+//
+// Property: EGLRenderSurfaceSizeProperty
+// Type: Size
+// Description: Set this property to specify a preferred size in pixels of the render surface.
+// The render surface size width and height must be greater than 0.
+// If this property is set, then the render surface size is fixed.
+// If this property is missing, a default behavior will be provided.
+// The default behavior uses the window size if a CoreWindow is specified or
+// the size of the SwapChainPanel control if one is specified.
+//
+const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
+
+#endif // ANGLE_WINDOWSSTORE_H_
diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp index 99c4ad968e..21a77b89cb 100644 --- a/platform/winrt/os_winrt.cpp +++ b/platform/winrt/os_winrt.cpp @@ -27,7 +27,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles1/rasterizer_gles1.h" #include "os_winrt.h" #include "drivers/nedmalloc/memory_pool_static_nedmalloc.h" #include "drivers/unix/memory_pool_static_malloc.h" @@ -62,16 +61,16 @@ using namespace Microsoft::WRL; int OSWinrt::get_video_driver_count() const { - return 2; + return 1; } const char * OSWinrt::get_video_driver_name(int p_driver) const { - return p_driver==0?"GLES2":"GLES1"; + return "GLES2"; } OS::VideoMode OSWinrt::get_default_video_mode() const { - return VideoMode(800,600,false); + return video_mode; } int OSWinrt::get_audio_driver_count() const { @@ -142,12 +141,27 @@ void OSWinrt::set_gl_context(ContextEGL* p_context) { gl_context = p_context; }; +void OSWinrt::screen_size_changed() { + + gl_context->reset(); +}; + void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { main_loop=NULL; outside=true; gl_context->initialize(); + VideoMode vm; + vm.width = gl_context->get_window_width(); + vm.height = gl_context->get_window_height(); + vm.fullscreen = true; + vm.resizable = false; + + set_video_mode(vm); + + gl_context->make_current(); + rasterizer = memnew( RasterizerGLES2 ); visual_server = memnew( VisualServerRaster(rasterizer) ); if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) { @@ -270,6 +284,11 @@ String OSWinrt::get_clipboard() const { }; +void OSWinrt::input_event(InputEvent &p_event) { + p_event.ID = ++last_id; + input->parse_input_event(p_event); +}; + void OSWinrt::delete_main_loop() { if (main_loop) @@ -392,7 +411,7 @@ void OSWinrt::set_window_title(const String& p_title) { void OSWinrt::set_video_mode(const VideoMode& p_video_mode,int p_screen) { - + video_mode = p_video_mode; } OS::VideoMode OSWinrt::get_video_mode(int p_screen) const { @@ -512,7 +531,7 @@ Error OSWinrt::kill(const ProcessID& p_pid) { Error OSWinrt::set_cwd(const String& p_cwd) { - return OK; + return FAILED; } String OSWinrt::get_executable_path() const { @@ -553,8 +572,12 @@ Error OSWinrt::shell_open(String p_uri) { String OSWinrt::get_locale() const { +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // this should work on phone 8.1, but it doesn't + return "en"; +#else Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag; return language->Data(); +#endif } void OSWinrt::release_rendering_thread() { @@ -634,6 +657,7 @@ OSWinrt::OSWinrt() { gl_context = NULL; + AudioDriverManagerSW::add_driver(&audio_driver); } diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h index c309239af1..68236309a9 100644 --- a/platform/winrt/os_winrt.h +++ b/platform/winrt/os_winrt.h @@ -40,6 +40,7 @@ #include "servers/spatial_sound/spatial_sound_server_sw.h" #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/audio/audio_driver_dummy.h" #include "gl_context_egl.h" @@ -124,6 +125,7 @@ class OSWinrt : public OS { MainLoop *main_loop; + AudioDriverDummy audio_driver; AudioServerSW *audio_server; SampleManagerMallocSW *sample_manager; SpatialSoundServerSW *spatial_sound_server; @@ -226,17 +228,22 @@ public: virtual String get_data_dir() const; void set_gl_context(ContextEGL* p_context); + void screen_size_changed(); virtual void release_rendering_thread(); virtual void make_rendering_thread(); virtual void swap_buffers(); + virtual bool has_touchscreen_ui_hint() const { return true; }; + virtual Error shell_open(String p_uri); void run(); virtual bool get_swap_ok_cancel() { return true; } + void input_event(InputEvent &p_event); + OSWinrt(); ~OSWinrt(); diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 8616a20486..b0876d7fc6 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -38,6 +38,11 @@ def can_build(): if (x11_error): print("xcursor not found.. x11 disabled.") return False + + x11_error=os.system("pkg-config xinerama --modversion > /dev/null ") + if (x11_error): + print("xinerama not found.. x11 disabled.") + return False return True # X11 enabled @@ -47,6 +52,8 @@ def get_opts(): return [ ('use_llvm','Use llvm compiler','no'), ('use_sanitizer','Use llvm compiler sanitize address','no'), + ('pulseaudio','Detect & Use pulseaudio','yes'), + ('new_wm_api', 'Use experimental window management API','no'), ] def get_flags(): @@ -54,6 +61,7 @@ def get_flags(): return [ ('builtin_zlib', 'no'), ("openssl", "yes"), + ("theora","no"), ] @@ -68,17 +76,23 @@ def configure(env): else: env["bits"]="32" - env.Append(CPPPATH=['#platform/x11']) if (env["use_llvm"]=="yes"): - env["CC"]="clang" - env["CXX"]="clang++" - env["LD"]="clang++" - if (env["use_sanitizer"]=="yes"): - env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) - env.Append(LINKFLAGS=['-fsanitize=address']) + if 'clang++' not in env['CXX']: + env["CC"]="clang" + env["CXX"]="clang++" + env["LD"]="clang++" + env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) + env.extra_suffix=".llvm" + if (env["colored"]=="yes"): + if sys.stdout.isatty(): + env.Append(CXXFLAGS=["-fcolor-diagnostics"]) + if (env["use_sanitizer"]=="yes"): + env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) + env.Append(LINKFLAGS=['-fsanitize=address']) + env.extra_suffix+="s" #if (env["tools"]=="no"): # #no tools suffix @@ -99,6 +113,7 @@ def configure(env): env.Append(CCFLAGS=['-g2', '-Wall','-DDEBUG_ENABLED','-DDEBUG_MEMORY_ENABLED']) env.ParseConfig('pkg-config x11 --cflags --libs') + env.ParseConfig('pkg-config xinerama --cflags --libs') env.ParseConfig('pkg-config xcursor --cflags --libs') env.ParseConfig('pkg-config openssl --cflags --libs') @@ -109,7 +124,16 @@ def configure(env): env.Append(CPPFLAGS=['-DOPENGL_ENABLED','-DGLEW_ENABLED']) env.Append(CPPFLAGS=["-DALSA_ENABLED"]) - env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLES_OVER_GL']) + + if (env["pulseaudio"]=="yes"): + if not os.system("pkg-config --exists libpulse-simple"): + print("Enabling PulseAudio") + env.Append(CPPFLAGS=["-DPULSEAUDIO_ENABLED"]) + env.ParseConfig('pkg-config --cflags --libs libpulse-simple') + else: + print("PulseAudio development libraries not found, disabling driver") + + env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_ENABLED','-DGLES_OVER_GL']) env.Append(LIBS=['GL', 'GLU', 'pthread','asound','z']) #TODO detect linux/BSD! #env.Append(CPPFLAGS=['-DMPC_FIXED_POINT']) @@ -118,16 +142,11 @@ def configure(env): if (is64 and env["bits"]=="32"): env.Append(CPPFLAGS=['-m32']) env.Append(LINKFLAGS=['-m32','-L/usr/lib/i386-linux-gnu']) - elif (not is64 and env["bits"]=="32"): + elif (not is64 and env["bits"]=="64"): env.Append(CPPFLAGS=['-m64']) env.Append(LINKFLAGS=['-m64','-L/usr/lib/i686-linux-gnu']) - if (env["CXX"]=="clang++"): - env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) - env["CC"]="clang" - env["LD"]="clang++" - import methods env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) @@ -135,3 +154,7 @@ def configure(env): env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) #env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } ) + if(env["new_wm_api"]=="yes"): + env.Append(CPPFLAGS=['-DNEW_WM_API']) + env.ParseConfig('pkg-config xinerama --cflags --libs') + diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp index b17b92bccf..bed57fbe9f 100644 --- a/platform/x11/export/export.cpp +++ b/platform/x11/export/export.cpp @@ -11,7 +11,7 @@ void register_x11_exporter() { { Ref<EditorExportPlatformPC> exporter = Ref<EditorExportPlatformPC>( memnew(EditorExportPlatformPC) ); - exporter->set_binary_extension("bin"); + exporter->set_binary_extension(""); exporter->set_release_binary32("linux_x11_32_release"); exporter->set_debug_binary32("linux_x11_32_debug"); exporter->set_release_binary64("linux_x11_64_release"); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 4c45fcfaaf..92b0abff37 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -28,7 +28,6 @@ /*************************************************************************/ #include "servers/visual/visual_server_raster.h" #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles1/rasterizer_gles1.h" #include "os_x11.h" #include "key_mapping_x11.h" #include <stdio.h> @@ -37,6 +36,17 @@ #include "servers/physics/physics_server_sw.h" #include "X11/Xutil.h" + +#include "X11/Xatom.h" +#include "X11/extensions/Xinerama.h" +// ICCCM +#define WM_NormalState 1L // window normal state +#define WM_IconicState 3L // window minimized +// EWMH +#define _NET_WM_STATE_REMOVE 0L // remove/unset property +#define _NET_WM_STATE_ADD 1L // add/set property +#define _NET_WM_STATE_TOGGLE 2L // toggle property + #include "main/main.h" @@ -57,23 +67,35 @@ #include <X11/Xatom.h> -#include "os/pc_joystick_map.h" +//#include "os/pc_joystick_map.h" #undef CursorShape int OS_X11::get_video_driver_count() const { - return 2; + return 1; } const char * OS_X11::get_video_driver_name(int p_driver) const { - return p_driver==0?"GLES2":"GLES1"; + return "GLES2"; } OS::VideoMode OS_X11::get_default_video_mode() const { return OS::VideoMode(800,600,false); } +int OS_X11::get_audio_driver_count() const { + + return AudioDriverManagerSW::get_driver_count(); +} + +const char *OS_X11::get_audio_driver_name(int p_driver) const { + + AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver); + ERR_FAIL_COND_V( !driver, "" ); + return AudioDriverManagerSW::get_driver(p_driver)->get_name(); +} + void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { last_button_state=0; @@ -106,10 +128,10 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi if (xim == NULL) { WARN_PRINT("XOpenIM failed"); - xim_style=NULL; + xim_style=0L; } else { ::XIMStyles *xim_styles=NULL; - xim_style=0; + xim_style=0L; char *imvalret=NULL; imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); if (imvalret != NULL || xim_styles == NULL) { @@ -117,7 +139,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi } if (xim_styles) { - xim_style = 0; + xim_style = 0L; for (int i=0;i<xim_styles->count_styles;i++) { if (xim_styles->supported_styles[i] == @@ -151,14 +173,11 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // maybe contextgl wants to be in charge of creating the window //print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height)); #if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) + context_gl = memnew( ContextGL_X11( x11_display, x11_window,current_videomode, false ) ); context_gl->initialize(); - if (p_video_driver == 0) { - rasterizer = memnew( RasterizerGLES2 ); - } else { - rasterizer = memnew( RasterizerGLES1 ); - }; + rasterizer = memnew( RasterizerGLES2 ); #endif visual_server = memnew( VisualServerRaster(rasterizer) ); @@ -168,9 +187,11 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD)); } +#if 1 + // NEW_WM_API // borderless fullscreen window mode if (current_videomode.fullscreen) { - // needed for lxde/openbox, possibly others + // needed for lxde/openbox, possibly others Hints hints; Atom property; hints.flags = 2; @@ -199,7 +220,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); } - // disable resizeable window + // disable resizable window if (!current_videomode.resizable) { XSizeHints *xsh; xsh = XAllocSizeHints(); @@ -215,7 +236,25 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi xsh->min_height = xwa.height; xsh->max_height = xwa.height; XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); + } +#else + capture_idle = 0; + minimized = false; + maximized = false; + + if (current_videomode.fullscreen) { + //set_wm_border(false); + set_wm_fullscreen(true); } + if (!current_videomode.resizable) { + int screen = get_current_screen(); + Size2i screen_size = get_screen_size(screen); + set_window_size(screen_size); + set_window_resizable(false); + } +#endif + AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); @@ -253,19 +292,19 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XChangeWindowAttributes(x11_display, x11_window,CWEventMask,&new_attr); - XClassHint* classHint; + XClassHint* classHint; - /* set the titlebar name */ - XStoreName(x11_display, x11_window, "Godot"); + /* set the titlebar name */ + XStoreName(x11_display, x11_window, "Godot"); - /* set the name and class hints for the window manager to use */ - classHint = XAllocClassHint(); - if (classHint) { - classHint->res_name = "Godot"; - classHint->res_class = "Godot"; - } - XSetClassHint(x11_display, x11_window, classHint); - XFree(classHint); + /* set the name and class hints for the window manager to use */ + classHint = XAllocClassHint(); + if (classHint) { + classHint->res_name = "Godot"; + classHint->res_class = "Godot"; + } + XSetClassHint(x11_display, x11_window, classHint); + XFree(classHint); wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); XSetWMProtocols(x11_display, x11_window, &wm_delete, 1); @@ -457,8 +496,9 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { center.y = current_videomode.height/2; XWarpPointer(x11_display, None, x11_window, 0,0,0,0, (int)center.x, (int)center.y); - } + input->set_mouse_pos(center); + } } void OS_X11::warp_mouse_pos(const Point2& p_to) { @@ -468,8 +508,12 @@ void OS_X11::warp_mouse_pos(const Point2& p_to) { last_mouse_pos=p_to; } else { + /*XWindowAttributes xwa; + XGetWindowAttributes(x11_display, x11_window, &xwa); + printf("%d %d\n", xwa.x, xwa.y); needed? */ + XWarpPointer(x11_display, None, x11_window, - 0,0,0,0, (int)p_to.x, (int)p_to.y); + 0,0,0,0, (int)p_to.x , (int)p_to.y); } } @@ -482,7 +526,6 @@ OS::MouseMode OS_X11::get_mouse_mode() const { int OS_X11::get_mouse_button_state() const { - return last_button_state; } @@ -509,6 +552,344 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons } +//#ifdef NEW_WM_API +#if 0 +// Just now not needed. Can be used for a possible OS.set_border(bool) method +void OS_X11::set_wm_border(bool p_enabled) { + // needed for lxde/openbox, possibly others + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = p_enabled ? 1L : 0L; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + XMapRaised(x11_display, x11_window); + //XMoveResizeWindow(x11_display, x11_window, 0, 0, 800, 800); +} +#endif + +void OS_X11::set_wm_fullscreen(bool p_enabled) { + // Using EWMH -- Extened Window Manager Hints + XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = wm_fullscreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +int OS_X11::get_screen_count() const { + // Using Xinerama Extension + int event_base, error_base; + const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); + if( !ext_okay ) return 0; + + int count; + XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); + XFree(xsi); + return count; +} + +int OS_X11::get_current_screen() const { + int x,y; + Window child; + XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + + int count = get_screen_count(); + for(int i=0; i<count; i++) { + Point2i pos = get_screen_position(i); + Size2i size = get_screen_size(i); + if( (x >= pos.x && x <pos.x + size.width) && (y >= pos.y && y < pos.y + size.height) ) + return i; + } + return 0; +} + +void OS_X11::set_current_screen(int p_screen) { + int count = get_screen_count(); + if(p_screen >= count) return; + + if( current_videomode.fullscreen ) { + Point2i position = get_screen_position(p_screen); + Size2i size = get_screen_size(p_screen); + + XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y); + } + else { + if( p_screen != get_current_screen() ) { + Point2i position = get_screen_position(p_screen); + XMoveWindow(x11_display, x11_window, position.x, position.y); + } + } +} + +Point2 OS_X11::get_screen_position(int p_screen) const { + // Using Xinerama Extension + int event_base, error_base; + const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); + if( !ext_okay ) return Point2i(0,0); + + int count; + XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); + if( p_screen >= count ) return Point2i(0,0); + + Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org); + XFree(xsi); + return position; +} + +Size2 OS_X11::get_screen_size(int p_screen) const { + // Using Xinerama Extension + int event_base, error_base; + const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); + if( !ext_okay ) return Size2i(0,0); + + int count; + XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); + if( p_screen >= count ) return Size2i(0,0); + + Size2i size = Point2i(xsi[p_screen].width, xsi[p_screen].height); + XFree(xsi); + return size; +} + + +Point2 OS_X11::get_window_position() const { + int x,y; + Window child; + XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + + int screen = get_current_screen(); + Point2i screen_position = get_screen_position(screen); + + return Point2i(x-screen_position.x, y-screen_position.y); +} + +void OS_X11::set_window_position(const Point2& p_position) { + // Using EWMH -- Extended Window Manager Hints + // to get the size of the decoration + Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + int result; + + result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 32, + False, + AnyPropertyType, + &type, + &format, + &len, + &remaining, + &data + ); + + long left = 0L; + long top = 0L; + + if( result == Success ) { + long *extends = (long *) data; + + left = extends[0]; + top = extends[2]; + + XFree(data); + } + + int screen = get_current_screen(); + Point2i screen_position = get_screen_position(screen); + + left -= screen_position.x; + top -= screen_position.y; + + XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top); +} + +Size2 OS_X11::get_window_size() const { + XWindowAttributes xwa; + XGetWindowAttributes(x11_display, x11_window, &xwa); + return Size2i(xwa.width, xwa.height); +} + +void OS_X11::set_window_size(const Size2 p_size) { + XResizeWindow(x11_display, x11_window, p_size.x, p_size.y); +} + +void OS_X11::set_window_fullscreen(bool p_enabled) { + set_wm_fullscreen(p_enabled); + current_videomode.fullscreen = p_enabled; + + visual_server->init(); +} + +bool OS_X11::is_window_fullscreen() const { + return current_videomode.fullscreen; +} + +void OS_X11::set_window_resizable(bool p_enabled) { + XSizeHints *xsh; + xsh = XAllocSizeHints(); + xsh->flags = p_enabled ? 0L : PMinSize | PMaxSize; + if(!p_enabled) { + XWindowAttributes xwa; + XGetWindowAttributes(x11_display,x11_window,&xwa); + xsh->min_width = xwa.width; + xsh->max_width = xwa.width; + xsh->min_height = xwa.height; + xsh->max_height = xwa.height; + } + XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); + current_videomode.resizable = p_enabled; +} + +bool OS_X11::is_window_resizable() const { + return current_videomode.resizable; +} + +void OS_X11::set_window_minimized(bool p_enabled) { + // Using ICCCM -- Inter-Client Communication Conventions Manual + XEvent xev; + Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_change; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + //XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + xev.xclient.data.l[1] = wm_hidden; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +bool OS_X11::is_window_minimized() const { + // Using ICCCM -- Inter-Client Communication Conventions Manual + Atom property = XInternAtom(x11_display,"WM_STATE", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 32, + False, + AnyPropertyType, + &type, + &format, + &len, + &remaining, + &data + ); + + if( result == Success ) { + long *state = (long *) data; + if( state[0] == WM_IconicState ) + return true; + } + return false; +} + +void OS_X11::set_window_maximized(bool p_enabled) { + // Using EWMH -- Extended Window Manager Hints + XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = wm_max_horz; + xev.xclient.data.l[2] = wm_max_vert; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + maximized = p_enabled; +} + +bool OS_X11::is_window_maximized() const { + // Using EWMH -- Extended Window Manager Hints + Atom property = XInternAtom(x11_display,"_NET_WM_STATE",False ); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 1024, + False, + XA_ATOM, + &type, + &format, + &len, + &remaining, + &data + ); + + if(result == Success) { + Atom *atoms = (Atom*) data; + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + bool found_wm_max_horz = false; + bool found_wm_max_vert = false; + + for( unsigned int i=0; i < len; i++ ) { + if( atoms[i] == wm_max_horz ) + found_wm_max_horz = true; + if( atoms[i] == wm_max_vert ) + found_wm_max_vert = true; + + if( found_wm_max_horz && found_wm_max_vert ) + return true; + } + XFree(atoms); + } + + return false; +} + InputModifierState OS_X11::get_key_modifier_state(unsigned int p_x11_state) { @@ -583,11 +964,9 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { KeySym keysym_keycode=0; // keysym used to find a keycode KeySym keysym_unicode=0; // keysym used to find unicode - int nbytes=0; // bytes the string takes - // XLookupString returns keysyms usable as nice scancodes/ char str[256+1]; - nbytes=XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL); + XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL); // Meanwhile, XLookupString returns keysyms useful for unicode. @@ -684,7 +1063,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { ::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time); if (peek_event.type == KeyPress && tresh<5 ) { KeySym rk; - nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL); + XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL); if (rk==keysym_keycode) { XEvent event; XNextEvent(x11_display, &event); //erase next event @@ -748,13 +1127,18 @@ void OS_X11::process_xevents() { break; case VisibilityNotify: { - XVisibilityEvent * visibility = (XVisibilityEvent *)&event; minimized = (visibility->state == VisibilityFullyObscured); - } break; - case FocusIn: + case FocusIn: + minimized = false; +#ifdef NEW_WM_API + if(current_videomode.fullscreen) { + set_wm_fullscreen(true); + visual_server->init(); + } +#endif main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); if (mouse_mode==MOUSE_MODE_CAPTURED) { XGrabPointer(x11_display, x11_window, True, @@ -765,6 +1149,13 @@ void OS_X11::process_xevents() { break; case FocusOut: +#ifdef NEW_WM_API + if(current_videomode.fullscreen) { + set_wm_fullscreen(false); + set_window_minimized(true); + visual_server->init(); + } +#endif main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); if (mouse_mode==MOUSE_MODE_CAPTURED) { //dear X11, I try, I really try, but you never work, you do whathever you want. @@ -791,7 +1182,7 @@ void OS_X11::process_xevents() { event.xbutton.x=last_mouse_pos.x; event.xbutton.y=last_mouse_pos.y; } - + InputEvent mouse_event; mouse_event.ID=++event_id; mouse_event.type = InputEvent::MOUSE_BUTTON; @@ -826,7 +1217,7 @@ void OS_X11::process_xevents() { last_click_ms+=diff; last_click_pos = Point2(event.xbutton.x,event.xbutton.y); } - } + } input->parse_input_event( mouse_event); @@ -836,16 +1227,15 @@ void OS_X11::process_xevents() { last_timestamp=event.xmotion.time; - + // Motion is also simple. // A little hack is in order // to be able to send relative motion events. - Point2i pos( event.xmotion.x, event.xmotion.y ); if (mouse_mode==MOUSE_MODE_CAPTURED) { #if 1 - Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2); + //Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2); if (pos==Point2i(current_videomode.width/2,current_videomode.height/2)) { //this sucks, it's a hack, etc and is a little inaccurate, etc. //but nothing I can do, X11 sucks. @@ -854,9 +1244,9 @@ void OS_X11::process_xevents() { break; } - Point2i ncenter = pos; - pos = last_mouse_pos + ( pos-center ); - center=ncenter; + Point2i new_center = pos; + pos = last_mouse_pos + ( pos - center ); + center=new_center; do_mouse_warp=true; #else //Dear X11, thanks for making my life miserable @@ -869,9 +1259,7 @@ void OS_X11::process_xevents() { XWarpPointer(x11_display, None, x11_window, 0,0,0,0, (int)center.x, (int)center.y); #endif - } - if (!last_mouse_pos_valid) { @@ -880,7 +1268,14 @@ void OS_X11::process_xevents() { } Point2i rel = pos - last_mouse_pos; - + +#ifdef NEW_WM_API + if (mouse_mode==MOUSE_MODE_CAPTURED) { + pos.x = current_videomode.width / 2; + pos.y = current_videomode.height / 2; + } +#endif + InputEvent motion_event; motion_event.ID=++event_id; motion_event.type=InputEvent::MOUSE_MOTION; @@ -900,6 +1295,8 @@ void OS_X11::process_xevents() { motion_event.mouse_motion.relative_y=rel.y; last_mouse_pos=pos; + + // printf("rel: %d,%d\n", rel.x, rel.y ); input->parse_input_event( motion_event); @@ -974,8 +1371,18 @@ void OS_X11::process_xevents() { if (do_mouse_warp) { XWarpPointer(x11_display, None, x11_window, - 0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2); - + 0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2); + + /* + Window root, child; + int root_x, root_y; + int win_x, win_y; + unsigned int mask; + XQueryPointer( x11_display, x11_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask ); + + printf("Root: %d,%d\n", root_x, root_y); + printf("Win: %d,%d\n", win_x, win_y); + */ } } @@ -1088,7 +1495,73 @@ String OS_X11::get_name() { Error OS_X11::shell_open(String p_uri) { - return ERR_UNAVAILABLE; + Error ok; + List<String> args; + args.push_back(p_uri); + ok = execute("/usr/bin/xdg-open",args,false); + if (ok==OK) + return OK; + ok = execute("gnome-open",args,false); + if (ok==OK) + return OK; + ok = execute("kde-open",args,false); + return ok; +} + +String OS_X11::get_system_dir(SystemDir p_dir) const { + + + String xdgparam; + + switch(p_dir) { + case SYSTEM_DIR_DESKTOP: { + + xdgparam="DESKTOP"; + } break; + case SYSTEM_DIR_DCIM: { + + xdgparam="PICTURES"; + + } break; + case SYSTEM_DIR_DOCUMENTS: { + + xdgparam="DOCUMENTS"; + + } break; + case SYSTEM_DIR_DOWNLOADS: { + + xdgparam="DOWNLOAD"; + + } break; + case SYSTEM_DIR_MOVIES: { + + xdgparam="VIDEOS"; + + } break; + case SYSTEM_DIR_MUSIC: { + + xdgparam="MUSIC"; + + } break; + case SYSTEM_DIR_PICTURES: { + + xdgparam="PICTURES"; + + } break; + case SYSTEM_DIR_RINGTONES: { + + xdgparam="MUSIC"; + + } break; + } + + String pipe; + List<String> arg; + arg.push_back(xdgparam); + Error err = const_cast<OS_X11*>(this)->execute("/usr/bin/xdg-user-dir",arg,true,NULL,&pipe); + if (err!=OK) + return "."; + return pipe.strip_edges(); } @@ -1277,6 +1750,7 @@ void OS_X11::process_joysticks() { #endif }; + void OS_X11::set_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(p_shape,CURSOR_MAX); @@ -1380,13 +1854,15 @@ OS_X11::OS_X11() { AudioDriverManagerSW::add_driver(&driver_rtaudio); #endif +#ifdef PULSEAUDIO_ENABLED + AudioDriverManagerSW::add_driver(&driver_pulseaudio); +#endif + #ifdef ALSA_ENABLED AudioDriverManagerSW::add_driver(&driver_alsa); #endif minimized = false; - xim_style=NULL; + xim_style=0L; mouse_mode=MOUSE_MODE_VISIBLE; - - }; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 2ffca0e042..ebcb0dc2fc 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -43,6 +43,7 @@ #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/alsa/audio_driver_alsa.h" +#include "drivers/pulseaudio/audio_driver_pulseaudio.h" #include "servers/physics_2d/physics_2d_server_sw.h" #include <X11/keysym.h> @@ -129,6 +130,10 @@ class OS_X11 : public OS_Unix { AudioDriverALSA driver_alsa; #endif +#ifdef PULSEAUDIO_ENABLED + AudioDriverPulseAudio driver_pulseaudio; +#endif + enum { JOYSTICKS_MAX = 8, MAX_JOY_AXIS = 32768, // I've no idea @@ -155,12 +160,21 @@ class OS_X11 : public OS_Unix { Joystick joysticks[JOYSTICKS_MAX]; + unsigned int capture_idle; + bool maximized; + //void set_wm_border(bool p_enabled); + void set_wm_fullscreen(bool p_enabled); + + protected: virtual int get_video_driver_count() const; virtual const char * get_video_driver_name(int p_driver) const; virtual VideoMode get_default_video_mode() const; - + + virtual int get_audio_driver_count() const; + virtual const char * get_audio_driver_name(int p_driver) const; + virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver); virtual void finalize(); @@ -170,6 +184,7 @@ protected: void process_joysticks(); void close_joystick(int p_id = -1); + public: virtual String get_name(); @@ -197,12 +212,33 @@ public: virtual void make_rendering_thread(); virtual void swap_buffers(); + virtual String get_system_dir(SystemDir p_dir) const; + virtual Error shell_open(String p_uri); virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0); virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_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; + virtual void move_window_to_foreground(); void run(); diff --git a/platform/x11/platform_config.h b/platform/x11/platform_config.h index 21703969cc..f372f8c2cb 100644 --- a/platform/x11/platform_config.h +++ b/platform/x11/platform_config.h @@ -34,5 +34,5 @@ #endif #define GLES2_INCLUDE_H "gl_context/glew.h" -#define GLES1_INCLUDE_H "gl_context/glew.h" + diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 316dffb3f9..2fcfc18429 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "animated_sprite.h" - +#include "scene/scene_string_names.h" void AnimatedSprite::edit_set_pivot(const Point2& p_pivot) { set_offset(p_pivot); @@ -207,7 +207,7 @@ void AnimatedSprite::set_frame(int p_frame) { frame=p_frame; update(); _change_notify("frame"); - + emit_signal(SceneStringNames::get_singleton()->frame_changed); } int AnimatedSprite::get_frame() const { @@ -233,6 +233,7 @@ void AnimatedSprite::set_offset(const Point2& p_offset) { offset=p_offset; update(); item_rect_changed(); + _change_notify("offset"); } Point2 AnimatedSprite::get_offset() const { @@ -325,6 +326,8 @@ void AnimatedSprite::_bind_methods() { ObjectTypeDB::bind_method(_MD("_res_changed"),&AnimatedSprite::_res_changed); + ADD_SIGNAL(MethodInfo("frame_changed")); + ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index ad228662e4..a5c455ce64 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -73,14 +73,25 @@ real_t Area2D::get_gravity() const{ return gravity; } -void Area2D::set_density(real_t p_density){ +void Area2D::set_linear_damp(real_t p_linear_damp){ - density=p_density; - Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_DENSITY,p_density); + linear_damp=p_linear_damp; + Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_LINEAR_DAMP,p_linear_damp); } -real_t Area2D::get_density() const{ +real_t Area2D::get_linear_damp() const{ - return density; + return linear_damp; +} + +void Area2D::set_angular_damp(real_t p_angular_damp){ + + angular_damp=p_angular_damp; + Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_ANGULAR_DAMP,p_angular_damp); +} + +real_t Area2D::get_angular_damp() const{ + + return angular_damp; } void Area2D::set_priority(real_t p_priority){ @@ -94,7 +105,7 @@ real_t Area2D::get_priority() const{ } -void Area2D::_body_enter_scene(ObjectID p_id) { +void Area2D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; @@ -102,9 +113,9 @@ void Area2D::_body_enter_scene(ObjectID p_id) { Map<ObjectID,BodyState>::Element *E=body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_scene); + ERR_FAIL_COND(E->get().in_tree); - E->get().in_scene=true; + E->get().in_tree=true; emit_signal(SceneStringNames::get_singleton()->body_enter,node); for(int i=0;i<E->get().shapes.size();i++) { @@ -113,15 +124,15 @@ void Area2D::_body_enter_scene(ObjectID p_id) { } -void Area2D::_body_exit_scene(ObjectID p_id) { +void Area2D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; ERR_FAIL_COND(!node); Map<ObjectID,BodyState>::Element *E=body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_scene); - E->get().in_scene=false; + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree=false; emit_signal(SceneStringNames::get_singleton()->body_exit,node); for(int i=0;i<E->get().shapes.size();i++) { @@ -142,16 +153,18 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b ERR_FAIL_COND(!body_in && !E); + locked=true; + if (body_in) { if (!E) { E = body_map.insert(objid,BodyState()); E->get().rc=0; - E->get().in_scene=node && node->is_inside_scene(); + E->get().in_tree=node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid)); - if (E->get().in_scene) { + node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree,make_binds(objid)); + if (E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_enter,node); } } @@ -162,7 +175,7 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b E->get().shapes.insert(ShapePair(p_body_shape,p_area_shape)); - if (E->get().in_scene) { + if (!node || E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_area_shape); } @@ -178,9 +191,9 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b if (E->get().rc==0) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); - node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); - if (E->get().in_scene) + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); + if (E->get().in_tree) emit_signal(SceneStringNames::get_singleton()->body_exit,obj); } @@ -188,7 +201,7 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b eraseit=true; } - if (node && E->get().in_scene) { + if (!node || E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_area_shape); } @@ -197,33 +210,182 @@ void Area2D::_body_inout(int p_status,const RID& p_body, int p_instance, int p_b } + locked=false; + + } + +void Area2D::_area_enter_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = obj ? obj->cast_to<Node>() : NULL; + ERR_FAIL_COND(!node); + + Map<ObjectID,AreaState>::Element *E=area_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(E->get().in_tree); + + E->get().in_tree=true; + emit_signal(SceneStringNames::get_singleton()->area_enter,node); + for(int i=0;i<E->get().shapes.size();i++) { + + emit_signal(SceneStringNames::get_singleton()->area_enter_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape); + } + +} + +void Area2D::_area_exit_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = obj ? obj->cast_to<Node>() : NULL; + ERR_FAIL_COND(!node); + Map<ObjectID,AreaState>::Element *E=area_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree=false; + emit_signal(SceneStringNames::get_singleton()->area_exit,node); + for(int i=0;i<E->get().shapes.size();i++) { + + emit_signal(SceneStringNames::get_singleton()->area_exit_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape); + } + +} + +void Area2D::_area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape) { + + bool area_in = p_status==Physics2DServer::AREA_BODY_ADDED; + ObjectID objid=p_instance; + + Object *obj = ObjectDB::get_instance(objid); + Node *node = obj ? obj->cast_to<Node>() : NULL; + + Map<ObjectID,AreaState>::Element *E=area_map.find(objid); + + ERR_FAIL_COND(!area_in && !E); + + locked=true; + + if (area_in) { + if (!E) { + + E = area_map.insert(objid,AreaState()); + E->get().rc=0; + E->get().in_tree=node && node->is_inside_tree(); + if (node) { + node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree,make_binds(objid)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_enter,node); + } + } + + } + E->get().rc++; + if (node) + E->get().shapes.insert(AreaShapePair(p_area_shape,p_self_shape)); + + + if (!node || E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_enter_shape,objid,node,p_area_shape,p_self_shape); + } + + } else { + + E->get().rc--; + + if (node) + E->get().shapes.erase(AreaShapePair(p_area_shape,p_self_shape)); + + bool eraseit=false; + + if (E->get().rc==0) { + + if (node) { + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree); + if (E->get().in_tree) + emit_signal(SceneStringNames::get_singleton()->area_exit,obj); + + } + + eraseit=true; + + } + if (!node || E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_exit_shape,objid,obj,p_area_shape,p_self_shape); + } + + if (eraseit) + area_map.erase(E); + + } + + locked=false; + + +} + + + void Area2D::_clear_monitoring() { + if (locked) { + ERR_EXPLAIN("This function can't be used during the in/out signal."); + } + ERR_FAIL_COND(locked); - Map<ObjectID,BodyState> bmcopy = body_map; - body_map.clear(); - //disconnect all monitored stuff + { + Map<ObjectID,BodyState> bmcopy = body_map; + body_map.clear(); + //disconnect all monitored stuff - for (Map<ObjectID,BodyState>::Element *E=bmcopy.front();E;E=E->next()) { + for (Map<ObjectID,BodyState>::Element *E=bmcopy.front();E;E=E->next()) { - Object *obj = ObjectDB::get_instance(E->key()); - Node *node = obj ? obj->cast_to<Node>() : NULL; - ERR_CONTINUE(!node); - if (!E->get().in_scene) - continue; + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = obj ? obj->cast_to<Node>() : NULL; + ERR_CONTINUE(!node); + if (!E->get().in_tree) + continue; - for(int i=0;i<E->get().shapes.size();i++) { + for(int i=0;i<E->get().shapes.size();i++) { - emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape); + } + + emit_signal(SceneStringNames::get_singleton()->body_exit,obj); + + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); } - emit_signal(SceneStringNames::get_singleton()->body_exit,obj); + } + + { - node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); - node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); + Map<ObjectID,AreaState> bmcopy = area_map; + area_map.clear(); + //disconnect all monitored stuff + + for (Map<ObjectID,AreaState>::Element *E=bmcopy.front();E;E=E->next()) { + + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = obj ? obj->cast_to<Node>() : NULL; + ERR_CONTINUE(!node); + if (!E->get().in_tree) + continue; + + for(int i=0;i<E->get().shapes.size();i++) { + + emit_signal(SceneStringNames::get_singleton()->area_exit_shape,E->key(),node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape); + } + + emit_signal(SceneStringNames::get_singleton()->area_exit,obj); + + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree); + } } } @@ -232,7 +394,7 @@ void Area2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { _clear_monitoring(); } break; @@ -243,6 +405,11 @@ void Area2D::_notification(int p_what) { void Area2D::set_enable_monitoring(bool p_enable) { + if (locked) { + ERR_EXPLAIN("This function can't be used during the in/out signal."); + } + ERR_FAIL_COND(locked); + if (p_enable==monitoring) return; @@ -251,8 +418,10 @@ void Area2D::set_enable_monitoring(bool p_enable) { if (monitoring) { Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout"); + Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,"_area_inout"); } else { Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName()); + Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),NULL,StringName()); _clear_monitoring(); } @@ -263,11 +432,94 @@ bool Area2D::is_monitoring_enabled() const { return monitoring; } +void Area2D::set_monitorable(bool p_enable) { + + if (locked) { + ERR_EXPLAIN("This function can't be used during the in/out signal."); + } + ERR_FAIL_COND(locked); + + if (p_enable==monitorable) + return; + + monitorable=p_enable; + + Physics2DServer::get_singleton()->area_set_monitorable(get_rid(),monitorable); +} + +bool Area2D::is_monitorable() const { + + return monitorable; +} + +Array Area2D::get_overlapping_bodies() const { + + ERR_FAIL_COND_V(!monitoring,Array()); + Array ret; + ret.resize(body_map.size()); + int idx=0; + for (const Map<ObjectID,BodyState>::Element *E=body_map.front();E;E=E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize( ret.size() -1 ); //ops + } else { + ret[idx++]=obj; + } + + } + + return ret; +} + +Array Area2D::get_overlapping_areas() const { + + ERR_FAIL_COND_V(!monitoring,Array()); + Array ret; + ret.resize(area_map.size()); + int idx=0; + for (const Map<ObjectID,AreaState>::Element *E=area_map.front();E;E=E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize( ret.size() -1 ); //ops + } else { + ret[idx++]=obj; + } + + } + + return ret; +} + +bool Area2D::overlaps_area(Node* p_area) const { + + ERR_FAIL_NULL_V(p_area,false); + const Map<ObjectID,AreaState>::Element *E=area_map.find(p_area->get_instance_ID()); + if (!E) + return false; + return E->get().in_tree; + + + +} + +bool Area2D::overlaps_body(Node* p_body) const{ + + ERR_FAIL_NULL_V(p_body,false); + const Map<ObjectID,BodyState>::Element *E=body_map.find(p_body->get_instance_ID()); + if (!E) + return false; + return E->get().in_tree; + +} + void Area2D::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_body_enter_scene","id"),&Area2D::_body_enter_scene); - ObjectTypeDB::bind_method(_MD("_body_exit_scene","id"),&Area2D::_body_exit_scene); + ObjectTypeDB::bind_method(_MD("_body_enter_tree","id"),&Area2D::_body_enter_tree); + ObjectTypeDB::bind_method(_MD("_body_exit_tree","id"),&Area2D::_body_exit_tree); + + ObjectTypeDB::bind_method(_MD("_area_enter_tree","id"),&Area2D::_area_enter_tree); + ObjectTypeDB::bind_method(_MD("_area_exit_tree","id"),&Area2D::_area_exit_tree); ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area2D::set_space_override_mode); ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area2D::get_space_override_mode); @@ -281,8 +533,11 @@ void Area2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_gravity","gravity"),&Area2D::set_gravity); ObjectTypeDB::bind_method(_MD("get_gravity"),&Area2D::get_gravity); - ObjectTypeDB::bind_method(_MD("set_density","density"),&Area2D::set_density); - ObjectTypeDB::bind_method(_MD("get_density"),&Area2D::get_density); + ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&Area2D::set_linear_damp); + ObjectTypeDB::bind_method(_MD("get_linear_damp"),&Area2D::get_linear_damp); + + ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&Area2D::set_angular_damp); + ObjectTypeDB::bind_method(_MD("get_angular_damp"),&Area2D::get_angular_damp); ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area2D::set_priority); ObjectTypeDB::bind_method(_MD("get_priority"),&Area2D::get_priority); @@ -290,21 +545,39 @@ void Area2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area2D::set_enable_monitoring); ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area2D::is_monitoring_enabled); + ObjectTypeDB::bind_method(_MD("set_monitorable","enable"),&Area2D::set_monitorable); + ObjectTypeDB::bind_method(_MD("is_monitorable"),&Area2D::is_monitorable); + + ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area2D::get_overlapping_bodies); + ObjectTypeDB::bind_method(_MD("get_overlapping_areas"),&Area2D::get_overlapping_areas); + + ObjectTypeDB::bind_method(_MD("overlaps_body:PhysicsBody2D","body"),&Area2D::overlaps_body); + ObjectTypeDB::bind_method(_MD("overlaps_area:Area2D","area"),&Area2D::overlaps_area); + ObjectTypeDB::bind_method(_MD("_body_inout"),&Area2D::_body_inout); + ObjectTypeDB::bind_method(_MD("_area_inout"),&Area2D::_area_inout); + + + ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"))); + ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"))); + ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"))); + ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D"))); - ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape"))); - ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape"))); - ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body"))); - ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body"))); ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp")); ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable")); } @@ -314,10 +587,14 @@ Area2D::Area2D() : CollisionObject2D(Physics2DServer::get_singleton()->area_crea set_gravity(98);; set_gravity_vector(Vector2(0,1)); gravity_is_point=false; - density=0.1; + linear_damp=0.1; + angular_damp=1; + locked=false; priority=0; monitoring=false; + monitorable=false; set_enable_monitoring(true); + set_monitorable(true); } diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index b4c8edf138..6a6c757e0c 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -49,14 +49,17 @@ private: Vector2 gravity_vec; real_t gravity; bool gravity_is_point; - real_t density; + real_t linear_damp; + real_t angular_damp; int priority; bool monitoring; + bool monitorable; + bool locked; void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape); - void _body_enter_scene(ObjectID p_id); - void _body_exit_scene(ObjectID p_id); + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); struct ShapePair { @@ -76,12 +79,42 @@ private: struct BodyState { int rc; - bool in_scene; + bool in_tree; VSet<ShapePair> shapes; }; Map<ObjectID,BodyState> body_map; + + + void _area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape); + + void _area_enter_tree(ObjectID p_id); + void _area_exit_tree(ObjectID p_id); + + struct AreaShapePair { + + int area_shape; + int self_shape; + bool operator<(const AreaShapePair& p_sp) const { + if (area_shape==p_sp.area_shape) + return self_shape < p_sp.self_shape; + else + return area_shape < p_sp.area_shape; + } + + AreaShapePair() {} + AreaShapePair(int p_bs, int p_as) { area_shape=p_bs; self_shape=p_as; } + }; + + struct AreaState { + + int rc; + bool in_tree; + VSet<AreaShapePair> shapes; + }; + + Map<ObjectID,AreaState> area_map; void _clear_monitoring(); @@ -103,8 +136,11 @@ public: void set_gravity(real_t p_gravity); real_t get_gravity() const; - void set_density(real_t p_density); - real_t get_density() const; + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; + + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; void set_priority(real_t p_priority); real_t get_priority() const; @@ -112,6 +148,14 @@ public: void set_enable_monitoring(bool p_enable); bool is_monitoring_enabled() const; + void set_monitorable(bool p_enable); + bool is_monitorable() const; + + Array get_overlapping_bodies() const; //function for script + Array get_overlapping_areas() const; //function for script + + bool overlaps_area(Node* p_area) const; + bool overlaps_body(Node* p_body) const; Area2D(); ~Area2D(); diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp new file mode 100644 index 0000000000..245b3ba7eb --- /dev/null +++ b/scene/2d/back_buffer_copy.cpp @@ -0,0 +1,75 @@ +#include "back_buffer_copy.h" + +void BackBufferCopy::_update_copy_mode() { + + switch(copy_mode) { + + case COPY_MODE_DISALED: { + + VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),false,Rect2()); + } break; + case COPY_MODE_RECT: { + + VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),true,rect); + } break; + case COPY_MODE_VIEWPORT: { + + VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),true,Rect2()); + + } break; + + } +} + +Rect2 BackBufferCopy::get_item_rect() const { + + return rect; +} + +void BackBufferCopy::set_rect(const Rect2& p_rect) { + + rect=p_rect; + _update_copy_mode(); +} + +Rect2 BackBufferCopy::get_rect() const{ + return rect; +} + +void BackBufferCopy::set_copy_mode(CopyMode p_mode){ + + copy_mode=p_mode; + _update_copy_mode(); +} +BackBufferCopy::CopyMode BackBufferCopy::get_copy_mode() const{ + + return copy_mode; +} + + +void BackBufferCopy::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_rect","rect"),&BackBufferCopy::set_rect); + ObjectTypeDB::bind_method(_MD("get_rect"),&BackBufferCopy::get_rect); + + ObjectTypeDB::bind_method(_MD("set_copy_mode","copy_mode"),&BackBufferCopy::set_copy_mode); + ObjectTypeDB::bind_method(_MD("get_copy_mode"),&BackBufferCopy::get_copy_mode); + + ADD_PROPERTY( PropertyInfo(Variant::INT,"copy_mode",PROPERTY_HINT_ENUM,"Disabled,Rect,Viewport"),_SCS("set_copy_mode"),_SCS("get_copy_mode")); + ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),_SCS("set_rect"),_SCS("get_rect")); + + BIND_CONSTANT( COPY_MODE_DISALED ); + BIND_CONSTANT( COPY_MODE_RECT ); + BIND_CONSTANT( COPY_MODE_VIEWPORT ); + +} + +BackBufferCopy::BackBufferCopy(){ + + rect=Rect2(-100,-100,200,200); + copy_mode=COPY_MODE_RECT; + _update_copy_mode(); +} +BackBufferCopy::~BackBufferCopy(){ + +} diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h new file mode 100644 index 0000000000..3a86ffa309 --- /dev/null +++ b/scene/2d/back_buffer_copy.h @@ -0,0 +1,41 @@ +#ifndef BACKBUFFERCOPY_H +#define BACKBUFFERCOPY_H + +#include "scene/2d/node_2d.h" + +class BackBufferCopy : public Node2D { + OBJ_TYPE( BackBufferCopy,Node2D); +public: + enum CopyMode { + COPY_MODE_DISALED, + COPY_MODE_RECT, + COPY_MODE_VIEWPORT + }; +private: + + Rect2 rect; + CopyMode copy_mode; + + void _update_copy_mode(); + +protected: + + static void _bind_methods(); + +public: + + void set_rect(const Rect2& p_rect); + Rect2 get_rect() const; + + void set_copy_mode(CopyMode p_mode); + CopyMode get_copy_mode() const; + + Rect2 get_item_rect() const; + + BackBufferCopy(); + ~BackBufferCopy(); +}; + +VARIANT_ENUM_CAST(BackBufferCopy::CopyMode); + +#endif // BACKBUFFERCOPY_H diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index fe6c9637e0..b2d74b4ad5 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -33,10 +33,10 @@ void Camera2D::_update_scroll() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; - if (get_scene()->is_editor_hint()) { + if (get_tree()->is_editor_hint()) { update(); //will just be drawn return; } @@ -48,7 +48,7 @@ void Camera2D::_update_scroll() { if (viewport) { viewport->set_canvas_transform( xform ); } - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,group_name,"_camera_moved",xform); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_camera_moved",xform); }; } @@ -67,7 +67,7 @@ Vector2 Camera2D::get_zoom() const { Matrix32 Camera2D::get_camera_transform() { - if (!get_scene()) + if (!get_tree()) return Matrix32(); Size2 screen_size = get_viewport_rect().size; @@ -213,7 +213,7 @@ void Camera2D::_notification(int p_what) { _update_scroll(); } break; - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { viewport = NULL; Node *n=this; @@ -239,7 +239,7 @@ void Camera2D::_notification(int p_what) { } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (is_current()) { if (viewport) { @@ -316,13 +316,23 @@ bool Camera2D::is_current() const { void Camera2D::make_current() { - if (!is_inside_scene()) { + if (!is_inside_tree()) { current=true; } else { - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,group_name,"_make_current",this); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_make_current",this); } } +void Camera2D::clear_current() { + + current=false; + if (is_inside_tree()) { + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_make_current",(Object*)(NULL)); + } + +} + + void Camera2D::set_limit(Margin p_margin,int p_limit) { ERR_FAIL_INDEX(p_margin,4); @@ -435,6 +445,7 @@ void Camera2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating); ObjectTypeDB::bind_method(_MD("make_current"),&Camera2D::make_current); + ObjectTypeDB::bind_method(_MD("clear_current"),&Camera2D::clear_current); ObjectTypeDB::bind_method(_MD("_make_current"),&Camera2D::_make_current); ObjectTypeDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 116169cac1..515f9711bf 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -26,97 +26,98 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERA_2D_H
-#define CAMERA_2D_H
-
-#include "scene/2d/node_2d.h"
-#include "scene/main/viewport.h"
-
-
-class Camera2D : public Node2D {
-
- OBJ_TYPE( Camera2D, Node2D );
-
-protected:
- Point2 camera_pos;
- Point2 smoothed_camera_pos;
- bool first;
-
- Viewport *viewport;
-
- StringName group_name;
- StringName canvas_group_name;
- RID canvas;
- Vector2 offset;
- Vector2 zoom;
- bool centered;
- bool rotating;
- bool current;
- float smoothing;
- int limit[4];
- float drag_margin[4];
-
- bool h_drag_enabled;
- bool v_drag_enabled;
- float h_ofs;
- float v_ofs;
-
-
- Point2 camera_screen_center;
- void _update_scroll();
-
- void _make_current(Object *p_which);
- void _set_current(bool p_current);
-protected:
-
- virtual Matrix32 get_camera_transform();
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_offset(const Vector2& p_offset);
- Vector2 get_offset() const;
-
- void set_centered(bool p_centered);
- bool is_centered() const;
-
- void set_rotating(bool p_rotating);
- bool is_rotating() const;
-
- void set_limit(Margin p_margin,int p_limit);
- int get_limit(Margin p_margin) const;
-
-
- void set_h_drag_enabled(bool p_enabled);
- bool is_h_drag_enabled() const;
-
- void set_v_drag_enabled(bool p_enabled);
- bool is_v_drag_enabled() const;
-
- void set_drag_margin(Margin p_margin,float p_drag_margin);
- float get_drag_margin(Margin p_margin) const;
-
- void set_v_offset(float p_offset);
- float get_v_offset() const;
-
- void set_h_offset(float p_offset);
- float get_h_offset() const;
-
- void set_follow_smoothing(float p_speed);
- float get_follow_smoothing() const;
-
- void make_current();
- bool is_current() const;
-
- void set_zoom(const Vector2& p_zoom);
- Vector2 get_zoom() const;
-
- Point2 get_camera_screen_center() const;
-
- Vector2 get_camera_pos() const;
- void force_update_scroll();
-
- Camera2D();
-};
-
-#endif // CAMERA_2D_H
+#ifndef CAMERA_2D_H +#define CAMERA_2D_H + +#include "scene/2d/node_2d.h" +#include "scene/main/viewport.h" + + +class Camera2D : public Node2D { + + OBJ_TYPE( Camera2D, Node2D ); + +protected: + Point2 camera_pos; + Point2 smoothed_camera_pos; + bool first; + + Viewport *viewport; + + StringName group_name; + StringName canvas_group_name; + RID canvas; + Vector2 offset; + Vector2 zoom; + bool centered; + bool rotating; + bool current; + float smoothing; + int limit[4]; + float drag_margin[4]; + + bool h_drag_enabled; + bool v_drag_enabled; + float h_ofs; + float v_ofs; + + + Point2 camera_screen_center; + void _update_scroll(); + + void _make_current(Object *p_which); + void _set_current(bool p_current); +protected: + + virtual Matrix32 get_camera_transform(); + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_offset(const Vector2& p_offset); + Vector2 get_offset() const; + + void set_centered(bool p_centered); + bool is_centered() const; + + void set_rotating(bool p_rotating); + bool is_rotating() const; + + void set_limit(Margin p_margin,int p_limit); + int get_limit(Margin p_margin) const; + + + void set_h_drag_enabled(bool p_enabled); + bool is_h_drag_enabled() const; + + void set_v_drag_enabled(bool p_enabled); + bool is_v_drag_enabled() const; + + void set_drag_margin(Margin p_margin,float p_drag_margin); + float get_drag_margin(Margin p_margin) const; + + void set_v_offset(float p_offset); + float get_v_offset() const; + + void set_h_offset(float p_offset); + float get_h_offset() const; + + void set_follow_smoothing(float p_speed); + float get_follow_smoothing() const; + + void make_current(); + void clear_current(); + bool is_current() const; + + void set_zoom(const Vector2& p_zoom); + Vector2 get_zoom() const; + + Point2 get_camera_screen_center() const; + + Vector2 get_camera_pos() const; + void force_update_scroll(); + + Camera2D(); +}; + +#endif // CAMERA_2D_H diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index d66f100b3f..118ba33bc6 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -36,9 +36,199 @@ #include "scene/resources/texture.h" #include "scene/resources/style_box.h" + +bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) { + + if (p_name==SceneStringNames::get_singleton()->shader_shader) { + set_shader(p_value); + return true; + } else if (p_name==SceneStringNames::get_singleton()->shading_mode) { + set_shading_mode(ShadingMode(p_value.operator int())); + return true; + } else { + + if (shader.is_valid()) { + + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/")==0) { //backwards compatibility + pr = n.substr(6,n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->canvas_item_material_set_shader_param(material,pr,p_value); + return true; + } + } + } + + return false; +} + +bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const { + + + if (p_name==SceneStringNames::get_singleton()->shader_shader) { + + r_ret=get_shader(); + return true; + } else if (p_name==SceneStringNames::get_singleton()->shading_mode) { + + + r_ret=shading_mode; + return true; + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret=VisualServer::get_singleton()->canvas_item_material_get_shader_param(material,pr); + return true; + } + } + + } + + + return false; +} + + +void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const { + + p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) ); + p_list->push_back( PropertyInfo( Variant::INT, "shader/shading_mode",PROPERTY_HINT_ENUM,"Normal,Unshaded,Light Only") ); + + if (!shader.is_null()) { + + shader->get_param_list(p_list); + } + +} + +void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) { + + ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM); +#ifdef TOOLS_ENABLED + + if (shader.is_valid()) { + shader->disconnect("changed",this,"_shader_changed"); + } +#endif + shader=p_shader; + +#ifdef TOOLS_ENABLED + + if (shader.is_valid()) { + shader->connect("changed",this,"_shader_changed"); + } +#endif + + RID rid; + if (shader.is_valid()) + rid=shader->get_rid(); + + VS::get_singleton()->canvas_item_material_set_shader(material,rid); + _change_notify(); //properties for shader exposed + emit_changed(); +} + +Ref<Shader> CanvasItemMaterial::get_shader() const{ + + return shader; +} + +void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){ + + VS::get_singleton()->canvas_item_material_set_shader_param(material,p_param,p_value); +} + +Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{ + + return VS::get_singleton()->canvas_item_material_get_shader_param(material,p_param); +} + +void CanvasItemMaterial::_shader_changed() { + + +} + +RID CanvasItemMaterial::get_rid() const { + + return material; +} + +void CanvasItemMaterial::set_shading_mode(ShadingMode p_mode) { + + shading_mode=p_mode; + VS::get_singleton()->canvas_item_material_set_shading_mode(material,VS::CanvasItemShadingMode(p_mode)); +} + +CanvasItemMaterial::ShadingMode CanvasItemMaterial::get_shading_mode() const { + return shading_mode; +} + + +void CanvasItemMaterial::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader); + ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader); + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param); + ObjectTypeDB::bind_method(_MD("set_shading_mode","mode"),&CanvasItemMaterial::set_shading_mode); + ObjectTypeDB::bind_method(_MD("get_shading_mode"),&CanvasItemMaterial::get_shading_mode); + + BIND_CONSTANT( SHADING_NORMAL ); + BIND_CONSTANT( SHADING_UNSHADED ); + BIND_CONSTANT( SHADING_ONLY_LIGHT ); + + +} + +void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String f = p_function.operator String(); + if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) { + + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\""); + } + } + } + Resource::get_argument_options(p_function,p_idx,r_options); +} + +CanvasItemMaterial::CanvasItemMaterial() { + + material=VS::get_singleton()->canvas_item_material_create(); + shading_mode=SHADING_NORMAL; +} + +CanvasItemMaterial::~CanvasItemMaterial(){ + + VS::get_singleton()->free(material); +} + + + + + + + + +/////////////////////////////////////////////////////////////////// + + + bool CanvasItem::is_visible() const { - if (!is_inside_scene()) + if (!is_inside_tree()) return false; const CanvasItem *p=this; @@ -92,7 +282,7 @@ void CanvasItem::show() { hidden=false; VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,true); - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (is_visible()) { @@ -106,11 +296,11 @@ void CanvasItem::hide() { if (hidden) return; - bool propagate=is_inside_scene() && is_visible(); + bool propagate=is_inside_tree() && is_visible(); hidden=true; VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,false); - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (propagate) _propagate_visibility_changed(false); @@ -147,7 +337,7 @@ void CanvasItem::_update_callback() { - if (!is_inside_scene()) { + if (!is_inside_tree()) { pending_update=false; return; } @@ -225,7 +415,7 @@ void CanvasItem::_sort_children() { pending_children_sort=false; - if (!is_inside_scene()) + if (!is_inside_tree()) return; for(int i=0;i<get_child_count();i++) { @@ -243,7 +433,7 @@ void CanvasItem::_sort_children() { void CanvasItem::_raise_self() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; VisualServer::get_singleton()->canvas_item_raise(canvas_item); @@ -283,7 +473,7 @@ void CanvasItem::_enter_canvas() { group = "root_canvas"+itos(canvas.get_id()); add_to_group(group); - get_scene()->call_group(SceneMainLoop::GROUP_CALL_UNIQUE,group,"_raise_self"); + get_tree()->call_group(SceneTree::GROUP_CALL_UNIQUE,group,"_raise_self"); } else { @@ -313,7 +503,7 @@ void CanvasItem::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { first_draw=true; pending_children_sort=false; @@ -324,14 +514,14 @@ void CanvasItem::_notification(int p_what) { } _enter_canvas(); if (!block_transform_notify && !xform_change.in_list()) { - get_scene()->xform_change_list.add(&xform_change); + get_tree()->xform_change_list.add(&xform_change); } } break; case NOTIFICATION_MOVED_IN_PARENT: { if (group!="") { - get_scene()->call_group(SceneMainLoop::GROUP_CALL_UNIQUE,group,"_raise_self"); + get_tree()->call_group(SceneTree::GROUP_CALL_UNIQUE,group,"_raise_self"); } else { CanvasItem *p = get_parent_item(); ERR_FAIL_COND(!p); @@ -340,9 +530,9 @@ void CanvasItem::_notification(int p_what) { } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (xform_change.in_list()) - get_scene()->xform_change_list.remove(&xform_change); + get_tree()->xform_change_list.remove(&xform_change); _exit_canvas(); if (C) { get_parent()->cast_to<CanvasItem>()->children_items.erase(C); @@ -379,7 +569,7 @@ bool CanvasItem::_is_visible_() const { void CanvasItem::update() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (pending_update) return; @@ -406,7 +596,7 @@ void CanvasItem::set_as_toplevel(bool p_toplevel) { if (toplevel==p_toplevel) return; - if (!is_inside_scene()) { + if (!is_inside_tree()) { toplevel=p_toplevel; return; } @@ -458,6 +648,16 @@ CanvasItem::BlendMode CanvasItem::get_blend_mode() const { return blend_mode; } +void CanvasItem::set_light_mask(int p_light_mask) { + + light_mask=p_light_mask; + VS::get_singleton()->canvas_item_set_light_mask(canvas_item,p_light_mask); +} + +int CanvasItem::get_light_mask() const{ + + return light_mask; +} void CanvasItem::item_rect_changed() { @@ -511,7 +711,7 @@ void CanvasItem::draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos) p_texture->draw(canvas_item,p_pos); } -void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_rect, bool p_tile,const Color& p_modulate) { +void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -519,17 +719,17 @@ void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_ } ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect(canvas_item,p_rect,p_tile,p_modulate); + p_texture->draw_rect(canvas_item,p_rect,p_tile,p_modulate,p_transpose); } -void CanvasItem::draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) { +void CanvasItem::draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) { if (!drawing) { ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL(); } ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect_region(canvas_item,p_rect,p_src_rect,p_modulate); + p_texture->draw_rect_region(canvas_item,p_rect,p_src_rect,p_modulate,p_transpose); } void CanvasItem::draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect) { @@ -630,8 +830,8 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) { if (!p_node->xform_change.in_list()) { if (!p_node->block_transform_notify) { - if (p_node->is_inside_scene()) - get_scene()->xform_change_list.add(&p_node->xform_change); + if (p_node->is_inside_tree()) + get_tree()->xform_change_list.add(&p_node->xform_change); } } @@ -648,13 +848,13 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) { Rect2 CanvasItem::get_viewport_rect() const { - ERR_FAIL_COND_V(!is_inside_scene(),Rect2()); + ERR_FAIL_COND_V(!is_inside_tree(),Rect2()); return get_viewport()->get_visible_rect(); } RID CanvasItem::get_canvas() const { - ERR_FAIL_COND_V(!is_inside_scene(),RID()); + ERR_FAIL_COND_V(!is_inside_tree(),RID()); if (canvas_layer) return canvas_layer->get_world_2d()->get_canvas(); @@ -677,7 +877,7 @@ CanvasItem *CanvasItem::get_toplevel() const { Ref<World2D> CanvasItem::get_world_2d() const { - ERR_FAIL_COND_V(!is_inside_scene(),Ref<World2D>()); + ERR_FAIL_COND_V(!is_inside_tree(),Ref<World2D>()); CanvasItem *tl=get_toplevel(); @@ -693,7 +893,7 @@ Ref<World2D> CanvasItem::get_world_2d() const { RID CanvasItem::get_viewport_rid() const { - ERR_FAIL_COND_V(!is_inside_scene(),RID()); + ERR_FAIL_COND_V(!is_inside_tree(),RID()); return get_viewport()->get_viewport(); } @@ -720,6 +920,96 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{ return behind; } +void CanvasItem::set_material(const Ref<CanvasItemMaterial>& p_material) { + + + material=p_material; + RID rid; + if (material.is_valid()) + rid=material->get_rid(); + VS::get_singleton()->canvas_item_set_material(canvas_item,rid); + _change_notify(); //properties for material exposed +} + +void CanvasItem::set_use_parent_material(bool p_use_parent_material) { + + use_parent_material=p_use_parent_material; + VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material); +} + +bool CanvasItem::get_use_parent_material() const{ + + return use_parent_material; +} + +Ref<CanvasItemMaterial> CanvasItem::get_material() const{ + + return material; +} + + +InputEvent CanvasItem::make_input_local(const InputEvent& p_event) const { + + ERR_FAIL_COND_V(!is_inside_tree(),p_event); + + InputEvent ev = p_event; + + Matrix32 local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse(); + + switch(ev.type) { + + case InputEvent::MOUSE_BUTTON: { + + Vector2 g = local_matrix.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y)); + Vector2 l = local_matrix.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y)); + ev.mouse_button.x=l.x; + ev.mouse_button.y=l.y; + ev.mouse_button.global_x=g.x; + ev.mouse_button.global_y=g.y; + + } break; + case InputEvent::MOUSE_MOTION: { + + Vector2 g = local_matrix.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); + Vector2 l = local_matrix.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); + Vector2 r = local_matrix.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 s = local_matrix.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); + ev.mouse_motion.x=l.x; + ev.mouse_motion.y=l.y; + ev.mouse_motion.global_x=g.x; + ev.mouse_motion.global_y=g.y; + ev.mouse_motion.relative_x=r.x; + ev.mouse_motion.relative_y=r.y; + ev.mouse_motion.speed_x=s.x; + ev.mouse_motion.speed_y=s.y; + + } break; + case InputEvent::SCREEN_TOUCH: { + + + Vector2 t = local_matrix.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y)); + ev.screen_touch.x=t.x; + ev.screen_touch.y=t.y; + + } break; + case InputEvent::SCREEN_DRAG: { + + + Vector2 t = local_matrix.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); + Vector2 r = local_matrix.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); + Vector2 s = local_matrix.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); + ev.screen_drag.x=t.x; + ev.screen_drag.y=t.y; + ev.screen_drag.relative_x=r.x; + ev.screen_drag.relative_y=r.y; + ev.screen_drag.speed_x=s.x; + ev.screen_drag.speed_y=s.y; + } break; + } + + return ev; +} + void CanvasItem::_bind_methods() { @@ -751,17 +1041,19 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_blend_mode","blend_mode"),&CanvasItem::set_blend_mode); ObjectTypeDB::bind_method(_MD("get_blend_mode"),&CanvasItem::get_blend_mode); + ObjectTypeDB::bind_method(_MD("set_light_mask","light_mask"),&CanvasItem::set_light_mask); + ObjectTypeDB::bind_method(_MD("get_light_mask"),&CanvasItem::get_light_mask); + ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&CanvasItem::set_opacity); ObjectTypeDB::bind_method(_MD("get_opacity"),&CanvasItem::get_opacity); ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity); ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity); - ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enabe"),&CanvasItem::set_draw_behind_parent); + ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enable"),&CanvasItem::set_draw_behind_parent); ObjectTypeDB::bind_method(_MD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled); ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top); ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top); - //ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0)); @@ -780,21 +1072,34 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform); ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform); + ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas); ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform); ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect); + ObjectTypeDB::bind_method(_MD("get_canvas_transform"),&CanvasItem::get_canvas_transform); ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas); ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d); //ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport); + ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material); + ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material); + + ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material); + ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material); + + ObjectTypeDB::bind_method(_MD("make_input_local","event"),&CanvasItem::make_input_local); + BIND_VMETHOD(MethodInfo("_draw")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") ); ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity") ); ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/self_opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"),_SCS("get_self_opacity") ); - ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") ); //exporting these two things doesn't really make much sense i think //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") ); //ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled")); @@ -824,7 +1129,7 @@ void CanvasItem::_bind_methods() { Matrix32 CanvasItem::get_canvas_transform() const { - ERR_FAIL_COND_V(!is_inside_scene(),Matrix32()); + ERR_FAIL_COND_V(!is_inside_tree(),Matrix32()); if (canvas_layer) return canvas_layer->get_transform(); @@ -835,7 +1140,7 @@ Matrix32 CanvasItem::get_canvas_transform() const { Matrix32 CanvasItem::get_viewport_transform() const { - ERR_FAIL_COND_V(!is_inside_scene(),Matrix32()); + ERR_FAIL_COND_V(!is_inside_tree(),Matrix32()); if (canvas_layer) { @@ -871,7 +1176,9 @@ CanvasItem::CanvasItem() : xform_change(this) { block_transform_notify=false; // viewport=NULL; canvas_layer=NULL; + use_parent_material=false; global_invalid=true; + light_mask=1; C=NULL; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 604eef0527..167f2b96f3 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -32,6 +32,7 @@ #include "scene/main/node.h" #include "scene/resources/texture.h" #include "scene/main/scene_main_loop.h" +#include "scene/resources/shader.h" class CanvasLayer; class Viewport; @@ -39,6 +40,50 @@ class Font; class StyleBox; +class CanvasItemMaterial : public Resource{ + + OBJ_TYPE(CanvasItemMaterial,Resource); + RID material; + Ref<Shader> shader; +public: + enum ShadingMode { + SHADING_NORMAL, + SHADING_UNSHADED, + SHADING_ONLY_LIGHT, + }; + +protected: + + ShadingMode shading_mode; + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + + void _shader_changed(); + static void _bind_methods(); + + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; + +public: + + void set_shader(const Ref<Shader>& p_shader); + Ref<Shader> get_shader() const; + + void set_shader_param(const StringName& p_param,const Variant& p_value); + Variant get_shader_param(const StringName& p_param) const; + + void set_shading_mode(ShadingMode p_mode); + ShadingMode get_shading_mode() const; + + virtual RID get_rid() const; + CanvasItemMaterial(); + ~CanvasItemMaterial(); +}; + +VARIANT_ENUM_CAST( CanvasItemMaterial::ShadingMode ); + + class CanvasItem : public Node { OBJ_TYPE( CanvasItem, Node ); @@ -70,6 +115,7 @@ private: List<CanvasItem*>::Element *C; BlendMode blend_mode; + int light_mask; bool first_draw; bool hidden; @@ -79,6 +125,9 @@ private: bool drawing; bool block_transform_notify; bool behind; + bool use_parent_material; + + Ref<CanvasItemMaterial> material; mutable Matrix32 global_transform; mutable bool global_invalid; @@ -99,8 +148,6 @@ private: void _queue_sort_children(); void _sort_children(); - - void _notify_transform(CanvasItem *p_node); void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); } @@ -108,9 +155,7 @@ private: protected: - - - _FORCE_INLINE_ void _notify_transform() { if (!is_inside_scene()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } + _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } void item_rect_changed(); @@ -120,7 +165,7 @@ public: enum { - NOTIFICATION_TRANSFORM_CHANGED=SceneMainLoop::NOTIFICATION_TRANSFORM_CHANGED, //unique + NOTIFICATION_TRANSFORM_CHANGED=SceneTree::NOTIFICATION_TRANSFORM_CHANGED, //unique NOTIFICATION_DRAW=30, NOTIFICATION_VISIBILITY_CHANGED=31, NOTIFICATION_ENTER_CANVAS=32, @@ -150,6 +195,9 @@ public: void set_blend_mode(BlendMode p_blend_mode); BlendMode get_blend_mode() const; + void set_light_mask(int p_light_mask); + int get_light_mask() const; + void set_opacity(float p_opacity); float get_opacity() const; @@ -162,8 +210,8 @@ public: void draw_rect(const Rect2& p_rect, const Color& p_color); void draw_circle(const Point2& p_pos, float p_radius, const Color& p_color); void draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos); - void draw_texture_rect(const Ref<Texture>& p_texture, const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)); - void draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)); + void draw_texture_rect(const Ref<Texture>& p_texture, const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false); + void draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false); void draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect); void draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, Ref<Texture> p_texture=Ref<Texture>(),float p_width=1); void draw_polygon(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), Ref<Texture> p_texture=Ref<Texture>()); @@ -204,7 +252,13 @@ public: RID get_canvas() const; Ref<World2D> get_world_2d() const; + void set_material(const Ref<CanvasItemMaterial>& p_material); + Ref<CanvasItemMaterial> get_material() const; + + void set_use_parent_material(bool p_use_parent_material); + bool get_use_parent_material() const; + InputEvent make_input_local(const InputEvent& pevent) const; CanvasItem(); ~CanvasItem(); diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp new file mode 100644 index 0000000000..82dd8012a5 --- /dev/null +++ b/scene/2d/canvas_modulate.cpp @@ -0,0 +1,46 @@ +#include "canvas_modulate.h" + + +void CanvasModulate::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_CANVAS) { + + VS::get_singleton()->canvas_set_modulate(get_canvas(),color); + } else if (p_what==NOTIFICATION_EXIT_CANVAS) { + + VS::get_singleton()->canvas_set_modulate(get_canvas(),Color(1,1,1,1)); + } +} + +void CanvasModulate::_bind_methods(){ + + ObjectTypeDB::bind_method(_MD("set_color","color"),&CanvasModulate::set_color); + ObjectTypeDB::bind_method(_MD("get_color"),&CanvasModulate::get_color); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color")); +} + + +void CanvasModulate::set_color(const Color& p_color){ + + color=p_color; + if (is_inside_tree()) { + VS::get_singleton()->canvas_set_modulate(get_canvas(),color); + } +} +Color CanvasModulate::get_color() const { + + return color; +} + + +CanvasModulate::CanvasModulate() +{ + color=Color(1,1,1,1); +} + +CanvasModulate::~CanvasModulate() +{ + +} + diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h new file mode 100644 index 0000000000..a6894f29c2 --- /dev/null +++ b/scene/2d/canvas_modulate.h @@ -0,0 +1,23 @@ +#ifndef CANVASMODULATE_H +#define CANVASMODULATE_H + +#include "scene/2d/node_2d.h" + +class CanvasModulate : public Node2D { + + OBJ_TYPE(CanvasModulate,Node2D); + + Color color; +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_color(const Color& p_color); + Color get_color() const; + + CanvasModulate(); + ~CanvasModulate(); +}; + +#endif // CANVASMODULATE_H diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index e5d9872a28..a883fee103 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -28,6 +28,7 @@ /*************************************************************************/ #include "collision_object_2d.h" #include "servers/physics_2d_server.h" +#include "scene/scene_string_names.h" void CollisionObject2D::_update_shapes_from_children() { @@ -45,7 +46,7 @@ void CollisionObject2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (area) Physics2DServer::get_singleton()->area_set_transform(rid,get_global_transform()); @@ -58,9 +59,15 @@ void CollisionObject2D::_notification(int p_what) { } else Physics2DServer::get_singleton()->body_set_space(rid,space); + _update_pickable(); + //get space } + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_pickable(); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (area) @@ -69,7 +76,7 @@ void CollisionObject2D::_notification(int p_what) { Physics2DServer::get_singleton()->body_set_state(rid,Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform()); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (area) { Physics2DServer::get_singleton()->area_set_space(rid,RID()); @@ -156,14 +163,65 @@ bool CollisionObject2D::_get(const StringName& p_name,Variant &r_ret) const { void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const { - p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR) ); + p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); for(int i=0;i<shapes.size();i++) { String path="shapes/"+itos(i)+"/"; - p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_NOEDITOR) ); - p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); - p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); + p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); + p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); + p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); + } +} + + +void CollisionObject2D::set_pickable(bool p_enabled) { + + if (pickable==p_enabled) + return; + + pickable=p_enabled; + _update_pickable(); +} + +bool CollisionObject2D::is_pickable() const { + + return pickable; +} + +void CollisionObject2D::_input_event(Node *p_viewport, const InputEvent& p_input_event, int p_shape) { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_viewport,p_input_event,p_shape); + } + emit_signal(SceneStringNames::get_singleton()->input_event,p_viewport,p_input_event,p_shape); +} + +void CollisionObject2D::_mouse_enter() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); } + emit_signal(SceneStringNames::get_singleton()->mouse_enter); +} + + +void CollisionObject2D::_mouse_exit() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); + } + emit_signal(SceneStringNames::get_singleton()->mouse_exit); + +} + +void CollisionObject2D::_update_pickable() { + if (!is_inside_tree()) + return; + bool pickable = this->pickable && is_inside_tree() && is_visible(); + if (area) + Physics2DServer::get_singleton()->area_set_pickable(rid,pickable); + else + Physics2DServer::get_singleton()->body_set_pickable(rid,pickable); } void CollisionObject2D::_bind_methods() { @@ -180,6 +238,17 @@ void CollisionObject2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject2D::clear_shapes); ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject2D::get_rid); + ObjectTypeDB::bind_method(_MD("set_pickable","enabled"),&CollisionObject2D::set_pickable); + ObjectTypeDB::bind_method(_MD("is_pickable"),&CollisionObject2D::is_pickable); + + BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx"))); + + ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx"))); + ADD_SIGNAL( MethodInfo("mouse_enter")); + ADD_SIGNAL( MethodInfo("mouse_exit")); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input/pickable"),_SCS("set_pickable"),_SCS("is_pickable")); + } @@ -262,7 +331,9 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { rid=p_rid; area=p_area; + pickable=true; if (p_area) { + Physics2DServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID()); } else { Physics2DServer::get_singleton()->body_attach_object_instance_ID(rid,get_instance_ID()); diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index 4a529ce062..393973ce90 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -38,6 +38,7 @@ class CollisionObject2D : public Node2D { bool area; RID rid; + bool pickable; struct ShapeData { Matrix32 xform; @@ -66,9 +67,17 @@ protected: bool _get(const StringName& p_name,Variant &r_ret) const; void _get_property_list( List<PropertyInfo> *p_list) const; static void _bind_methods(); + + void _update_pickable(); +friend class Viewport; + void _input_event(Node *p_viewport, const InputEvent& p_input_event, int p_shape); + void _mouse_enter(); + void _mouse_exit(); + public: + void add_shape(const Ref<Shape2D>& p_shape, const Matrix32& p_transform=Matrix32()); int get_shape_count() const; void set_shape(int p_shape_idx, const Ref<Shape2D>& p_shape); @@ -80,6 +89,9 @@ public: void remove_shape(int p_shape_idx); void clear_shapes(); + void set_pickable(bool p_enabled); + bool is_pickable() const; + _FORCE_INLINE_ RID get_rid() const { return rid; } CollisionObject2D(); diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index ef63286697..049017c0a5 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -33,6 +33,9 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { + if (unparenting) + return; + CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); ERR_FAIL_COND(!co); @@ -41,7 +44,6 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { bool solids=build_mode==BUILD_SOLIDS; - if (solids) { //here comes the sun, lalalala @@ -51,6 +53,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D ); convex->set_points(decomp[i]); co->add_shape(convex,get_transform()); + if (trigger) + co->set_shape_as_trigger(co->get_shape_count()-1,true); } @@ -71,6 +75,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { concave->set_segments(segments); co->add_shape(concave,get_transform()); + if (trigger) + co->set_shape_as_trigger(co->get_shape_count()-1,true); } @@ -93,9 +99,12 @@ void CollisionPolygon2D::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_ENTER_TREE: { + unparenting=false; + } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - if (!is_inside_scene()) + if (!is_inside_tree()) break; _update_parent(); @@ -120,6 +129,11 @@ void CollisionPolygon2D::_notification(int p_what) { } #endif } break; + case NOTIFICATION_UNPARENTED: { + unparenting = true; + _update_parent(); + } break; + } } @@ -166,6 +180,18 @@ Rect2 CollisionPolygon2D::get_item_rect() const { return aabb; } +void CollisionPolygon2D::set_trigger(bool p_trigger) { + + trigger=p_trigger; + _update_parent(); +} + +bool CollisionPolygon2D::is_trigger() const{ + + return trigger; +} + + void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object); @@ -175,14 +201,20 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode); ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode); + ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger); + ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); } CollisionPolygon2D::CollisionPolygon2D() { aabb=Rect2(-10,-10,20,20); build_mode=BUILD_SOLIDS; + trigger=false; + unparenting=false; } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 09c2060088..735110efad 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -50,6 +50,8 @@ protected: Rect2 aabb; BuildMode build_mode; Vector<Point2> polygon; + bool trigger; + bool unparenting; void _add_to_collision_object(Object *p_obj); void _update_parent(); @@ -60,6 +62,9 @@ protected: static void _bind_methods(); public: + void set_trigger(bool p_trigger); + bool is_trigger() const; + void set_build_mode(BuildMode p_mode); BuildMode get_build_mode() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 3f068f4ccc..9f35ade322 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -72,12 +72,12 @@ void CollisionShape2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { unparenting=false; } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { - if (!is_inside_scene()) + if (!is_inside_tree()) break; _update_parent(); diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 0e673ff791..e706ad658a 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -32,7 +32,7 @@ void Joint2D::_update_joint() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (joint.is_valid()) { @@ -86,7 +86,7 @@ void Joint2D::_notification(int p_what) { case NOTIFICATION_READY: { _update_joint(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (joint.is_valid()) { Physics2DServer::get_singleton()->free(joint); @@ -145,7 +145,7 @@ void PinJoint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { - if (is_inside_scene() && get_scene()->is_editor_hint()) { + if (is_inside_tree() && get_tree()->is_editor_hint()) { draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(0,-10),Point2(0,+10),Color(0.7,0.6,0.0,0.5),3); @@ -197,7 +197,7 @@ void GrooveJoint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { - if (is_inside_scene() && get_scene()->is_editor_hint()) { + if (is_inside_tree() && get_tree()->is_editor_hint()) { draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3); @@ -291,7 +291,7 @@ void DampedSpringJoint2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_DRAW: { - if (is_inside_scene() && get_scene()->is_editor_hint()) { + if (is_inside_tree() && get_tree()->is_editor_hint()) { draw_line(Point2(-10,0),Point2(+10,0),Color(0.7,0.6,0.0,0.5),3); draw_line(Point2(-10,length),Point2(+10,length),Color(0.7,0.6,0.0,0.5),3); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp new file mode 100644 index 0000000000..c0ab544d42 --- /dev/null +++ b/scene/2d/light_2d.cpp @@ -0,0 +1,365 @@ +#include "light_2d.h" +#include "servers/visual_server.h" + +void Light2D::edit_set_pivot(const Point2& p_pivot) { + + set_texture_offset(p_pivot); + +} + +Point2 Light2D::edit_get_pivot() const { + + return get_texture_offset(); +} +bool Light2D::edit_has_pivot() const { + + return true; +} + +Rect2 Light2D::get_item_rect() const { + + if (texture.is_null()) + return Rect2(0,0,1,1); + + Size2i s; + + s = texture->get_size()*_scale; + Point2i ofs=texture_offset; + ofs-=s/2; + + if (s==Size2(0,0)) + s=Size2(1,1); + + return Rect2(ofs,s); +} + + +void Light2D::set_enabled( bool p_enabled) { + + VS::get_singleton()->canvas_light_set_enabled(canvas_light,p_enabled); + enabled=p_enabled; +} + +bool Light2D::is_enabled() const { + + return enabled; +} + +void Light2D::set_texture( const Ref<Texture>& p_texture) { + + texture=p_texture; + if (texture.is_valid()) + VS::get_singleton()->canvas_light_set_texture(canvas_light,texture->get_rid()); + else + VS::get_singleton()->canvas_light_set_texture(canvas_light,RID()); +} + +Ref<Texture> Light2D::get_texture() const { + + return texture; +} + +void Light2D::set_texture_offset( const Vector2& p_offset) { + + texture_offset=p_offset; + VS::get_singleton()->canvas_light_set_texture_offset(canvas_light,texture_offset); + item_rect_changed(); + +} + +Vector2 Light2D::get_texture_offset() const { + + return texture_offset; +} + +void Light2D::set_color( const Color& p_color) { + + color=p_color; + VS::get_singleton()->canvas_light_set_color(canvas_light,color); + +} +Color Light2D::get_color() const { + + return color; +} + +void Light2D::set_height( float p_height) { + + height=p_height; + VS::get_singleton()->canvas_light_set_height(canvas_light,height); + +} + + +float Light2D::get_height() const { + + return height; +} + +void Light2D::set_energy( float p_energy) { + + energy=p_energy; + VS::get_singleton()->canvas_light_set_energy(canvas_light,energy); + +} + + +float Light2D::get_energy() const { + + return energy; +} + + + +void Light2D::set_texture_scale( float p_scale) { + + _scale=p_scale; + VS::get_singleton()->canvas_light_set_scale(canvas_light,_scale); + item_rect_changed(); + +} + + +float Light2D::get_texture_scale() const { + + return _scale; +} + +void Light2D::set_z_range_min( int p_min_z) { + + z_min=p_min_z; + VS::get_singleton()->canvas_light_set_z_range(canvas_light,z_min,z_max); + +} +int Light2D::get_z_range_min() const { + + return z_min; +} + +void Light2D::set_z_range_max( int p_max_z) { + + z_max=p_max_z; + VS::get_singleton()->canvas_light_set_z_range(canvas_light,z_min,z_max); + +} +int Light2D::get_z_range_max() const { + + return z_max; +} + +void Light2D::set_layer_range_min( int p_min_layer) { + + layer_min=p_min_layer; + VS::get_singleton()->canvas_light_set_layer_range(canvas_light,layer_min,layer_max); + +} +int Light2D::get_layer_range_min() const { + + return layer_min; +} + +void Light2D::set_layer_range_max( int p_max_layer) { + + layer_max=p_max_layer; + VS::get_singleton()->canvas_light_set_layer_range(canvas_light,layer_min,layer_max); + +} +int Light2D::get_layer_range_max() const { + + return layer_max; +} + +void Light2D::set_item_mask( int p_mask) { + + item_mask=p_mask; + VS::get_singleton()->canvas_light_set_item_mask(canvas_light,item_mask); + +} + +int Light2D::get_item_mask() const { + + return item_mask; +} + +void Light2D::set_item_shadow_mask( int p_mask) { + + item_shadow_mask=p_mask; + VS::get_singleton()->canvas_light_set_item_shadow_mask(canvas_light,item_shadow_mask); + +} + +int Light2D::get_item_shadow_mask() const { + + return item_shadow_mask; +} + +void Light2D::set_mode( Mode p_mode ) { + + mode=p_mode; + VS::get_singleton()->canvas_light_set_mode(canvas_light,VS::CanvasLightMode(p_mode)); +} + +Light2D::Mode Light2D::get_mode() const { + + return mode; +} + +void Light2D::set_shadow_enabled( bool p_enabled) { + + shadow=p_enabled; + VS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light,shadow); + +} +bool Light2D::is_shadow_enabled() const { + + return shadow; +} + +void Light2D::set_shadow_buffer_size( int p_size ) { + + shadow_buffer_size=p_size; + VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light,shadow_buffer_size); +} + +int Light2D::get_shadow_buffer_size() const { + + return shadow_buffer_size; +} + +void Light2D::set_shadow_esm_multiplier( float p_multiplier) { + + shadow_esm_multiplier=p_multiplier; + VS::get_singleton()->canvas_light_set_shadow_esm_multiplier(canvas_light,p_multiplier); +} + +float Light2D::get_shadow_esm_multiplier() const{ + + return shadow_esm_multiplier; +} + + +void Light2D::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_TREE) { + + VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, get_canvas() ); + } + + if (p_what==NOTIFICATION_TRANSFORM_CHANGED) { + + VS::get_singleton()->canvas_light_set_transform( canvas_light, get_global_transform()); + } + + if (p_what==NOTIFICATION_EXIT_TREE) { + + VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, RID() ); + } + +} + +void Light2D::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&Light2D::set_enabled); + ObjectTypeDB::bind_method(_MD("is_enabled"),&Light2D::is_enabled); + + ObjectTypeDB::bind_method(_MD("set_texture","texture"),&Light2D::set_texture); + ObjectTypeDB::bind_method(_MD("get_texture"),&Light2D::get_texture); + + ObjectTypeDB::bind_method(_MD("set_texture_offset","texture_offset"),&Light2D::set_texture_offset); + ObjectTypeDB::bind_method(_MD("get_texture_offset"),&Light2D::get_texture_offset); + + ObjectTypeDB::bind_method(_MD("set_color","color"),&Light2D::set_color); + ObjectTypeDB::bind_method(_MD("get_color"),&Light2D::get_color); + + ObjectTypeDB::bind_method(_MD("set_height","height"),&Light2D::set_height); + ObjectTypeDB::bind_method(_MD("get_height"),&Light2D::get_height); + + ObjectTypeDB::bind_method(_MD("set_energy","energy"),&Light2D::set_energy); + ObjectTypeDB::bind_method(_MD("get_energy"),&Light2D::get_energy); + + ObjectTypeDB::bind_method(_MD("set_texture_scale","texture_scale"),&Light2D::set_texture_scale); + ObjectTypeDB::bind_method(_MD("get_texture_scale"),&Light2D::get_texture_scale); + + + ObjectTypeDB::bind_method(_MD("set_z_range_min","z"),&Light2D::set_z_range_min); + ObjectTypeDB::bind_method(_MD("get_z_range_min"),&Light2D::get_z_range_min); + + ObjectTypeDB::bind_method(_MD("set_z_range_max","z"),&Light2D::set_z_range_max); + ObjectTypeDB::bind_method(_MD("get_z_range_max"),&Light2D::get_z_range_max); + + ObjectTypeDB::bind_method(_MD("set_layer_range_min","layer"),&Light2D::set_layer_range_min); + ObjectTypeDB::bind_method(_MD("get_layer_range_min"),&Light2D::get_layer_range_min); + + ObjectTypeDB::bind_method(_MD("set_layer_range_max","layer"),&Light2D::set_layer_range_max); + ObjectTypeDB::bind_method(_MD("get_layer_range_max"),&Light2D::get_layer_range_max); + + + ObjectTypeDB::bind_method(_MD("set_item_mask","item_mask"),&Light2D::set_item_mask); + ObjectTypeDB::bind_method(_MD("get_item_mask"),&Light2D::get_item_mask); + + ObjectTypeDB::bind_method(_MD("set_item_shadow_mask","item_shadow_mask"),&Light2D::set_item_shadow_mask); + ObjectTypeDB::bind_method(_MD("get_item_shadow_mask"),&Light2D::get_item_shadow_mask); + + ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Light2D::set_mode); + ObjectTypeDB::bind_method(_MD("get_mode"),&Light2D::get_mode); + + ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled); + ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled); + + ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size); + ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size); + + ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier); + ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale")); + ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy"),_SCS("set_energy"),_SCS("get_energy")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix"),_SCS("set_mode"),_SCS("get_mode")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_shadow_mask"),_SCS("get_item_shadow_mask")); + + BIND_CONSTANT( MODE_ADD ); + BIND_CONSTANT( MODE_SUB ); + BIND_CONSTANT( MODE_MIX ); + + +} + +Light2D::Light2D() { + + canvas_light=VisualServer::get_singleton()->canvas_light_create(); + enabled=true; + shadow=false; + color=Color(1,1,1); + height=0; + _scale=1.0; + z_min=-1024; + z_max=1024; + layer_min=0; + layer_max=0; + item_mask=1; + item_shadow_mask=1; + mode=MODE_ADD; + shadow_buffer_size=2048; + shadow_esm_multiplier=80; + energy=1.0; + +} + +Light2D::~Light2D() { + + VisualServer::get_singleton()->free(canvas_light); +} diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h new file mode 100644 index 0000000000..ef875aec2f --- /dev/null +++ b/scene/2d/light_2d.h @@ -0,0 +1,106 @@ +#ifndef LIGHT_2D_H +#define LIGHT_2D_H + +#include "scene/2d/node_2d.h" + +class Light2D : public Node2D { + + OBJ_TYPE(Light2D,Node2D); +public: + enum Mode { + MODE_ADD, + MODE_SUB, + MODE_MIX, + }; + +private: + RID canvas_light; + bool enabled; + bool shadow; + Color color; + float height; + float _scale; + float energy; + int z_min; + int z_max; + int layer_min; + int layer_max; + int item_mask; + int item_shadow_mask; + int shadow_buffer_size; + float shadow_esm_multiplier; + Mode mode; + Ref<Texture> texture; + Vector2 texture_offset; + +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + + virtual void edit_set_pivot(const Point2& p_pivot); + virtual Point2 edit_get_pivot() const; + virtual bool edit_has_pivot() const; + + void set_enabled( bool p_enabled); + bool is_enabled() const; + + void set_texture( const Ref<Texture>& p_texture); + Ref<Texture> get_texture() const; + + void set_texture_offset( const Vector2& p_offset); + Vector2 get_texture_offset() const; + + void set_color( const Color& p_color); + Color get_color() const; + + void set_height( float p_height); + float get_height() const; + + void set_energy( float p_energy); + float get_energy() const; + + void set_texture_scale( float p_scale); + float get_texture_scale() const; + + void set_z_range_min( int p_min_z); + int get_z_range_min() const; + + void set_z_range_max( int p_max_z); + int get_z_range_max() const; + + void set_layer_range_min( int p_min_layer); + int get_layer_range_min() const; + + void set_layer_range_max( int p_max_layer); + int get_layer_range_max() const; + + void set_item_mask( int p_mask); + int get_item_mask() const; + + void set_item_shadow_mask( int p_mask); + int get_item_shadow_mask() const; + + void set_mode( Mode p_mode ); + Mode get_mode() const; + + void set_shadow_enabled( bool p_enabled); + bool is_shadow_enabled() const; + + void set_shadow_buffer_size( int p_size ); + int get_shadow_buffer_size() const; + + void set_shadow_esm_multiplier( float p_multiplier); + float get_shadow_esm_multiplier() const; + + virtual Rect2 get_item_rect() const; + + Light2D(); + ~Light2D(); +}; + +VARIANT_ENUM_CAST(Light2D::Mode); + +#endif // LIGHT_2D_H diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp new file mode 100644 index 0000000000..6ebd499f71 --- /dev/null +++ b/scene/2d/light_occluder_2d.cpp @@ -0,0 +1,202 @@ +#include "light_occluder_2d.h" + + +void OccluderPolygon2D::set_polygon(const DVector<Vector2>& p_polygon) { + + polygon=p_polygon; + VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed); + emit_changed(); +} + +DVector<Vector2> OccluderPolygon2D::get_polygon() const{ + + return polygon; +} + +void OccluderPolygon2D::set_closed(bool p_closed) { + + if (closed==p_closed) + return; + closed=p_closed; + if (polygon.size()) + VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed); + emit_changed(); +} + +bool OccluderPolygon2D::is_closed() const{ + + return closed; +} + +void OccluderPolygon2D::set_cull_mode(CullMode p_mode){ + + cull=p_mode; + VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon,VS::CanvasOccluderPolygonCullMode(p_mode)); +} + +OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const{ + + return cull; +} + + +RID OccluderPolygon2D::get_rid() const { + + return occ_polygon; +} + +void OccluderPolygon2D::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed); + ObjectTypeDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed); + + ObjectTypeDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode); + ObjectTypeDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode); + + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + + BIND_CONSTANT(CULL_DISABLED); + BIND_CONSTANT(CULL_CLOCKWISE); + BIND_CONSTANT(CULL_COUNTER_CLOCKWISE); +} + + +OccluderPolygon2D::OccluderPolygon2D() { + + occ_polygon=VS::get_singleton()->canvas_occluder_polygon_create(); + closed=true; + cull=CULL_DISABLED; +} + +OccluderPolygon2D::~OccluderPolygon2D() { + + VS::get_singleton()->free(occ_polygon); +} + +#ifdef DEBUG_ENABLED +void LightOccluder2D::_poly_changed() { + + update(); +} +#endif + + +void LightOccluder2D::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_CANVAS) { + + VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas()); + VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform()); + + } + if (p_what==NOTIFICATION_TRANSFORM_CHANGED) { + + VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform()); + } + + if (p_what==NOTIFICATION_DRAW) { + + if (get_tree()->is_editor_hint()) { + + if (occluder_polygon.is_valid()) { + + DVector<Vector2> poly = occluder_polygon->get_polygon(); + + if (poly.size()) { + if (occluder_polygon->is_closed()) { + Vector<Color> color; + color.push_back(Color(0,0,0,0.6)); + draw_polygon(Variant(poly),color); + } else { + + int ps=poly.size(); + DVector<Vector2>::Read r = poly.read(); + for(int i=0;i<ps-1;i++) { + + draw_line(r[i],r[i+1],Color(0,0,0,0.6),3); + } + } + } + } + } + } + + + if (p_what==NOTIFICATION_EXIT_CANVAS) { + + VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,RID()); + } + + +} + +void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon) { + +#ifdef DEBUG_ENABLED + if (occluder_polygon.is_valid()) + occluder_polygon->disconnect("changed",this,"_poly_changed"); +#endif + occluder_polygon=p_polygon; + + if (occluder_polygon.is_valid()) + VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,occluder_polygon->get_rid()); + else + VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,RID()); + +#ifdef DEBUG_ENABLED + if (occluder_polygon.is_valid()) + occluder_polygon->connect("changed",this,"_poly_changed"); + update(); +#endif + +} + +Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const { + + return occluder_polygon; +} + +void LightOccluder2D::set_occluder_light_mask(int p_mask) { + + mask=p_mask; + VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder,mask); +} + +int LightOccluder2D::get_occluder_light_mask() const{ + + return mask; +} + +void LightOccluder2D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon); + ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon); + + ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask); + ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask); + +#ifdef DEBUG_ENABLED + ObjectTypeDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed); +#endif + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask")); +} + +LightOccluder2D::LightOccluder2D() { + + occluder=VS::get_singleton()->canvas_light_occluder_create(); + mask=1; +} + +LightOccluder2D::~LightOccluder2D() { + + VS::get_singleton()->free(occluder); +} + diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h new file mode 100644 index 0000000000..0343e3697e --- /dev/null +++ b/scene/2d/light_occluder_2d.h @@ -0,0 +1,73 @@ +#ifndef LIGHTOCCLUDER2D_H +#define LIGHTOCCLUDER2D_H + +#include "scene/2d/node_2d.h" + +class OccluderPolygon2D : public Resource { + + OBJ_TYPE(OccluderPolygon2D,Resource); +public: + + enum CullMode { + CULL_DISABLED, + CULL_CLOCKWISE, + CULL_COUNTER_CLOCKWISE + }; +private: + + + RID occ_polygon; + DVector<Vector2> polygon; + bool closed; + CullMode cull; + +protected: + + static void _bind_methods(); +public: + + void set_polygon(const DVector<Vector2>& p_polygon); + DVector<Vector2> get_polygon() const; + + void set_closed(bool p_closed); + bool is_closed() const; + + void set_cull_mode(CullMode p_mode); + CullMode get_cull_mode() const; + + virtual RID get_rid() const; + OccluderPolygon2D(); + ~OccluderPolygon2D(); + +}; + +VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode); + +class LightOccluder2D : public Node2D { + OBJ_TYPE(LightOccluder2D,Node2D); + + RID occluder; + bool enabled; + int mask; + Ref<OccluderPolygon2D> occluder_polygon; + +#ifdef DEBUG_ENABLED + void _poly_changed(); +#endif + +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon); + Ref<OccluderPolygon2D> get_occluder_polygon() const; + + void set_occluder_light_mask(int p_mask); + int get_occluder_light_mask() const; + + LightOccluder2D(); + ~LightOccluder2D(); +}; + +#endif // LIGHTOCCLUDER2D_H diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp new file mode 100644 index 0000000000..46af68444a --- /dev/null +++ b/scene/2d/navigation2d.cpp @@ -0,0 +1,660 @@ +#include "navigation2d.h" + +#define USE_ENTRY_POINT + +void Navigation2D::_navpoly_link(int p_id) { + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + NavMesh &nm=navpoly_map[p_id]; + ERR_FAIL_COND(nm.linked); + + print_line("LINK"); + + DVector<Vector2> vertices=nm.navpoly->get_vertices(); + int len = vertices.size(); + if (len==0) + return; + + DVector<Vector2>::Read r=vertices.read(); + + for(int i=0;i<nm.navpoly->get_polygon_count();i++) { + + //build + + List<Polygon>::Element *P=nm.polygons.push_back(Polygon()); + Polygon &p=P->get(); + p.owner=&nm; + + Vector<int> poly = nm.navpoly->get_polygon(i); + int plen=poly.size(); + const int *indices=poly.ptr(); + bool valid=true; + p.edges.resize(plen); + + Vector2 center; + + for(int j=0;j<plen;j++) { + + int idx = indices[j]; + if (idx<0 || idx>=len) { + valid=false; + break; + } + + Polygon::Edge e; + Vector2 ep=nm.xform.xform(r[idx]); + center+=ep; + e.point=_get_point(ep); + p.edges[j]=e; + } + + if (!valid) { + nm.polygons.pop_back(); + ERR_CONTINUE(!valid); + continue; + } + + p.center=center/plen; + + //connect + + for(int j=0;j<plen;j++) { + + int next = (j+1)%plen; + EdgeKey ek(p.edges[j].point,p.edges[next].point); + + Map<EdgeKey,Connection>::Element *C=connections.find(ek); + if (!C) { + + Connection c; + c.A=&p; + c.A_edge=j; + c.B=NULL; + c.B_edge=-1; + connections[ek]=c; + } else { + + if (C->get().B!=NULL) { + print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); + } + ERR_CONTINUE(C->get().B!=NULL); //wut + + C->get().B=&p; + C->get().B_edge=j; + C->get().A->edges[C->get().A_edge].C=&p; + C->get().A->edges[C->get().A_edge].C_edge=j;; + p.edges[j].C=C->get().A; + p.edges[j].C_edge=C->get().A_edge; + //connection successful. + } + } + } + + nm.linked=true; + +} + + +void Navigation2D::_navpoly_unlink(int p_id) { + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + NavMesh &nm=navpoly_map[p_id]; + ERR_FAIL_COND(!nm.linked); + + print_line("UNLINK"); + + for (List<Polygon>::Element *E=nm.polygons.front();E;E=E->next()) { + + + Polygon &p=E->get(); + + int ec = p.edges.size(); + Polygon::Edge *edges=p.edges.ptr(); + + for(int i=0;i<ec;i++) { + int next = (i+1)%ec; + + EdgeKey ek(edges[i].point,edges[next].point); + Map<EdgeKey,Connection>::Element *C=connections.find(ek); + ERR_CONTINUE(!C); + if (C->get().B) { + //disconnect + + C->get().B->edges[C->get().B_edge].C=NULL; + C->get().B->edges[C->get().B_edge].C_edge=-1; + C->get().A->edges[C->get().A_edge].C=NULL; + C->get().A->edges[C->get().A_edge].C_edge=-1; + + if (C->get().A==&E->get()) { + + C->get().A=C->get().B; + C->get().A_edge=C->get().B_edge; + } + C->get().B=NULL; + C->get().B_edge=-1; + + } else { + connections.erase(C); + //erase + } + } + } + + nm.polygons.clear(); + + nm.linked=false; + + +} + + +int Navigation2D::navpoly_create(const Ref<NavigationPolygon>& p_mesh, const Matrix32& p_xform, Object *p_owner) { + + int id = last_id++; + NavMesh nm; + nm.linked=false; + nm.navpoly=p_mesh; + nm.xform=p_xform; + nm.owner=p_owner; + navpoly_map[id]=nm; + + _navpoly_link(id); + + return id; +} + +void Navigation2D::navpoly_set_transform(int p_id, const Matrix32& p_xform){ + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + NavMesh &nm=navpoly_map[p_id]; + if (nm.xform==p_xform) + return; //bleh + _navpoly_unlink(p_id); + nm.xform=p_xform; + _navpoly_link(p_id); + + + +} +void Navigation2D::navpoly_remove(int p_id){ + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + _navpoly_unlink(p_id); + navpoly_map.erase(p_id); + +} +#if 0 +void Navigation2D::_clip_path(Vector<Vector2>& path, Polygon *from_poly, const Vector2& p_to_point, Polygon* p_to_poly) { + + Vector2 from = path[path.size()-1]; + + if (from.distance_to(p_to_point)<CMP_EPSILON) + return; + Plane cut_plane; + cut_plane.normal = (from-p_to_point).cross(up); + if (cut_plane.normal==Vector2()) + return; + cut_plane.normal.normalize(); + cut_plane.d = cut_plane.normal.dot(from); + + + while(from_poly!=p_to_poly) { + + int pe = from_poly->prev_edge; + Vector2 a = _get_vertex(from_poly->edges[pe].point); + Vector2 b = _get_vertex(from_poly->edges[(pe+1)%from_poly->edges.size()].point); + + from_poly=from_poly->edges[pe].C; + ERR_FAIL_COND(!from_poly); + + if (a.distance_to(b)>CMP_EPSILON) { + + Vector2 inters; + if (cut_plane.intersects_segment(a,b,&inters)) { + if (inters.distance_to(p_to_point)>CMP_EPSILON && inters.distance_to(path[path.size()-1])>CMP_EPSILON) { + path.push_back(inters); + } + } + } + } +} +#endif + +Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vector2& p_end, bool p_optimize) { + + + Polygon *begin_poly=NULL; + Polygon *end_poly=NULL; + Vector2 begin_point; + Vector2 end_point; + float begin_d=1e20; + float end_d=1e20; + + //look for point inside triangle + + for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) { + + + Polygon &p=F->get(); + if (begin_d || end_d) { + for(int i=2;i<p.edges.size();i++) { + + if (begin_d>0) { + + if (Geometry::is_point_in_triangle(p_start,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) { + + begin_poly=&p; + begin_point=p_start; + begin_d=0; + if (end_d==0) + break; + + } + } + + if (end_d>0) { + + if (Geometry::is_point_in_triangle(p_end,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) { + + end_poly=&p; + end_point=p_end; + end_d=0; + if (begin_d==0) + break; + } + } + + } + } + + p.prev_edge=-1; + } + } + + //start or end not inside triangle.. look for closest segment :| + if (begin_d || end_d) { + for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) { + + Polygon &p=F->get(); + int es = p.edges.size(); + for(int i=0;i<es;i++) { + + Vector2 edge[2]={ + _get_vertex(p.edges[i].point), + _get_vertex(p.edges[(i+1)%es].point) + }; + + + if (begin_d>0) { + Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_start,edge); + float d = spoint.distance_to(p_start); + if (d<begin_d) { + begin_poly=&p; + begin_point=spoint; + begin_d=d; + } + } + + if (end_d>0) { + Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_end,edge); + float d = spoint.distance_to(p_end); + if (d<end_d) { + end_poly=&p; + end_point=spoint; + end_d=d; + } + } + } + } + } + } + + if (!begin_poly || !end_poly) { + + //print_line("No Path Path"); + return Vector<Vector2>(); //no path + } + + if (begin_poly==end_poly) { + + Vector<Vector2> path; + path.resize(2); + path[0]=begin_point; + path[1]=end_point; + //print_line("Direct Path"); + return path; + } + + + bool found_route=false; + + List<Polygon*> open_list; + + begin_poly->entry=p_start; + + for(int i=0;i<begin_poly->edges.size();i++) { + + if (begin_poly->edges[i].C) { + + begin_poly->edges[i].C->prev_edge=begin_poly->edges[i].C_edge; +#ifdef USE_ENTRY_POINT + Vector2 edge[2]={ + _get_vertex(begin_poly->edges[i].point), + _get_vertex(begin_poly->edges[(i+1)%begin_poly->edges.size()].point) + }; + + Vector2 entry = Geometry::get_closest_point_to_segment_2d(begin_poly->entry,edge); + begin_poly->edges[i].C->distance = begin_poly->entry.distance_to(entry); + begin_poly->edges[i].C->entry=entry; +#else + begin_poly->edges[i].C->distance=begin_poly->center.distance_to(begin_poly->edges[i].C->center); +#endif + open_list.push_back(begin_poly->edges[i].C); + + if (begin_poly->edges[i].C==end_poly) { + found_route=true; + } + } + } + + + while(!found_route) { + + if (open_list.size()==0) { + // print_line("NOU OPEN LIST"); + break; + } + //check open list + + List<Polygon*>::Element *least_cost_poly=NULL; + float least_cost=1e30; + + //this could be faster (cache previous results) + for (List<Polygon*>::Element *E=open_list.front();E;E=E->next()) { + + Polygon *p=E->get(); + + + float cost=p->distance; + cost+=p->center.distance_to(end_point); + + if (cost<least_cost) { + + least_cost_poly=E; + least_cost=cost; + } + } + + + Polygon *p=least_cost_poly->get(); + //open the neighbours for search + int es = p->edges.size(); + + for(int i=0;i<es;i++) { + + + Polygon::Edge &e=p->edges[i]; + + if (!e.C) + continue; + +#ifdef USE_ENTRY_POINT + Vector2 edge[2]={ + _get_vertex(p->edges[i].point), + _get_vertex(p->edges[(i+1)%es].point) + }; + + Vector2 edge_entry = Geometry::get_closest_point_to_segment_2d(p->entry,edge); + float distance = p->entry.distance_to(edge_entry) + p->distance; + +#else + + float distance = p->center.distance_to(e.C->center) + p->distance; + +#endif + + + if (e.C->prev_edge!=-1) { + //oh this was visited already, can we win the cost? + + if (e.C->distance>distance) { + + e.C->prev_edge=e.C_edge; + e.C->distance=distance; +#ifdef USE_ENTRY_POINT + e.C->entry=edge_entry; +#endif + } + } else { + //add to open neighbours + + e.C->prev_edge=e.C_edge; + e.C->distance=distance; +#ifdef USE_ENTRY_POINT + e.C->entry=edge_entry; +#endif + + open_list.push_back(e.C); + + if (e.C==end_poly) { + //oh my reached end! stop algorithm + found_route=true; + break; + + } + + } + } + + if (found_route) + break; + + open_list.erase(least_cost_poly); + } + + if (found_route) { + + Vector<Vector2> path; + + if (p_optimize) { + //string pulling + + Polygon *apex_poly=end_poly; + Vector2 apex_point=end_point; + Vector2 portal_left=apex_point; + Vector2 portal_right=apex_point; + Polygon *left_poly=end_poly; + Polygon *right_poly=end_poly; + Polygon *p=end_poly; + path.push_back(end_point); + + while(p) { + + Vector2 left; + Vector2 right; + +//#define CLOCK_TANGENT(m_a,m_b,m_c) ( ((m_a)-(m_c)).cross((m_a)-(m_b)) ) +#define CLOCK_TANGENT(m_a,m_b,m_c) ((((m_a).x - (m_c).x) * ((m_b).y - (m_c).y) - ((m_b).x - (m_c).x) * ((m_a).y - (m_c).y))) + + if (p==begin_poly) { + left=begin_point; + right=begin_point; + } else { + int prev = p->prev_edge; + int prev_n = (p->prev_edge+1)%p->edges.size(); + left = _get_vertex(p->edges[prev].point); + right = _get_vertex(p->edges[prev_n].point); + + if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5) < 0){ + SWAP(left,right); + } + } + + bool skip=false; + + + if (CLOCK_TANGENT(apex_point,portal_left,left) >= 0){ + //process + if (portal_left==apex_point || CLOCK_TANGENT(apex_point,left,portal_right) > 0) { + left_poly=p; + portal_left=left; + } else { + + //_clip_path(path,apex_poly,portal_right,right_poly); + + apex_point=portal_right; + p=right_poly; + left_poly=p; + apex_poly=p; + portal_left=apex_point; + portal_right=apex_point; + path.push_back(apex_point); + skip=true; + } + } + + if (!skip && CLOCK_TANGENT(apex_point,portal_right,right) <= 0){ + //process + if (portal_right==apex_point || CLOCK_TANGENT(apex_point,right,portal_left) < 0) { + right_poly=p; + portal_right=right; + } else { + + //_clip_path(path,apex_poly,portal_left,left_poly); + + apex_point=portal_left; + p=left_poly; + right_poly=p; + apex_poly=p; + portal_right=apex_point; + portal_left=apex_point; + path.push_back(apex_point); + } + } + + if (p!=begin_poly) + p=p->edges[p->prev_edge].C; + else + p=NULL; + + } + + if (path[path.size()-1]!=begin_point) + path.push_back(begin_point); + + path.invert(); + + + + + } else { + //midpoints + Polygon *p=end_poly; + + path.push_back(end_point); + while(true) { + int prev = p->prev_edge; + int prev_n = (p->prev_edge+1)%p->edges.size(); + Vector2 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5; + path.push_back(point); + p = p->edges[prev].C; + if (p==begin_poly) + break; + } + + path.push_back(begin_point); + + + path.invert();; + } + + return path; + } + + + return Vector<Vector2>(); + +} + + +Vector2 Navigation2D::get_closest_point(const Vector2& p_point) { + + Vector2 closest_point=Vector2(); + float closest_point_d=1e20; + + for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) { + + Polygon &p=F->get(); + for(int i=2;i<p.edges.size();i++) { + + if (Geometry::is_point_in_triangle(p_point,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) { + + return p_point; //inside triangle, nothing else to discuss + } + + } + } + } + + for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) { + + Polygon &p=F->get(); + int es = p.edges.size(); + for(int i=0;i<es;i++) { + + Vector2 edge[2]={ + _get_vertex(p.edges[i].point), + _get_vertex(p.edges[(i+1)%es].point) + }; + + + Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_point,edge); + float d = spoint.distance_squared_to(p_point); + if (d<closest_point_d) { + + closest_point=spoint; + closest_point_d=d; + } + } + } + } + + return closest_point; + +} + + +void Navigation2D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("navpoly_create","mesh:NavigationPolygon","xform","owner"),&Navigation2D::navpoly_create,DEFVAL(Variant())); + ObjectTypeDB::bind_method(_MD("navpoly_set_transform","id","xform"),&Navigation2D::navpoly_set_transform); + ObjectTypeDB::bind_method(_MD("navpoly_remove","id"),&Navigation2D::navpoly_remove); + + ObjectTypeDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation2D::get_simple_path,DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation2D::get_closest_point); + +} + +Navigation2D::Navigation2D() { + + ERR_FAIL_COND( sizeof(Point)!=8 ); + cell_size=1; // one pixel + last_id=1; + +} diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation2d.h new file mode 100644 index 0000000000..7ff01bb442 --- /dev/null +++ b/scene/2d/navigation2d.h @@ -0,0 +1,138 @@ +#ifndef NAVIGATION_2D_H +#define NAVIGATION_2D_H + +#include "scene/2d/node_2d.h" +#include "scene/2d/navigation_polygon.h" + +class Navigation2D : public Node2D { + + OBJ_TYPE( Navigation2D, Node2D); + + + union Point { + + struct { + int64_t x:32; + int64_t y:32; + }; + + uint64_t key; + bool operator<(const Point& p_key) const { return key < p_key.key; } + }; + + + struct EdgeKey { + + Point a; + Point b; + + bool operator<(const EdgeKey& p_key) const { + return (a.key==p_key.a.key)?(b.key<p_key.b.key):(a.key<p_key.a.key); + }; + + EdgeKey(const Point& p_a=Point(),const Point& p_b=Point()) { + a=p_a; + b=p_b; + if (a.key > b.key) { + SWAP(a,b); + } + } + }; + + + struct NavMesh; + + + struct Polygon { + + struct Edge { + Point point; + Polygon *C; //connection + int C_edge; + Edge() { C=NULL; C_edge=-1; } + }; + + Vector<Edge> edges; + + Vector2 center; + Vector2 entry; + + float distance; + int prev_edge; + + NavMesh *owner; + }; + + + struct Connection { + + Polygon *A; + int A_edge; + Polygon *B; + int B_edge; + Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;} + }; + + Map<EdgeKey,Connection> connections; + + + struct NavMesh { + + Object *owner; + Matrix32 xform; + bool linked; + Ref<NavigationPolygon> navpoly; + List<Polygon> polygons; + + }; + + + + _FORCE_INLINE_ Point _get_point(const Vector2& p_pos) const { + + int x = int(Math::floor(p_pos.x/cell_size)); + int y = int(Math::floor(p_pos.y/cell_size)); + + Point p; + p.key=0; + p.x=x; + p.y=y; + return p; + + } + + _FORCE_INLINE_ Vector2 _get_vertex(const Point& p_point) const { + + return Vector2(p_point.x,p_point.y)*cell_size; + } + + + + void _navpoly_link(int p_id); + void _navpoly_unlink(int p_id); + + float cell_size; + Map<int,NavMesh> navpoly_map; + int last_id; +#if 0 + void _clip_path(Vector<Vector2>& path,Polygon *from_poly, const Vector2& p_to_point, Polygon* p_to_poly); +#endif +protected: + + static void _bind_methods(); + +public: + + //API should be as dynamic as possible + int navpoly_create(const Ref<NavigationPolygon>& p_mesh,const Matrix32& p_xform,Object* p_owner=NULL); + void navpoly_set_transform(int p_id, const Matrix32& p_xform); + void navpoly_remove(int p_id); + + Vector<Vector2> get_simple_path(const Vector2& p_start, const Vector2& p_end,bool p_optimize=true); + Vector2 get_closest_point(const Vector2& p_point); + + Navigation2D(); +}; + + +#endif // Navigation2D2D_H diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp new file mode 100644 index 0000000000..fc69ea8a0d --- /dev/null +++ b/scene/2d/navigation_polygon.cpp @@ -0,0 +1,450 @@ +#include "navigation_polygon.h" +#include "navigation2d.h" +#include "triangulator.h" +#include "core_string_names.h" + +void NavigationPolygon::set_vertices(const DVector<Vector2>& p_vertices) { + + vertices=p_vertices; +} + +DVector<Vector2> NavigationPolygon::get_vertices() const{ + + return vertices; +} + + +void NavigationPolygon::_set_polygons(const Array& p_array) { + + polygons.resize(p_array.size()); + for(int i=0;i<p_array.size();i++) { + polygons[i].indices=p_array[i]; + } +} + +Array NavigationPolygon::_get_polygons() const { + + Array ret; + ret.resize(polygons.size()); + for(int i=0;i<ret.size();i++) { + ret[i]=polygons[i].indices; + } + + return ret; +} + +void NavigationPolygon::_set_outlines(const Array& p_array) { + + outlines.resize(p_array.size()); + for(int i=0;i<p_array.size();i++) { + outlines[i]=p_array[i]; + } +} + +Array NavigationPolygon::_get_outlines() const { + + Array ret; + ret.resize(outlines.size()); + for(int i=0;i<ret.size();i++) { + ret[i]=outlines[i]; + } + + return ret; +} + + +void NavigationPolygon::add_polygon(const Vector<int>& p_polygon){ + + Polygon polygon; + polygon.indices=p_polygon; + polygons.push_back(polygon); + +} + +void NavigationPolygon::add_outline_at_index(const DVector<Vector2>& p_outline,int p_index) { + + outlines.insert(p_index,p_outline); +} + +int NavigationPolygon::get_polygon_count() const{ + + return polygons.size(); +} +Vector<int> NavigationPolygon::get_polygon(int p_idx){ + + ERR_FAIL_INDEX_V(p_idx,polygons.size(),Vector<int>()); + return polygons[p_idx].indices; +} +void NavigationPolygon::clear_polygons(){ + + polygons.clear(); +} + +void NavigationPolygon::add_outline(const DVector<Vector2>& p_outline) { + + outlines.push_back(p_outline); +} + +int NavigationPolygon::get_outline_count() const{ + + return outlines.size(); +} + +void NavigationPolygon::set_outline(int p_idx,const DVector<Vector2>& p_outline) { + ERR_FAIL_INDEX(p_idx,outlines.size()); + outlines[p_idx]=p_outline; +} + +void NavigationPolygon::remove_outline(int p_idx) { + + ERR_FAIL_INDEX(p_idx,outlines.size()); + outlines.remove(p_idx); + +} + +DVector<Vector2> NavigationPolygon::get_outline(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,outlines.size(),DVector<Vector2>()); + return outlines[p_idx]; +} + +void NavigationPolygon::clear_outlines(){ + + outlines.clear();; +} +void NavigationPolygon::make_polygons_from_outlines(){ + + List<TriangulatorPoly> in_poly,out_poly; + + Vector2 outside_point(-1e10,-1e10); + + for(int i=0;i<outlines.size();i++) { + + DVector<Vector2> ol = outlines[i]; + int olsize = ol.size(); + if (olsize<3) + continue; + DVector<Vector2>::Read r=ol.read(); + for(int j=0;j<olsize;j++) { + outside_point.x = MAX( r[j].x, outside_point.x ); + outside_point.y = MAX( r[j].y, outside_point.y ); + } + + } + + outside_point+=Vector2(0.7239784,0.819238); //avoid precision issues + + + + for(int i=0;i<outlines.size();i++) { + + DVector<Vector2> ol = outlines[i]; + int olsize = ol.size(); + if (olsize<3) + continue; + DVector<Vector2>::Read r=ol.read(); + + int interscount=0; + //test if this is an outer outline + for(int k=0;k<outlines.size();k++) { + + if (i==k) + continue; //no self intersect + + DVector<Vector2> ol2 = outlines[k]; + int olsize2 = ol2.size(); + if (olsize2<3) + continue; + DVector<Vector2>::Read r2=ol2.read(); + + for(int l=0;l<olsize2;l++) { + + if (Geometry::segment_intersects_segment_2d(r[0],outside_point,r2[l],r2[(l+1)%olsize2],NULL)) { + interscount++; + } + } + + } + + bool outer = (interscount%2)==0; + + TriangulatorPoly tp; + tp.Init(olsize); + for(int j=0;j<olsize;j++) { + tp[j]=r[j]; + } + + if (outer) + tp.SetOrientation(TRIANGULATOR_CCW); + else { + tp.SetOrientation(TRIANGULATOR_CW); + tp.SetHole(true); + } + + in_poly.push_back(tp); + } + + + TriangulatorPartition tpart; + if (tpart.ConvexPartition_HM(&in_poly,&out_poly)==0) { //failed! + print_line("convex partition failed!"); + return; + } + + polygons.clear(); + vertices.resize(0); + + Map<Vector2,int> points; + for(List<TriangulatorPoly>::Element*I = out_poly.front();I;I=I->next()) { + + TriangulatorPoly& tp = I->get(); + + struct Polygon p; + + for(int i=0;i<tp.GetNumPoints();i++) { + + Map<Vector2,int>::Element *E=points.find(tp[i]); + if (!E) { + E=points.insert(tp[i],vertices.size()); + vertices.push_back(tp[i]); + } + p.indices.push_back(E->get()); + } + + polygons.push_back(p); + } + + emit_signal(CoreStringNames::get_singleton()->changed); +} + + +void NavigationPolygon::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationPolygon::set_vertices); + ObjectTypeDB::bind_method(_MD("get_vertices"),&NavigationPolygon::get_vertices); + + ObjectTypeDB::bind_method(_MD("add_polygon","polygon"),&NavigationPolygon::add_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon_count"),&NavigationPolygon::get_polygon_count); + ObjectTypeDB::bind_method(_MD("get_polygon","idx"),&NavigationPolygon::get_polygon); + ObjectTypeDB::bind_method(_MD("clear_polygons"),&NavigationPolygon::clear_polygons); + + ObjectTypeDB::bind_method(_MD("add_outline","outline"),&NavigationPolygon::add_outline); + ObjectTypeDB::bind_method(_MD("add_outline_at_index","outline","index"),&NavigationPolygon::add_outline_at_index); + ObjectTypeDB::bind_method(_MD("get_outline_count"),&NavigationPolygon::get_outline_count); + ObjectTypeDB::bind_method(_MD("set_outline","idx","outline"),&NavigationPolygon::set_outline); + ObjectTypeDB::bind_method(_MD("get_outline","idx"),&NavigationPolygon::get_outline); + ObjectTypeDB::bind_method(_MD("remove_outline","idx"),&NavigationPolygon::remove_outline); + ObjectTypeDB::bind_method(_MD("clear_outlines"),&NavigationPolygon::clear_outlines); + ObjectTypeDB::bind_method(_MD("make_polygons_from_outlines"),&NavigationPolygon::make_polygons_from_outlines); + + ObjectTypeDB::bind_method(_MD("_set_polygons","polygons"),&NavigationPolygon::_set_polygons); + ObjectTypeDB::bind_method(_MD("_get_polygons"),&NavigationPolygon::_get_polygons); + + ObjectTypeDB::bind_method(_MD("_set_outlines","outlines"),&NavigationPolygon::_set_outlines); + ObjectTypeDB::bind_method(_MD("_get_outlines"),&NavigationPolygon::_get_outlines); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices")); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons")); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"outlines",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_outlines"),_SCS("_get_outlines")); +} + +NavigationPolygon::NavigationPolygon() { + + +} + +void NavigationPolygonInstance::set_enabled(bool p_enabled) { + + if (enabled==p_enabled) + return; + enabled=p_enabled; + + if (!is_inside_tree()) + return; + + if (!enabled) { + + if (nav_id!=-1) { + navigation->navpoly_remove(nav_id); + nav_id=-1; + } + } else { + + if (navigation) { + + if (navpoly.is_valid()) { + + nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this); + } + } + + } + + if (get_tree()->is_editor_hint()) + update(); + +// update_gizmo(); +} + +bool NavigationPolygonInstance::is_enabled() const { + + + return enabled; +} + + +///////////////////////////// + + +void NavigationPolygonInstance::_notification(int p_what) { + + + switch(p_what) { + case NOTIFICATION_ENTER_TREE: { + + Node2D *c=this; + while(c) { + + navigation=c->cast_to<Navigation2D>(); + if (navigation) { + + if (enabled && navpoly.is_valid()) { + + nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this); + } + break; + } + + c=c->get_parent()->cast_to<Node2D>(); + } + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (navigation && nav_id!=-1) { + navigation->navpoly_set_transform(nav_id,get_relative_transform(navigation)); + } + + } break; + case NOTIFICATION_EXIT_TREE: { + + if (navigation) { + + if (nav_id!=-1) { + navigation->navpoly_remove(nav_id); + nav_id=-1; + } + } + navigation=NULL; + } break; + case NOTIFICATION_DRAW: { + + if (is_inside_tree() && get_tree()->is_editor_hint() && navpoly.is_valid()) { + + DVector<Vector2> verts=navpoly->get_vertices(); + int vsize = verts.size(); + if (vsize<3) + return; + + + Color color; + if (enabled) { + color=Color(0.1,0.8,1.0,0.4); + } else { + color=Color(1.0,0.8,0.1,0.4); + } + Vector<Color> colors; + Vector<Vector2> vertices; + vertices.resize(vsize); + colors.resize(vsize); + { + DVector<Vector2>::Read vr = verts.read(); + for(int i=0;i<vsize;i++) { + vertices[i]=vr[i]; + colors[i]=color; + } + } + + Vector<int> indices; + + + for(int i=0;i<navpoly->get_polygon_count();i++) { + Vector<int> polygon = navpoly->get_polygon(i); + + for(int j=2;j<polygon.size();j++) { + + int kofs[3]={0,j-1,j}; + for(int k=0;k<3;k++) { + + int idx = polygon[ kofs[k] ]; + ERR_FAIL_INDEX(idx,vsize); + indices.push_back(idx); + } + } + } + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(),indices,vertices,colors); + + } + } break; + + } +} + + +void NavigationPolygonInstance::set_navigation_polygon(const Ref<NavigationPolygon>& p_navpoly) { + + if (p_navpoly==navpoly) + return; + + if (navigation && nav_id!=-1) { + navigation->navpoly_remove(nav_id); + nav_id=-1; + } + if (navpoly.is_valid()) { + navpoly->disconnect(CoreStringNames::get_singleton()->changed,this,"_navpoly_changed"); + } + navpoly=p_navpoly; + + if (navpoly.is_valid()) { + navpoly->connect(CoreStringNames::get_singleton()->changed,this,"_navpoly_changed"); + } + + if (navigation && navpoly.is_valid() && enabled) { + nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this); + } + //update_gizmo(); + _change_notify("navpoly"); + +} + +Ref<NavigationPolygon> NavigationPolygonInstance::get_navigation_polygon() const{ + + return navpoly; +} + +void NavigationPolygonInstance::_navpoly_changed() { + + if (is_inside_tree() && get_tree()->is_editor_hint()) + update(); +} + +void NavigationPolygonInstance::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_navigation_polygon","navpoly"),&NavigationPolygonInstance::set_navigation_polygon); + ObjectTypeDB::bind_method(_MD("get_navigation_polygon"),&NavigationPolygonInstance::get_navigation_polygon); + + ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&NavigationPolygonInstance::set_enabled); + ObjectTypeDB::bind_method(_MD("is_enabled"),&NavigationPolygonInstance::is_enabled); + + ObjectTypeDB::bind_method(_MD("_navpoly_changed"),&NavigationPolygonInstance::_navpoly_changed); + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navpoly",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon"),_SCS("set_navigation_polygon"),_SCS("get_navigation_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); +} + +NavigationPolygonInstance::NavigationPolygonInstance() { + + navigation=NULL; + nav_id=-1; + enabled=true; + +} diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h new file mode 100644 index 0000000000..01307a170b --- /dev/null +++ b/scene/2d/navigation_polygon.h @@ -0,0 +1,84 @@ +#ifndef NAVIGATION_POLYGON_H +#define NAVIGATION_POLYGON_H + +#include "scene/2d/node_2d.h" + + +class NavigationPolygon : public Resource { + + OBJ_TYPE( NavigationPolygon, Resource ); + + DVector<Vector2> vertices; + struct Polygon { + Vector<int> indices; + }; + Vector<Polygon> polygons; + Vector< DVector<Vector2> > outlines; + +protected: + + static void _bind_methods(); + + void _set_polygons(const Array& p_array); + Array _get_polygons() const; + + void _set_outlines(const Array& p_array); + Array _get_outlines() const; + +public: + + + + void set_vertices(const DVector<Vector2>& p_vertices); + DVector<Vector2> get_vertices() const; + + void add_polygon(const Vector<int>& p_polygon); + int get_polygon_count() const; + + void add_outline(const DVector<Vector2>& p_outline); + void add_outline_at_index(const DVector<Vector2>& p_outline,int p_index); + void set_outline(int p_idx,const DVector<Vector2>& p_outline); + DVector<Vector2> get_outline(int p_idx) const; + void remove_outline(int p_idx); + int get_outline_count() const; + + void clear_outlines(); + void make_polygons_from_outlines(); + + Vector<int> get_polygon(int p_idx); + void clear_polygons(); + + NavigationPolygon(); +}; + + +class Navigation2D; + +class NavigationPolygonInstance : public Node2D { + + OBJ_TYPE(NavigationPolygonInstance,Node2D); + + bool enabled; + int nav_id; + Navigation2D *navigation; + Ref<NavigationPolygon> navpoly; + + void _navpoly_changed(); + +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_navigation_polygon(const Ref<NavigationPolygon>& p_navpoly); + Ref<NavigationPolygon> get_navigation_polygon() const; + + NavigationPolygonInstance(); +}; + + +#endif // NAVIGATIONPOLYGON_H diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 4c00db2429..0b098f0cad 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -65,7 +65,7 @@ void Node2D::edit_set_state(const Variant& p_state) { pos = state[0]; angle = state[1]; - scale = state[2]; + _scale = state[2]; _update_transform(); _change_notify("transform/rot"); _change_notify("transform/scale"); @@ -93,11 +93,11 @@ void Node2D::edit_set_rect(const Rect2& p_edit_rect) { Point2 new_pos = p_edit_rect.pos + p_edit_rect.size*zero_offset;//p_edit_rect.pos - r.pos; Matrix32 postxf; - postxf.set_rotation_and_scale(angle,scale); + postxf.set_rotation_and_scale(angle,_scale); new_pos = postxf.xform(new_pos); pos+=new_pos; - scale*=new_scale; + _scale*=new_scale; _update_transform(); _change_notify("transform/scale"); @@ -118,19 +118,19 @@ void Node2D::_update_xform_values() { pos=_mat.elements[2]; angle=_mat.get_rotation(); - scale=_mat.get_scale(); + _scale=_mat.get_scale(); _xform_dirty=false; } void Node2D::_update_transform() { Matrix32 mat(angle,pos); - _mat.set_rotation_and_scale(angle,scale); + _mat.set_rotation_and_scale(angle,_scale); _mat.elements[2]=pos; VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),_mat); - if (!is_inside_scene()) + if (!is_inside_tree()) return; @@ -161,11 +161,11 @@ void Node2D::set_scale(const Size2& p_scale) { if (_xform_dirty) ((Node2D*)this)->_update_xform_values(); - scale=p_scale; - if (scale.x==0) - scale.x=CMP_EPSILON; - if (scale.y==0) - scale.y=CMP_EPSILON; + _scale=p_scale; + if (_scale.x==0) + _scale.x=CMP_EPSILON; + if (_scale.y==0) + _scale.y=CMP_EPSILON; _update_transform(); _change_notify("transform/scale"); @@ -187,7 +187,7 @@ Size2 Node2D::get_scale() const { if (_xform_dirty) ((Node2D*)this)->_update_xform_values(); - return scale; + return _scale; } void Node2D::_set_rotd(float p_angle) { @@ -224,11 +224,27 @@ Rect2 Node2D::get_item_rect() const { return Rect2(Point2(-32,-32),Size2(64,64)); } -void Node2D::rotate(float p_degrees) { +void Node2D::rotate(float p_radians) { - set_rot( get_rot() + p_degrees); + set_rot( get_rot() + p_radians); } +void Node2D::translate(const Vector2& p_amount) { + + set_pos( get_pos() + p_amount ); +} + +void Node2D::global_translate(const Vector2& p_amount) { + + set_global_pos( get_global_pos() + p_amount ); +} + +void Node2D::scale(const Vector2& p_amount) { + + set_scale( get_scale() * p_amount ); +} + + void Node2D::move_x(float p_delta,bool p_scaled){ Matrix32 t = get_transform(); @@ -272,7 +288,7 @@ void Node2D::set_transform(const Matrix32& p_transform) { VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),_mat); - if (!is_inside_scene()) + if (!is_inside_tree()) return; _notify_transform(); @@ -289,6 +305,47 @@ void Node2D::set_global_transform(const Matrix32& p_transform) { } +void Node2D::set_z(int p_z) { + + ERR_FAIL_COND(p_z<VS::CANVAS_ITEM_Z_MIN); + ERR_FAIL_COND(p_z>VS::CANVAS_ITEM_Z_MAX); + z=p_z; + VS::get_singleton()->canvas_item_set_z(get_canvas_item(),z); + +} + +void Node2D::set_z_as_relative(bool p_enabled) { + + if (z_relative==p_enabled) + return; + z_relative=p_enabled; + VS::get_singleton()->canvas_item_set_z_as_relative_to_parent(get_canvas_item(),p_enabled); +} + +bool Node2D::is_z_relative() const { + + return z_relative; +} + + +int Node2D::get_z() const{ + + return z; +} + +Matrix32 Node2D::get_relative_transform(const Node *p_parent) const { + + if (p_parent==this) + return Matrix32(); + + Node2D *parent_2d = get_parent()->cast_to<Node2D>(); + ERR_FAIL_COND_V(!parent_2d,Matrix32()); + if (p_parent==parent_2d) + return get_transform(); + else + return parent_2d->get_relative_transform(p_parent) * get_transform(); +} + void Node2D::_bind_methods() { @@ -304,22 +361,34 @@ void Node2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_rot"),&Node2D::get_rot); ObjectTypeDB::bind_method(_MD("get_scale"),&Node2D::get_scale); - ObjectTypeDB::bind_method(_MD("rotate","degrees"),&Node2D::rotate); + ObjectTypeDB::bind_method(_MD("rotate","radians"),&Node2D::rotate); ObjectTypeDB::bind_method(_MD("move_local_x","delta","scaled"),&Node2D::move_x,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("move_local_y","delta","scaled"),&Node2D::move_y,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("translate","offset"),&Node2D::translate); + ObjectTypeDB::bind_method(_MD("global_translate","offset"),&Node2D::global_translate); + ObjectTypeDB::bind_method(_MD("scale","ratio"),&Node2D::scale); + ObjectTypeDB::bind_method(_MD("set_global_pos","pos"),&Node2D::set_global_pos); ObjectTypeDB::bind_method(_MD("get_global_pos"),&Node2D::get_global_pos); - ObjectTypeDB::bind_method(_MD("set_global_pos"),&Node2D::set_global_pos); ObjectTypeDB::bind_method(_MD("set_transform","xform"),&Node2D::set_transform); ObjectTypeDB::bind_method(_MD("set_global_transform","xform"),&Node2D::set_global_transform); + ObjectTypeDB::bind_method(_MD("set_z","z"),&Node2D::set_z); + ObjectTypeDB::bind_method(_MD("get_z"),&Node2D::get_z); + + ObjectTypeDB::bind_method(_MD("set_z_as_relative","enable"),&Node2D::set_z_as_relative); + ObjectTypeDB::bind_method(_MD("is_z_relative"),&Node2D::is_z_relative); + ObjectTypeDB::bind_method(_MD("edit_set_pivot"),&Node2D::edit_set_pivot); + ObjectTypeDB::bind_method(_MD("get_relative_transform"),&Node2D::get_relative_transform); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale")); - + ADD_PROPERTY(PropertyInfo(Variant::INT,"z/z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z"),_SCS("get_z")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"z/relative"),_SCS("set_z_as_relative"),_SCS("is_z_relative")); } @@ -329,8 +398,10 @@ Node2D::Node2D() { angle=0; - scale=Vector2(1,1); + _scale=Vector2(1,1); _xform_dirty=false; + z=0; + z_relative=true; } diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 582c56fa9b..39a1061195 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -37,7 +37,9 @@ class Node2D : public CanvasItem { Point2 pos; float angle; - Size2 scale; + Size2 _scale; + int z; + bool z_relative; Matrix32 _mat; @@ -70,9 +72,12 @@ public: void set_rot(float p_angle); void set_scale(const Size2& p_scale); - void rotate(float p_degrees); + void rotate(float p_radians); void move_x(float p_delta,bool p_scaled=false); void move_y(float p_delta,bool p_scaled=false); + void translate(const Vector2& p_amount); + void global_translate(const Vector2& p_amount); + void scale(const Vector2& p_amount); Point2 get_pos() const; float get_rot() const; @@ -85,6 +90,15 @@ public: void set_global_transform(const Matrix32& p_transform); void set_global_pos(const Point2& p_pos); + void set_z(int p_z); + int get_z() const; + + void set_z_as_relative(bool p_enabled); + bool is_z_relative() const; + + Matrix32 get_relative_transform(const Node *p_parent) const; + + Matrix32 get_transform() const; diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp index 55607bd4eb..df37285f9d 100644 --- a/scene/2d/parallax_background.cpp +++ b/scene/2d/parallax_background.cpp @@ -36,13 +36,13 @@ void ParallaxBackground::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { group_name = "__cameras_"+itos(get_viewport().get_id()); add_to_group(group_name); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { remove_from_group(group_name); } break; @@ -78,7 +78,7 @@ void ParallaxBackground::set_scroll_offset(const Point2& p_ofs) { void ParallaxBackground::_update_scroll() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; Vector2 ofs = base_offset+offset*base_scale; diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index 2cda51dccb..a0913ab50c 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -74,7 +74,7 @@ void ParallaxLayer::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { orig_offset=get_pos(); orig_scale=get_scale(); @@ -85,9 +85,9 @@ void ParallaxLayer::_notification(int p_what) { void ParallaxLayer::set_base_offset_and_scale(const Point2& p_offset,float p_scale) { - if (!is_inside_scene()) + if (!is_inside_tree()) return; - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) return; Point2 new_ofs = ((orig_offset+p_offset)*motion_scale)*p_scale; diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 819b06e095..c9dd92ff3d 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -34,14 +34,14 @@ void ParticleAttractor2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { _update_owner(); } break; case NOTIFICATION_DRAW: { - if (!get_scene()->is_editor_hint()) + if (!get_tree()->is_editor_hint()) return; Vector2 pv; @@ -58,7 +58,7 @@ void ParticleAttractor2D::_notification(int p_what) { } } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (owner) { _set_owner(NULL); } @@ -76,7 +76,7 @@ void ParticleAttractor2D::_owner_exited() { void ParticleAttractor2D::_update_owner() { - if (!is_inside_scene() || !has_node(path)) { + if (!is_inside_tree() || !has_node(path)) { _set_owner(NULL); return; } @@ -98,7 +98,7 @@ void ParticleAttractor2D::_set_owner(Particles2D* p_owner) { return; if (owner) { - owner->disconnect("exit_scene",this,"_owner_exited"); + owner->disconnect("exit_tree",this,"_owner_exited"); owner->attractors.erase(this); owner=NULL; } @@ -106,7 +106,7 @@ void ParticleAttractor2D::_set_owner(Particles2D* p_owner) { if (owner) { - owner->connect("exit_scene",this,"_owner_exited",varray(),CONNECT_ONESHOT); + owner->connect("exit_tree",this,"_owner_exited",varray(),CONNECT_ONESHOT); owner->attractors.insert(this); } } @@ -355,6 +355,8 @@ void Particles2D::_process_particles(float p_delta) { p.rot=Math::deg2rad(param[PARAM_INITIAL_ANGLE]+param[PARAM_INITIAL_ANGLE]*randomness[PARAM_INITIAL_ANGLE]*_rand_from_seed(&rand_seed)); active_count++; + p.frame=Math::fmod(param[PARAM_ANIM_INITIAL_POS]+randomness[PARAM_ANIM_INITIAL_POS]*_rand_from_seed(&rand_seed),1.0); + } else { @@ -426,6 +428,8 @@ void Particles2D::_process_particles(float p_delta) { p.pos+=p.velocity*frame_time; p.rot+=Math::lerp(param[PARAM_SPIN_VELOCITY],param[PARAM_SPIN_VELOCITY]*randomness[PARAM_SPIN_VELOCITY]*_rand_from_seed(&rand_seed),randomness[PARAM_SPIN_VELOCITY])*frame_time; + float anim_spd=param[PARAM_ANIM_SPEED_SCALE]+param[PARAM_ANIM_SPEED_SCALE]*randomness[PARAM_ANIM_SPEED_SCALE]*_rand_from_seed(&rand_seed); + p.frame=Math::fposmod(p.frame+(frame_time/lifetime)*anim_spd,1.0); active_count++; @@ -457,7 +461,7 @@ void Particles2D::_notification(int p_what) { _process_particles( get_process_delta_time() ); } break; - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { float ppt=preprocess; while(ppt>0) { @@ -474,9 +478,13 @@ void Particles2D::_notification(int p_what) { RID ci=get_canvas_item(); Size2 size(1,1); Point2 center; + int total_frames=1; if (!texture.is_null()) { size=texture->get_size(); + size.x/=h_frames; + size.y/=v_frames; + total_frames=h_frames*v_frames; } @@ -612,7 +620,17 @@ void Particles2D::_notification(int p_what) { if (texrid.is_valid()) { - texture->draw(ci,Point2(),color); + Rect2 src_rect; + src_rect.size=size; + + if (total_frames>1) { + int frame = Math::fast_ftoi(Math::floor(p.frame*total_frames)) % total_frames; + src_rect.pos.x = size.x * (frame%h_frames); + src_rect.pos.y = size.y * (frame/h_frames); + } + + + texture->draw_rect_region(ci,Rect2(Point2(),size),src_rect,color); //VisualServer::get_singleton()->canvas_item_add_texture_rect(ci,r,texrid,false,color); } else { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2(),size),color); @@ -642,7 +660,9 @@ static const char* _particlesframe_property_names[Particles2D::PARAM_MAX]={ "params/initial_angle", "params/initial_size", "params/final_size", - "params/hue_variation" + "params/hue_variation", + "params/anim_speed_scale", + "params/anim_initial_pos", }; static const char* _particlesframe_property_rnames[Particles2D::PARAM_MAX]={ @@ -659,7 +679,9 @@ static const char* _particlesframe_property_rnames[Particles2D::PARAM_MAX]={ "randomness/initial_angle", "randomness/initial_size", "randomness/final_size", - "randomness/hue_variation" + "randomness/hue_variation", + "randomness/anim_speed_scale", + "randomness/anim_initial_pos", }; static const char* _particlesframe_property_ranges[Particles2D::PARAM_MAX]={ @@ -676,7 +698,9 @@ static const char* _particlesframe_property_ranges[Particles2D::PARAM_MAX]={ "0,360,0.01", "0,1024,0.01", "0,1024,0.01", - "0,1,0.01" + "0,1,0.01", + "0,128,0.01", + "0,1,0.01", }; @@ -909,6 +933,28 @@ bool Particles2D::is_flipped_v() const{ return flip_v; } +void Particles2D::set_h_frames(int p_frames) { + + ERR_FAIL_COND(p_frames<1); + h_frames=p_frames; +} + +int Particles2D::get_h_frames() const{ + + return h_frames; +} + +void Particles2D::set_v_frames(int p_frames){ + + ERR_FAIL_COND(p_frames<1); + v_frames=p_frames; +} +int Particles2D::get_v_frames() const{ + + return v_frames; +} + + void Particles2D::set_emission_points(const DVector<Vector2>& p_points) { @@ -958,6 +1004,12 @@ void Particles2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_flip_v","enable"),&Particles2D::set_flip_v); ObjectTypeDB::bind_method(_MD("is_flipped_v"),&Particles2D::is_flipped_v); + ObjectTypeDB::bind_method(_MD("set_h_frames","enable"),&Particles2D::set_h_frames); + ObjectTypeDB::bind_method(_MD("get_h_frames"),&Particles2D::get_h_frames); + + ObjectTypeDB::bind_method(_MD("set_v_frames","enable"),&Particles2D::set_v_frames); + ObjectTypeDB::bind_method(_MD("get_v_frames"),&Particles2D::get_v_frames); + ObjectTypeDB::bind_method(_MD("set_emission_half_extents","extents"),&Particles2D::set_emission_half_extents); ObjectTypeDB::bind_method(_MD("get_emission_half_extents"),&Particles2D::get_emission_half_extents); @@ -997,6 +1049,9 @@ void Particles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/flip_h"),_SCS("set_flip_h"),_SCS("is_flipped_h")); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/flip_v"),_SCS("set_flip_v"),_SCS("is_flipped_v")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"config/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"config/h_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_h_frames"),_SCS("get_h_frames")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames")); + for(int i=0;i<PARAM_MAX;i++) { @@ -1022,13 +1077,18 @@ void Particles2D::_bind_methods() { BIND_CONSTANT( PARAM_SPREAD ); BIND_CONSTANT( PARAM_LINEAR_VELOCITY ); BIND_CONSTANT( PARAM_SPIN_VELOCITY ); + BIND_CONSTANT( PARAM_ORBIT_VELOCITY ); BIND_CONSTANT( PARAM_GRAVITY_DIRECTION ); BIND_CONSTANT( PARAM_GRAVITY_STRENGTH ); BIND_CONSTANT( PARAM_RADIAL_ACCEL ); BIND_CONSTANT( PARAM_TANGENTIAL_ACCEL ); + BIND_CONSTANT( PARAM_DAMPING ); + BIND_CONSTANT( PARAM_INITIAL_ANGLE ); BIND_CONSTANT( PARAM_INITIAL_SIZE ); BIND_CONSTANT( PARAM_FINAL_SIZE ); BIND_CONSTANT( PARAM_HUE_VARIATION ); + BIND_CONSTANT( PARAM_ANIM_SPEED_SCALE ); + BIND_CONSTANT( PARAM_ANIM_INITIAL_POS ); BIND_CONSTANT( PARAM_MAX ); BIND_CONSTANT( MAX_COLOR_PHASES ); @@ -1054,6 +1114,7 @@ Particles2D::Particles2D() { set_param(PARAM_INITIAL_ANGLE,0.0); set_param(PARAM_INITIAL_SIZE,1.0); set_param(PARAM_FINAL_SIZE,1.0); + set_param(PARAM_ANIM_SPEED_SCALE,1.0); time=0; @@ -1081,6 +1142,8 @@ Particles2D::Particles2D() { flip_h=false; flip_v=false; + v_frames=1; + h_frames=1; emit_timeout = 0; time_to_live = 0; diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h index 47bd078a7a..6d91fcafc3 100644 --- a/scene/2d/particles_2d.h +++ b/scene/2d/particles_2d.h @@ -99,6 +99,8 @@ public: PARAM_INITIAL_SIZE, PARAM_FINAL_SIZE, PARAM_HUE_VARIATION, + PARAM_ANIM_SPEED_SCALE, + PARAM_ANIM_INITIAL_POS, PARAM_MAX }; @@ -117,8 +119,9 @@ private: Point2 pos; Vector2 velocity; float rot; + float frame; uint32_t seed; - Particle() { active=false; seed=123465789; rot=0;} + Particle() { active=false; seed=123465789; rot=0; frame=0;} }; Vector<Particle> particles; @@ -146,6 +149,8 @@ private: float time_scale; bool flip_h; bool flip_v; + int h_frames; + int v_frames; Point2 emissor_offset; Vector2 initial_velocity; Vector2 extents; @@ -206,6 +211,13 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; + + void set_h_frames(int p_frames); + int get_h_frames() const; + + void set_v_frames(int p_frames); + int get_v_frames() const; + void set_color_phases(int p_phases); int get_color_phases() const; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index febec54124..5560274c98 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -31,7 +31,7 @@ void Path2D::_notification(int p_what) { - if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_scene() && get_scene()->is_editor_hint()) { + if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_tree() && get_tree()->is_editor_hint()) { //draw the curve!! for(int i=0;i<curve->get_point_count();i++) { @@ -52,7 +52,7 @@ void Path2D::_notification(int p_what) { void Path2D::_curve_changed() { - if (is_inside_scene() && get_scene()->is_editor_hint()) + if (is_inside_tree() && get_tree()->is_editor_hint()) update(); } @@ -135,7 +135,7 @@ void PathFollow2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { Node *parent=get_parent(); if (parent) { @@ -147,7 +147,7 @@ void PathFollow2D::_notification(int p_what) { } } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { path=NULL; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 308aa8402f..5457182ea7 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -43,13 +43,44 @@ void PhysicsBody2D::_notification(int p_what) { */ } +void PhysicsBody2D::set_one_way_collision_direction(const Vector2& p_dir) { + + one_way_collision_direction=p_dir; + Physics2DServer::get_singleton()->body_set_one_way_collision_direction(get_rid(),p_dir); +} + +Vector2 PhysicsBody2D::get_one_way_collision_direction() const{ + + return one_way_collision_direction; +} + + +void PhysicsBody2D::set_one_way_collision_max_depth(float p_depth) { + + one_way_collision_max_depth=p_depth; + Physics2DServer::get_singleton()->body_set_one_way_collision_max_depth(get_rid(),p_depth); + +} + +float PhysicsBody2D::get_one_way_collision_max_depth() const{ + + return one_way_collision_max_depth; +} + + void PhysicsBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody2D::set_layer_mask); ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody2D::get_layer_mask); + ObjectTypeDB::bind_method(_MD("set_one_way_collision_direction","dir"),&PhysicsBody2D::set_one_way_collision_direction); + ObjectTypeDB::bind_method(_MD("get_one_way_collision_direction"),&PhysicsBody2D::get_one_way_collision_direction); + ObjectTypeDB::bind_method(_MD("set_one_way_collision_max_depth","depth"),&PhysicsBody2D::set_one_way_collision_max_depth); + ObjectTypeDB::bind_method(_MD("get_one_way_collision_max_depth"),&PhysicsBody2D::get_one_way_collision_max_depth); ObjectTypeDB::bind_method(_MD("add_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::add_collision_exception_with); ObjectTypeDB::bind_method(_MD("remove_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::remove_collision_exception_with); ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); + ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"one_way_collision/direction"),_SCS("set_one_way_collision_direction"),_SCS("get_one_way_collision_direction")); + ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"one_way_collision/max_depth"),_SCS("set_one_way_collision_max_depth"),_SCS("get_one_way_collision_max_depth")); } void PhysicsBody2D::set_layer_mask(uint32_t p_mask) { @@ -66,6 +97,8 @@ uint32_t PhysicsBody2D::get_layer_mask() const { PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) { mask=1; + set_one_way_collision_max_depth(0); + set_pickable(false); } @@ -198,7 +231,7 @@ StaticBody2D::~StaticBody2D() { -void RigidBody2D::_body_enter_scene(ObjectID p_id) { +void RigidBody2D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; @@ -218,7 +251,7 @@ void RigidBody2D::_body_enter_scene(ObjectID p_id) { } -void RigidBody2D::_body_exit_scene(ObjectID p_id) { +void RigidBody2D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; @@ -251,10 +284,10 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap E = contact_monitor->body_map.insert(objid,BodyState()); // E->get().rc=0; - E->get().in_scene=node && node->is_inside_scene(); + E->get().in_scene=node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree,make_binds(objid)); if (E->get().in_scene) { emit_signal(SceneStringNames::get_singleton()->body_enter,node); } @@ -283,8 +316,8 @@ void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shap if (E->get().shapes.empty()) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); - node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); if (in_scene) emit_signal(SceneStringNames::get_singleton()->body_exit,obj); @@ -496,6 +529,42 @@ real_t RigidBody2D::get_bounce() const{ return bounce; } + +void RigidBody2D::set_gravity_scale(real_t p_gravity_scale){ + + gravity_scale=p_gravity_scale; + Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_GRAVITY_SCALE,gravity_scale); + +} +real_t RigidBody2D::get_gravity_scale() const{ + + return gravity_scale; +} + +void RigidBody2D::set_linear_damp(real_t p_linear_damp){ + + ERR_FAIL_COND(p_linear_damp<-1); + linear_damp=p_linear_damp; + Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_LINEAR_DAMP,linear_damp); + +} +real_t RigidBody2D::get_linear_damp() const{ + + return linear_damp; +} + +void RigidBody2D::set_angular_damp(real_t p_angular_damp){ + + ERR_FAIL_COND(p_angular_damp<-1); + angular_damp=p_angular_damp; + Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_ANGULAR_DAMP,angular_damp); + +} +real_t RigidBody2D::get_angular_damp() const{ + + return angular_damp; +} + void RigidBody2D::set_axis_velocity(const Vector2& p_axis) { Vector2 v = state? state->get_linear_velocity() : linear_velocity; @@ -618,6 +687,26 @@ RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() cons } +Array RigidBody2D::get_colliding_bodies() const { + + ERR_FAIL_COND_V(!contact_monitor,Array()); + + Array ret; + ret.resize(contact_monitor->body_map.size()); + int idx=0; + for (const Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize( ret.size() -1 ); //ops + } else { + ret[idx++]=obj; + } + + } + + return ret; +} + void RigidBody2D::set_contact_monitor(bool p_enabled) { if (p_enabled==is_contact_monitor_enabled()) @@ -663,6 +752,15 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&RigidBody2D::set_bounce); ObjectTypeDB::bind_method(_MD("get_bounce"),&RigidBody2D::get_bounce); + ObjectTypeDB::bind_method(_MD("set_gravity_scale","gravity_scale"),&RigidBody2D::set_gravity_scale); + ObjectTypeDB::bind_method(_MD("get_gravity_scale"),&RigidBody2D::get_gravity_scale); + + ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&RigidBody2D::set_linear_damp); + ObjectTypeDB::bind_method(_MD("get_linear_damp"),&RigidBody2D::get_linear_damp); + + ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&RigidBody2D::set_angular_damp); + ObjectTypeDB::bind_method(_MD("get_angular_damp"),&RigidBody2D::get_angular_damp); + ObjectTypeDB::bind_method(_MD("set_linear_velocity","linear_velocity"),&RigidBody2D::set_linear_velocity); ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&RigidBody2D::get_linear_velocity); @@ -694,8 +792,10 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_able_to_sleep"),&RigidBody2D::is_able_to_sleep); ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&RigidBody2D::_direct_state_changed); - ObjectTypeDB::bind_method(_MD("_body_enter_scene"),&RigidBody2D::_body_enter_scene); - ObjectTypeDB::bind_method(_MD("_body_exit_scene"),&RigidBody2D::_body_exit_scene); + ObjectTypeDB::bind_method(_MD("_body_enter_tree"),&RigidBody2D::_body_enter_tree); + ObjectTypeDB::bind_method(_MD("_body_exit_tree"),&RigidBody2D::_body_exit_tree); + + ObjectTypeDB::bind_method(_MD("get_colliding_bodies"),&RigidBody2D::get_colliding_bodies); BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:Physics2DDirectBodyState"))); @@ -704,6 +804,7 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),_SCS("set_gravity_scale"),_SCS("get_gravity_scale")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator")); ADD_PROPERTY( PropertyInfo(Variant::INT,"continuous_cd",PROPERTY_HINT_ENUM,"Disabled,Cast Ray,Cast Shape"),_SCS("set_continuous_collision_detection_mode"),_SCS("get_continuous_collision_detection_mode")); ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported")); @@ -712,6 +813,8 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),_SCS("set_can_sleep"),_SCS("is_able_to_sleep")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/linear",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/angular",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp")); ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); @@ -736,6 +839,11 @@ RigidBody2D::RigidBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_RIGID) { bounce=0; mass=1; friction=1; + + gravity_scale=1; + linear_damp=-1; + angular_damp=-1; + max_contacts_reported=0; state=NULL; @@ -803,7 +911,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { colliding=false; - ERR_FAIL_COND_V(!is_inside_scene(),Vector2()); + ERR_FAIL_COND_V(!is_inside_tree(),Vector2()); Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); ERR_FAIL_COND_V(!dss,Vector2()); const int max_shapes=32; @@ -836,7 +944,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { //motion recover for(int i=0;i<get_shape_count();i++) { - + if (is_shape_set_as_trigger(i)) + continue; if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) collided=true; @@ -856,7 +965,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { //if (d<margin) /// continue; - recover_motion+=(b-a)*0.2; + recover_motion+=(b-a)*0.4; } if (recover_motion==Vector2()) { @@ -880,11 +989,14 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; float lsafe,lunsafe; bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask); //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); if (!valid) { + safe=0; unsafe=0; best_shape=i; //sadly it's the best @@ -916,9 +1028,11 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt*get_shape_transform(best_shape), Vector2(), margin,&rest_info,exclude,get_layer_mask(),mask); if (!c2) { //should not happen, but floating point precision is so weird.. + colliding=false; } else { + //print_line("Travel: "+rtos(travel)); colliding=true; collision=rest_info.point; @@ -947,7 +1061,7 @@ Vector2 KinematicBody2D::move_to(const Vector2& p_position) { bool KinematicBody2D::can_move_to(const Vector2& p_position, bool p_discrete) { - ERR_FAIL_COND_V(!is_inside_scene(),false); + ERR_FAIL_COND_V(!is_inside_tree(),false); Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); ERR_FAIL_COND_V(!dss,false); @@ -987,7 +1101,7 @@ bool KinematicBody2D::can_move_to(const Vector2& p_position, bool p_discrete) { bool KinematicBody2D::is_colliding() const { - ERR_FAIL_COND_V(!is_inside_scene(),false); + ERR_FAIL_COND_V(!is_inside_tree(),false); return colliding; } @@ -1084,7 +1198,7 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move); ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to); - ObjectTypeDB::bind_method(_MD("can_move_to","position"),&KinematicBody2D::can_move_to); + ObjectTypeDB::bind_method(_MD("can_move_to","position","discrete"),&KinematicBody2D::can_move_to,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody2D::is_colliding); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index e429ca1432..eed43c95be 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -39,6 +39,8 @@ class PhysicsBody2D : public CollisionObject2D { OBJ_TYPE(PhysicsBody2D,CollisionObject2D); uint32_t mask; + Vector2 one_way_collision_direction; + float one_way_collision_max_depth; protected: void _notification(int p_what); @@ -53,6 +55,12 @@ public: void add_collision_exception_with(Node* p_node); //must be physicsbody void remove_collision_exception_with(Node* p_node); + void set_one_way_collision_direction(const Vector2& p_dir); + Vector2 get_one_way_collision_direction() const; + + void set_one_way_collision_max_depth(float p_dir); + float get_one_way_collision_max_depth() const; + PhysicsBody2D(); }; @@ -119,6 +127,9 @@ private: real_t bounce; real_t mass; real_t friction; + real_t gravity_scale; + real_t linear_damp; + real_t angular_damp; Vector2 linear_velocity; real_t angular_velocity; @@ -170,8 +181,8 @@ private: ContactMonitor *contact_monitor; - void _body_enter_scene(ObjectID p_id); - void _body_exit_scene(ObjectID p_id); + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); void _body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape); @@ -198,6 +209,15 @@ public: void set_bounce(real_t p_bounce); real_t get_bounce() const; + void set_gravity_scale(real_t p_gravity_scale); + real_t get_gravity_scale() const; + + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; + + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + void set_linear_velocity(const Vector2& p_velocity); Vector2 get_linear_velocity() const; @@ -229,6 +249,8 @@ public: void set_applied_force(const Vector2& p_force); Vector2 get_applied_force() const; + Array get_colliding_bodies() const; //function for script + RigidBody2D(); ~RigidBody2D(); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 2b4be734af..217a98aaea 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -359,5 +359,6 @@ Polygon2D::Polygon2D() { tex_rot=0; tex_tile=true; tex_scale=Vector2(1,1); + color=Color(1,1,1); rect_cache_dirty=true; } diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index ca3be9aa8f..2db2be123b 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -45,14 +45,14 @@ void Position2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { update(); } break; case NOTIFICATION_DRAW: { - if (!is_inside_scene()) + if (!is_inside_tree()) break; - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) _draw_cross(); } break; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 8479338521..e352ac64f5 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -33,7 +33,7 @@ void RayCast2D::set_cast_to(const Vector2& p_point) { cast_to=p_point; - if (is_inside_scene() && get_scene()->is_editor_hint()) + if (is_inside_tree() && get_tree()->is_editor_hint()) update(); } @@ -82,7 +82,7 @@ Vector2 RayCast2D::get_collision_normal() const{ void RayCast2D::set_enabled(bool p_enabled) { enabled=p_enabled; - if (is_inside_scene() && !get_scene()->is_editor_hint()) + if (is_inside_tree() && !get_tree()->is_editor_hint()) set_fixed_process(p_enabled); if (!p_enabled) collided=false; @@ -101,15 +101,15 @@ void RayCast2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { - if (enabled && !get_scene()->is_editor_hint()) + if (enabled && !get_tree()->is_editor_hint()) set_fixed_process(true); else set_fixed_process(false); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (enabled) set_fixed_process(false); @@ -118,7 +118,7 @@ void RayCast2D::_notification(int p_what) { #ifdef TOOLS_ENABLED case NOTIFICATION_DRAW: { - if (!get_scene()->is_editor_hint()) + if (!get_tree()->is_editor_hint()) break; Matrix32 xf; xf.rotate(cast_to.atan2()); diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index 80d038f6f8..b170986017 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -45,7 +45,7 @@ void RemoteTransform2D::_update_cache() { void RemoteTransform2D::_update_remote() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (!cache) @@ -59,7 +59,7 @@ void RemoteTransform2D::_update_remote() { if (!n) return; - if (!n->is_inside_scene()) + if (!n->is_inside_tree()) return; //todo make faster @@ -77,7 +77,7 @@ void RemoteTransform2D::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - if (!is_inside_scene()) + if (!is_inside_tree()) break; if (cache) { @@ -95,7 +95,7 @@ void RemoteTransform2D::_notification(int p_what) { void RemoteTransform2D::set_remote_node(const NodePath& p_remote_node) { remote_node=p_remote_node; - if (is_inside_scene()) + if (is_inside_tree()) _update_cache(); } diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h index 9561e72255..05a9b20f6e 100644 --- a/scene/2d/remote_transform_2d.h +++ b/scene/2d/remote_transform_2d.h @@ -38,7 +38,7 @@ class RemoteTransform2D : public Node2D { void _update_remote(); void _update_cache(); - void _node_exited_scene(); + //void _node_exited_scene(); protected: static void _bind_methods(); diff --git a/scene/2d/sample_player_2d.cpp b/scene/2d/sample_player_2d.cpp index bc1734ec06..a231acd13d 100644 --- a/scene/2d/sample_player_2d.cpp +++ b/scene/2d/sample_player_2d.cpp @@ -89,7 +89,7 @@ void SamplePlayer2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { SpatialSound2DServer::get_singleton()->source_set_polyphony(get_source_rid(),polyphony); @@ -102,6 +102,7 @@ void SamplePlayer2D::_notification(int p_what) { void SamplePlayer2D::set_sample_library(const Ref<SampleLibrary>& p_library) { library=p_library; + _change_notify(); } Ref<SampleLibrary> SamplePlayer2D::get_sample_library() const { diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index b606634819..2ac3c06031 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -69,9 +69,9 @@ void TouchScreenButton::_notification(int p_what) { case NOTIFICATION_DRAW: { - if (!is_inside_scene()) + if (!is_inside_tree()) return; - if (!get_scene()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility==VISIBILITY_TOUCHSCREEN_ONLY) + if (!get_tree()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility==VISIBILITY_TOUCHSCREEN_ONLY) return; if (finger_pressed!=-1) { @@ -87,13 +87,13 @@ void TouchScreenButton::_notification(int p_what) { } } break; - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { - if (!get_scene()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility==VISIBILITY_TOUCHSCREEN_ONLY) + if (!get_tree()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility==VISIBILITY_TOUCHSCREEN_ONLY) return; update(); - if (!get_scene()->is_editor_hint()) + if (!get_tree()->is_editor_hint()) set_process_input(true); if (action.operator String()!="" && InputMap::get_singleton()->has_action(action)) { @@ -129,7 +129,7 @@ String TouchScreenButton::get_action() const { void TouchScreenButton::_input(const InputEvent& p_event) { - if (!get_scene()) + if (!get_tree()) return; if (p_event.device != 0) @@ -149,7 +149,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) { ie.ID=0; ie.action.action=action_id; ie.action.pressed=false; - get_scene()->input_event(ie); + get_tree()->input_event(ie); } finger_pressed=-1; @@ -193,7 +193,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) { ie.ID=0; ie.action.action=action_id; ie.action.pressed=true; - get_scene()->input_event(ie); + get_tree()->input_event(ie); } update(); @@ -213,7 +213,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) { ie.ID=0; ie.action.action=action_id; ie.action.pressed=false; - get_scene()->input_event(ie); + get_tree()->input_event(ie); } finger_pressed=-1; @@ -268,7 +268,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) { ie.ID=0; ie.action.action=action_id; ie.action.pressed=true; - get_scene()->input_event(ie); + get_tree()->input_event(ie); } update(); @@ -289,7 +289,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) { ie.ID=0; ie.action.action=action_id; ie.action.pressed=false; - get_scene()->input_event(ie); + get_tree()->input_event(ie); } finger_pressed=-1; update(); diff --git a/scene/2d/sound_player_2d.cpp b/scene/2d/sound_player_2d.cpp index 2fffef4e51..ef51295476 100644 --- a/scene/2d/sound_player_2d.cpp +++ b/scene/2d/sound_player_2d.cpp @@ -39,7 +39,7 @@ void SoundPlayer2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { //find the sound space source_rid = SpatialSound2DServer::get_singleton()->source_create(get_world_2d()->get_sound_space()); @@ -56,7 +56,7 @@ void SoundPlayer2D::_notification(int p_what) { SpatialSound2DServer::get_singleton()->source_set_transform(source_rid,get_global_transform()); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (source_rid.is_valid()) SpatialSound2DServer::get_singleton()->free(source_rid); diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 8c3bbfdfc9..82f5a6972a 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -34,6 +34,7 @@ void Sprite::edit_set_pivot(const Point2& p_pivot) { set_offset(p_pivot); + } Point2 Sprite::edit_get_pivot() const { @@ -136,6 +137,7 @@ void Sprite::set_offset(const Point2& p_offset) { offset=p_offset; update(); item_rect_changed(); + _change_notify("offset"); } Point2 Sprite::get_offset() const { @@ -199,6 +201,8 @@ void Sprite::set_frame(int p_frame) { item_rect_changed(); frame=p_frame; + + emit_signal(SceneStringNames::get_singleton()->frame_changed); } int Sprite::get_frame() const { @@ -307,6 +311,8 @@ void Sprite::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&Sprite::set_modulate); ObjectTypeDB::bind_method(_MD("get_modulate"),&Sprite::get_modulate); + ADD_SIGNAL(MethodInfo("frame_changed")); + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); @@ -365,7 +371,7 @@ void ViewportSprite::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (!viewport_path.is_empty()) { @@ -380,7 +386,7 @@ void ViewportSprite::_notification(int p_what) { item_rect_changed(); } } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (texture.is_valid()) { @@ -422,7 +428,7 @@ void ViewportSprite::set_viewport_path(const NodePath& p_viewport) { viewport_path=p_viewport; update(); - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (texture.is_valid()) { diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index eb04ca924f..2b88ee5dba 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -29,11 +29,32 @@ #include "tile_map.h" #include "io/marshalls.h" #include "servers/physics_2d_server.h" +#include "method_bind_ext.inc" + +int TileMap::_get_quadrant_size() const { + + if (y_sort_mode) + return 1; + else + return quadrant_size; +} + void TileMap::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { + + Node2D *c=this; + while(c) { + + navigation=c->cast_to<Navigation2D>(); + if (navigation) { + break; + } + + c=c->get_parent()->cast_to<Node2D>(); + } pending_update=true; _update_dirty_quadrants(); @@ -43,9 +64,28 @@ void TileMap::_notification(int p_what) { } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { _update_quadrant_space(RID()); + for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { + + Quadrant &q=E->get(); + if (navigation) { + for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_remove(E->get().id); + } + q.navpoly_ids.clear(); + } + + for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->free(E->get().id); + } + q.occluder_instances.clear(); + } + + navigation=NULL; + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -62,24 +102,39 @@ void TileMap::_update_quadrant_space(const RID& p_space) { for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_space(q.static_body,p_space); + Physics2DServer::get_singleton()->body_set_space(q.body,p_space); } } void TileMap::_update_quadrant_transform() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; Matrix32 global_transform = get_global_transform(); + Matrix32 nav_rel; + if (navigation) + nav_rel = get_relative_transform(navigation); + for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); Matrix32 xform; xform.set_origin( q.pos ); xform = global_transform * xform; - Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform); + Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform); + + if (navigation) { + for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_set_transform(E->get().id,nav_rel * E->get().xform); + } + } + + for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->canvas_light_occluder_set_transform(E->get().id,global_transform * E->get().xform); + } } } @@ -160,11 +215,39 @@ bool TileMap::get_center_y() const { return center_y; } +void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& p_cell, const Vector2& p_offset, const Size2 &p_sc) { + + Size2 s=p_sc; + Vector2 offset = p_offset; + + if (p_cell.transpose) { + SWAP(xform.elements[0].x, xform.elements[0].y); + SWAP(xform.elements[1].x, xform.elements[1].y); + SWAP(offset.x, offset.y); + SWAP(s.x, s.y); + } + if (p_cell.flip_h) { + xform.elements[0].x=-xform.elements[0].x; + xform.elements[1].x=-xform.elements[1].x; + if (tile_origin==TILE_ORIGIN_TOP_LEFT) + offset.x=s.x-offset.x; + } + if (p_cell.flip_v) { + xform.elements[0].y=-xform.elements[0].y; + xform.elements[1].y=-xform.elements[1].y; + if (tile_origin==TILE_ORIGIN_TOP_LEFT) + offset.y=s.y-offset.y; + } + xform.elements[2].x+=offset.x; + xform.elements[2].y+=offset.y; + +} + void TileMap::_update_dirty_quadrants() { if (!pending_update) return; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (!tile_set.is_valid()) return; @@ -172,15 +255,42 @@ void TileMap::_update_dirty_quadrants() { VisualServer *vs = VisualServer::get_singleton(); Physics2DServer *ps = Physics2DServer::get_singleton(); Vector2 tofs = get_cell_draw_offset(); + Vector2 tcenter = cell_size/2; + Matrix32 nav_rel; + if (navigation) + nav_rel = get_relative_transform(navigation); + + Vector2 qofs; while (dirty_quadrant_list.first()) { Quadrant &q = *dirty_quadrant_list.first()->self(); - vs->canvas_item_clear(q.canvas_item); - ps->body_clear_shapes(q.static_body); + for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) { + + vs->free(E->get()); + } + + q.canvas_items.clear(); + + ps->body_clear_shapes(q.body); int shape_idx=0; + if (navigation) { + for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_remove(E->get().id); + } + q.navpoly_ids.clear(); + } + + for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->free(E->get().id); + } + q.occluder_instances.clear(); + Ref<CanvasItemMaterial> prev_material; + RID prev_canvas_item; + for(int i=0;i<q.cells.size();i++) { Map<PosKey,Cell>::Element *E=tile_map.find( q.cells[i] ); @@ -191,11 +301,35 @@ void TileMap::_update_dirty_quadrants() { Ref<Texture> tex = tile_set->tile_get_texture(c.id); Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id); - Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs; + Vector2 wofs = _map_to_world(E->key().x, E->key().y); + Vector2 offset = wofs - q.pos + tofs; if (!tex.is_valid()) continue; + Ref<CanvasItemMaterial> mat = tile_set->tile_get_material(c.id); + + RID canvas_item; + + if (prev_canvas_item==RID() || prev_material!=mat) { + + canvas_item=vs->canvas_item_create(); + if (mat.is_valid()) + vs->canvas_item_set_material(canvas_item,mat->get_rid()); + vs->canvas_item_set_parent( canvas_item, get_canvas_item() ); + Matrix32 xform; + xform.set_origin( q.pos ); + vs->canvas_item_set_transform( canvas_item, xform ); + q.canvas_items.push_back(canvas_item); + + prev_canvas_item=canvas_item; + prev_material=mat; + + } else { + canvas_item=prev_canvas_item; + } + + Rect2 r = tile_set->tile_get_region(c.id); Size2 s = tex->get_size(); @@ -222,14 +356,32 @@ void TileMap::_update_dirty_quadrants() { if (c.flip_v) rect.size.y=-rect.size.y; + Vector2 center_ofs; - rect.pos+=tile_ofs; - if (r==Rect2()) { + if (tile_origin==TILE_ORIGIN_TOP_LEFT) { + rect.pos+=tile_ofs; + } else if (tile_origin==TILE_ORIGIN_CENTER) { + rect.pos+=tcenter; - tex->draw_rect(q.canvas_item,rect); - } else { + Vector2 center = (s/2) - tile_ofs; + center_ofs=tcenter-(s/2); - tex->draw_rect_region(q.canvas_item,rect,r); + if (c.flip_h) + rect.pos.x-=s.x-center.x; + else + rect.pos.x-=center.x; + + if (c.flip_v) + rect.pos.y-=s.y-center.y; + else + rect.pos.y-=center.y; + } + + + if (r==Rect2()) { + tex->draw_rect(canvas_item,rect,false,Color(1,1,1),c.transpose); + } else { + tex->draw_rect_region(canvas_item,rect,r,Color(1,1,1),c.transpose); } Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id); @@ -243,26 +395,47 @@ void TileMap::_update_dirty_quadrants() { Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id); Matrix32 xform; xform.set_origin(offset.floor()); - if (c.flip_h) { - xform.elements[0]=-xform.elements[0]; - xform.elements[2].x+=s.x-shape_ofs.x; - } else { - xform.elements[2].x+=shape_ofs.x; - } - if (c.flip_v) { - xform.elements[1]=-xform.elements[1]; - xform.elements[2].y+=s.y-shape_ofs.y; - } else { + _fix_cell_transform(xform,c,shape_ofs+center_ofs,s); - xform.elements[2].y+=shape_ofs.y; - } + ps->body_add_shape(q.body,shape->get_rid(),xform); + ps->body_set_shape_metadata(q.body,shape_idx++,Vector2(E->key().x,E->key().y)); + } + } - ps->body_add_shape(q.static_body,shape->get_rid(),xform); - ps->body_set_shape_metadata(q.static_body,shape_idx++,Vector2(E->key().x,E->key().y)); + if (navigation) { + Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id); + Vector2 npoly_ofs = tile_set->tile_get_navigation_polygon_offset(c.id); + Matrix32 xform; + xform.set_origin(offset.floor()+q.pos); + _fix_cell_transform(xform,c,npoly_ofs+center_ofs,s); - } + int pid = navigation->navpoly_create(navpoly,nav_rel * xform); + + Quadrant::NavPoly np; + np.id=pid; + np.xform=xform; + q.navpoly_ids[E->key()]=np; + } + + + Ref<OccluderPolygon2D> occluder=tile_set->tile_get_light_occluder(c.id); + if (occluder.is_valid()) { + + Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id); + Matrix32 xform; + xform.set_origin(offset.floor()+q.pos); + _fix_cell_transform(xform,c,occluder_ofs+center_ofs,s); + + RID orid = VS::get_singleton()->canvas_light_occluder_create(); + VS::get_singleton()->canvas_light_occluder_set_transform(orid,get_global_transform() * xform); + VS::get_singleton()->canvas_light_occluder_set_polygon(orid,occluder->get_rid()); + VS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid,get_canvas()); + Quadrant::Occluder oc; + oc.xform=xform; + oc.id=orid; + q.occluder_instances[E->key()]=oc; } } @@ -278,10 +451,10 @@ void TileMap::_update_dirty_quadrants() { for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - if (q.canvas_item.is_valid()) { - VS::get_singleton()->canvas_item_raise(q.canvas_item); - } + for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) { + VS::get_singleton()->canvas_item_raise(E->get()); + } } quadrant_order_dirty=false; @@ -304,10 +477,10 @@ void TileMap::_recompute_rect_cache() { Rect2 r; - r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size); - r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) ); - r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) ); - r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) ); + r.pos=_map_to_world(E->key().x*_get_quadrant_size(), E->key().y*_get_quadrant_size()); + r.expand_to( _map_to_world(E->key().x*_get_quadrant_size()+_get_quadrant_size(), E->key().y*_get_quadrant_size()) ); + r.expand_to( _map_to_world(E->key().x*_get_quadrant_size()+_get_quadrant_size(), E->key().y*_get_quadrant_size()+_get_quadrant_size()) ); + r.expand_to( _map_to_world(E->key().x*_get_quadrant_size(), E->key().y*_get_quadrant_size()+_get_quadrant_size()) ); if (E==quadrant_map.front()) r_total=r; else @@ -318,7 +491,7 @@ void TileMap::_recompute_rect_cache() { if (r_total==Rect2()) { rect_cache=Rect2(-10,-10,20,20); } else { - rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*quadrant_size); + rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*_get_quadrant_size()); } item_rect_changed(); @@ -334,24 +507,26 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const Matrix32 xform; //xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size); Quadrant q; - q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size); + q.pos = _map_to_world(p_qk.x*_get_quadrant_size(),p_qk.y*_get_quadrant_size()); + q.pos+=get_cell_draw_offset(); + if (tile_origin==TILE_ORIGIN_CENTER) + q.pos+=cell_size/2; + xform.set_origin( q.pos ); - q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); - VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() ); - VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); - q.static_body=Physics2DServer::get_singleton()->body_create(Physics2DServer::BODY_MODE_STATIC); - Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.static_body,get_instance_ID()); - Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,friction); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,bounce); - - if (is_inside_scene()) { +// q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); + q.body=Physics2DServer::get_singleton()->body_create(use_kinematic?Physics2DServer::BODY_MODE_KINEMATIC:Physics2DServer::BODY_MODE_STATIC); + Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body,get_instance_ID()); + Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,friction); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,bounce); + + if (is_inside_tree()) { xform = get_global_transform() * xform; RID space = get_world_2d()->get_space(); - Physics2DServer::get_singleton()->body_set_space(q.static_body,space); + Physics2DServer::get_singleton()->body_set_space(q.body,space); } - Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform); + Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform); rect_cache_dirty=true; quadrant_order_dirty=true; @@ -361,11 +536,28 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const void TileMap::_erase_quadrant(Map<PosKey,Quadrant>::Element *Q) { Quadrant &q=Q->get(); - Physics2DServer::get_singleton()->free(q.static_body); - VisualServer::get_singleton()->free(q.canvas_item); + Physics2DServer::get_singleton()->free(q.body); + for (List<RID>::Element *E=q.canvas_items.front();E;E=E->next()) { + + VisualServer::get_singleton()->free(E->get()); + } + q.canvas_items.clear(); if (q.dirty_list.in_list()) dirty_quadrant_list.remove(&q.dirty_list); + if (navigation) { + for(Map<PosKey,Quadrant::NavPoly>::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_remove(E->get().id); + } + q.navpoly_ids.clear(); + } + + for(Map<PosKey,Quadrant::Occluder>::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->free(E->get().id); + } + q.occluder_instances.clear(); + quadrant_map.erase(Q); rect_cache_dirty=true; } @@ -379,13 +571,13 @@ void TileMap::_make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q) { if (pending_update) return; pending_update=true; - if (!is_inside_scene()) + if (!is_inside_tree()) return; call_deferred("_update_dirty_quadrants"); } -void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) { +void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) { PosKey pk(p_x,p_y); @@ -393,7 +585,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) { if (!E && p_tile==INVALID_CELL) return; //nothing to do - PosKey qk(p_x/quadrant_size,p_y/quadrant_size); + PosKey qk(p_x/_get_quadrant_size(),p_y/_get_quadrant_size()); if (p_tile==INVALID_CELL) { //erase existing tile_map.erase(pk); @@ -421,7 +613,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) { } else { ERR_FAIL_COND(!Q); // quadrant should exist... - if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y) + if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y && E->get().transpose==p_transpose) return; //nothing changed } @@ -432,6 +624,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) { c.id=p_tile; c.flip_h=p_flip_x; c.flip_v=p_flip_y; + c.transpose=p_transpose; _make_quadrant_dirty(Q); @@ -471,6 +664,17 @@ bool TileMap::is_cell_y_flipped(int p_x,int p_y) const { return E->get().flip_v; } +bool TileMap::is_cell_transposed(int p_x,int p_y) const { + + PosKey pk(p_x,p_y); + + const Map<PosKey,Cell>::Element *E=tile_map.find(pk); + + if (!E) + return false; + + return E->get().transpose; +} void TileMap::_recreate_quadrants() { @@ -479,7 +683,7 @@ void TileMap::_recreate_quadrants() { for (Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) { - PosKey qk(E->key().x/quadrant_size,E->key().y/quadrant_size); + PosKey qk(E->key().x/_get_quadrant_size(),E->key().y/_get_quadrant_size()); Map<PosKey,Quadrant>::Element *Q=quadrant_map.find(qk); if (!Q) { @@ -495,6 +699,7 @@ void TileMap::_recreate_quadrants() { } + void TileMap::_clear_quadrants() { while (quadrant_map.size()) { @@ -535,11 +740,12 @@ void TileMap::_set_tile_data(const DVector<int>& p_data) { uint32_t v = decode_uint32(&local[4]); bool flip_h = v&(1<<29); bool flip_v = v&(1<<30); + bool transpose = v&(1<<31); v&=(1<<29)-1; // if (x<-20 || y <-20 || x>4000 || y>4000) // continue; - set_cell(x,y,v,flip_h,flip_v); + set_cell(x,y,v,flip_h,flip_v,transpose); } @@ -562,6 +768,8 @@ DVector<int> TileMap::_get_tile_data() const { val|=(1<<29); if (E->get().flip_v) val|=(1<<30); + if (E->get().transpose) + val|=(1<<31); encode_uint32(val,&ptr[4]); idx+=2; @@ -586,17 +794,29 @@ void TileMap::set_collision_layer_mask(uint32_t p_layer) { for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); + Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer); } } +bool TileMap::get_collision_use_kinematic() const{ + + return use_kinematic; +} + +void TileMap::set_collision_use_kinematic(bool p_use_kinematic) { + + _clear_quadrants(); + use_kinematic=p_use_kinematic; + _recreate_quadrants(); +} + void TileMap::set_collision_friction(float p_friction) { friction=p_friction; for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,p_friction); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,p_friction); } } @@ -612,7 +832,7 @@ void TileMap::set_collision_bounce(float p_bounce){ for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce); } } @@ -647,6 +867,20 @@ void TileMap::set_half_offset(HalfOffset p_half_offset) { emit_signal("settings_changed"); } +void TileMap::set_tile_origin(TileOrigin p_tile_origin) { + + _clear_quadrants(); + tile_origin=p_tile_origin; + _recreate_quadrants(); + emit_signal("settings_changed"); +} + +TileMap::TileOrigin TileMap::get_tile_origin() const{ + + return tile_origin; +} + + Vector2 TileMap::get_cell_draw_offset() const { switch(mode) { @@ -773,6 +1007,21 @@ Vector2 TileMap::world_to_map(const Vector2& p_pos) const{ return ret.floor(); } +void TileMap::set_y_sort_mode(bool p_enable) { + + _clear_quadrants(); + y_sort_mode=p_enable; + VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),y_sort_mode); + _recreate_quadrants(); + emit_signal("settings_changed"); + +} + +bool TileMap::is_y_sort_mode_enabled() const { + + return y_sort_mode; +} + void TileMap::_bind_methods() { @@ -798,12 +1047,21 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size); ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size); + ObjectTypeDB::bind_method(_MD("set_tile_origin","origin"),&TileMap::set_tile_origin); + ObjectTypeDB::bind_method(_MD("get_tile_origin"),&TileMap::get_tile_origin); + ObjectTypeDB::bind_method(_MD("set_center_x","enable"),&TileMap::set_center_x); ObjectTypeDB::bind_method(_MD("get_center_x"),&TileMap::get_center_x); ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y); ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y); + ObjectTypeDB::bind_method(_MD("set_y_sort_mode","enable"),&TileMap::set_y_sort_mode); + ObjectTypeDB::bind_method(_MD("is_y_sort_mode_enabled"),&TileMap::is_y_sort_mode_enabled); + + ObjectTypeDB::bind_method(_MD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic); + ObjectTypeDB::bind_method(_MD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic); + ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask); ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask); @@ -813,7 +1071,7 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce); ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce); - ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell); ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped); ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped); @@ -837,6 +1095,9 @@ void TileMap::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform")); ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center"),_SCS("set_tile_origin"),_SCS("get_tile_origin")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"cell/y_sort"),_SCS("set_y_sort_mode"),_SCS("is_y_sort_mode_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision/use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce")); ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); @@ -851,6 +1112,8 @@ void TileMap::_bind_methods() { BIND_CONSTANT( HALF_OFFSET_X ); BIND_CONSTANT( HALF_OFFSET_Y ); BIND_CONSTANT( HALF_OFFSET_DISABLED ); + BIND_CONSTANT( TILE_ORIGIN_TOP_LEFT ); + BIND_CONSTANT( TILE_ORIGIN_CENTER ); } @@ -870,9 +1133,13 @@ TileMap::TileMap() { bounce=0; mode=MODE_SQUARE; half_offset=HALF_OFFSET_DISABLED; + use_kinematic=false; + navigation=NULL; + y_sort_mode=false; fp_adjust=0.01; fp_adjust=0.01; + tile_origin=TILE_ORIGIN_TOP_LEFT; } TileMap::~TileMap() { diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 4e9e2e7e97..e02c4ee5bb 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -30,6 +30,7 @@ #define TILE_MAP_H #include "scene/2d/node_2d.h" +#include "scene/2d/navigation2d.h" #include "scene/resources/tile_set.h" #include "self_list.h" #include "vset.h" @@ -51,6 +52,12 @@ public: HALF_OFFSET_DISABLED, }; + enum TileOrigin { + TILE_ORIGIN_TOP_LEFT, + TILE_ORIGIN_CENTER + }; + + private: Ref<TileSet> tile_set; @@ -60,6 +67,8 @@ private: Mode mode; Matrix32 custom_transform; HalfOffset half_offset; + bool use_kinematic; + Navigation2D *navigation; union PosKey { @@ -85,6 +94,7 @@ private: int32_t id:24; bool flip_h:1; bool flip_v:1; + bool transpose:1; }; uint32_t _u32t; @@ -96,15 +106,29 @@ private: struct Quadrant { Vector2 pos; - RID canvas_item; - RID static_body; + List<RID> canvas_items; + RID body; SelfList<Quadrant> dirty_list; + struct NavPoly { + int id; + Matrix32 xform; + }; + + struct Occluder { + RID id; + Matrix32 xform; + }; + + + Map<PosKey,NavPoly> navpoly_ids; + Map<PosKey,Occluder> occluder_instances; + VSet<PosKey> cells; - void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells; } - Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells;} + void operator=(const Quadrant& q) { pos=q.pos; canvas_items=q.canvas_items; body=q.body; cells=q.cells; navpoly_ids=q.navpoly_ids; occluder_instances=q.occluder_instances; } + Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_items=q.canvas_items; body=q.body; cells=q.cells; occluder_instances=q.occluder_instances; navpoly_ids=q.navpoly_ids;} Quadrant() : dirty_list(this) {} }; @@ -117,11 +141,14 @@ private: Rect2 rect_cache; bool rect_cache_dirty; bool quadrant_order_dirty; + bool y_sort_mode; float fp_adjust; float friction; float bounce; uint32_t collision_layer; + TileOrigin tile_origin; + void _fix_cell_transform(Matrix32& xform, const Cell& p_cell, const Vector2 &p_offset, const Size2 &p_sc); Map<PosKey,Quadrant>::Element *_create_quadrant(const PosKey& p_qk); void _erase_quadrant(Map<PosKey,Quadrant>::Element *Q); @@ -133,6 +160,9 @@ private: void _update_quadrant_transform(); void _recompute_rect_cache(); + _FORCE_INLINE_ int _get_quadrant_size() const; + + void _set_tile_data(const DVector<int>& p_data); DVector<int> _get_tile_data() const; @@ -167,16 +197,20 @@ public: void set_center_y(bool p_enable); bool get_center_y() const; - void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false); + void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false,bool p_transpose=false); int get_cell(int p_x,int p_y) const; bool is_cell_x_flipped(int p_x,int p_y) const; bool is_cell_y_flipped(int p_x,int p_y) const; + bool is_cell_transposed(int p_x,int p_y) const; Rect2 get_item_rect() const; void set_collision_layer_mask(uint32_t p_layer); uint32_t get_collision_layer_mask() const; + void set_collision_use_kinematic(bool p_use_kinematic); + bool get_collision_use_kinematic() const; + void set_collision_friction(float p_friction); float get_collision_friction() const; @@ -189,6 +223,9 @@ public: void set_half_offset(HalfOffset p_half_offset); HalfOffset get_half_offset() const; + void set_tile_origin(TileOrigin p_tile_origin); + TileOrigin get_tile_origin() const; + void set_custom_transform(const Matrix32& p_xform); Matrix32 get_custom_transform() const; @@ -198,6 +235,9 @@ public: Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const; Vector2 world_to_map(const Vector2& p_pos) const; + void set_y_sort_mode(bool p_enable); + bool is_y_sort_mode_enabled() const; + void clear(); TileMap(); @@ -206,5 +246,6 @@ public: VARIANT_ENUM_CAST(TileMap::Mode); VARIANT_ENUM_CAST(TileMap::HalfOffset); +VARIANT_ENUM_CAST(TileMap::TileOrigin); #endif // TILE_MAP_H diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index e5eb193f6f..abaaf3262a 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -32,6 +32,7 @@ #include "scene/2d/physics_body_2d.h" #include "scene/animation/animation_player.h" #include "scene/scene_string_names.h" +#include "particles_2d.h" void VisibilityNotifier2D::_enter_viewport(Viewport* p_viewport) { @@ -64,8 +65,13 @@ void VisibilityNotifier2D::_exit_viewport(Viewport* p_viewport){ void VisibilityNotifier2D::set_rect(const Rect2& p_rect){ rect=p_rect; - if (is_inside_scene()) + if (is_inside_tree()) { get_world_2d()->_update_notifier(this,get_global_transform().xform(rect)); + if (get_tree()->is_editor_hint()) { + update(); + item_rect_changed(); + } + } _change_notify("rect"); } @@ -85,7 +91,7 @@ void VisibilityNotifier2D::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { //get_world_2d()-> get_world_2d()->_register_notifier(this,get_global_transform().xform(rect)); @@ -97,12 +103,12 @@ void VisibilityNotifier2D::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - if (get_scene()->is_editor_hint()) { + if (get_tree()->is_editor_hint()) { draw_rect(rect,Color(1,0.5,1,0.2)); } } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { get_world_2d()->_remove_notifier(this); } break; @@ -188,9 +194,18 @@ void VisibilityEnabler2D::_find_nodes(Node* p_node) { } + if (enabler[ENABLER_PAUSE_PARTICLES]) { + + Particles2D *ps = p_node->cast_to<Particles2D>(); + if (ps) { + add=true; + } + + } + if (add) { - p_node->connect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed",varray(p_node),CONNECT_ONESHOT); + p_node->connect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed",varray(p_node),CONNECT_ONESHOT); nodes[p_node]=meta; _change_node_state(p_node,false); } @@ -207,9 +222,9 @@ void VisibilityEnabler2D::_find_nodes(Node* p_node) { void VisibilityEnabler2D::_notification(int p_what){ - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) return; @@ -222,9 +237,9 @@ void VisibilityEnabler2D::_notification(int p_what){ } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) return; @@ -235,7 +250,7 @@ void VisibilityEnabler2D::_notification(int p_what){ if (!visible) _change_node_state(E->key(),true); - E->key()->disconnect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed"); + E->key()->disconnect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed"); } nodes.clear(); @@ -271,6 +286,15 @@ void VisibilityEnabler2D::_change_node_state(Node* p_node,bool p_enabled) { } } + { + Particles2D *ps=p_node->cast_to<Particles2D>(); + + if (ps) { + + ps->set_emitting(p_enabled); + } + } + } @@ -292,9 +316,11 @@ void VisibilityEnabler2D::_bind_methods(){ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS ); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_particles"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_PARTICLES); BIND_CONSTANT( ENABLER_FREEZE_BODIES ); BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS ); + BIND_CONSTANT( ENABLER_PAUSE_PARTICLES ); BIND_CONSTANT( ENABLER_MAX); } @@ -320,3 +346,4 @@ VisibilityEnabler2D::VisibilityEnabler2D() { } + diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index cdf52ecb27..621c470d5d 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -73,6 +73,7 @@ public: enum Enabler { ENABLER_PAUSE_ANIMATIONS, ENABLER_FREEZE_BODIES, + ENABLER_PAUSE_PARTICLES, ENABLER_MAX }; diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 7370c36eb7..9cdd24d102 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -94,7 +94,7 @@ real_t Area::get_priority() const{ } -void Area::_body_enter_scene(ObjectID p_id) { +void Area::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; @@ -102,9 +102,9 @@ void Area::_body_enter_scene(ObjectID p_id) { Map<ObjectID,BodyState>::Element *E=body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_scene); + ERR_FAIL_COND(E->get().in_tree); - E->get().in_scene=true; + E->get().in_tree=true; emit_signal(SceneStringNames::get_singleton()->body_enter,node); for(int i=0;i<E->get().shapes.size();i++) { @@ -113,15 +113,16 @@ void Area::_body_enter_scene(ObjectID p_id) { } -void Area::_body_exit_scene(ObjectID p_id) { +void Area::_body_exit_tree(ObjectID p_id) { + Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; ERR_FAIL_COND(!node); Map<ObjectID,BodyState>::Element *E=body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_scene); - E->get().in_scene=false; + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree=false; emit_signal(SceneStringNames::get_singleton()->body_exit,node); for(int i=0;i<E->get().shapes.size();i++) { @@ -132,6 +133,7 @@ void Area::_body_exit_scene(ObjectID p_id) { void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape) { + bool body_in = p_status==PhysicsServer::AREA_BODY_ADDED; ObjectID objid=p_instance; @@ -142,16 +144,18 @@ void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_bod ERR_FAIL_COND(!body_in && !E); + locked=true; + if (body_in) { if (!E) { E = body_map.insert(objid,BodyState()); E->get().rc=0; - E->get().in_scene=node && node->is_inside_scene(); + E->get().in_tree=node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid)); - if (E->get().in_scene) { + node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree,make_binds(objid)); + if (E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_enter,node); } } @@ -162,7 +166,7 @@ void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_bod E->get().shapes.insert(ShapePair(p_body_shape,p_area_shape)); - if (E->get().in_scene) { + if (E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_area_shape); } @@ -178,9 +182,9 @@ void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_bod if (E->get().rc==0) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); - node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); - if (E->get().in_scene) + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); + if (E->get().in_tree) emit_signal(SceneStringNames::get_singleton()->body_exit,obj); } @@ -188,7 +192,7 @@ void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_bod eraseit=true; } - if (node && E->get().in_scene) { + if (node && E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_area_shape); } @@ -197,11 +201,19 @@ void Area::_body_inout(int p_status,const RID& p_body, int p_instance, int p_bod } + locked=false; + + } void Area::_clear_monitoring() { + if (locked) { + ERR_EXPLAIN("This function can't be used during the in/out signal."); + } + ERR_FAIL_COND(locked); + Map<ObjectID,BodyState> bmcopy = body_map; body_map.clear(); //disconnect all monitored stuff @@ -211,7 +223,7 @@ void Area::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = obj ? obj->cast_to<Node>() : NULL; ERR_CONTINUE(!node); - if (!E->get().in_scene) + if (!E->get().in_tree) continue; for(int i=0;i<E->get().shapes.size();i++) { @@ -221,20 +233,25 @@ void Area::_clear_monitoring() { emit_signal(SceneStringNames::get_singleton()->body_exit,obj); - node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); - node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); } } void Area::_notification(int p_what) { - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { _clear_monitoring(); } } void Area::set_enable_monitoring(bool p_enable) { + if (locked) { + ERR_EXPLAIN("This function can't be used during the in/out signal."); + } + ERR_FAIL_COND(locked); + if (p_enable==monitoring) return; @@ -255,11 +272,29 @@ bool Area::is_monitoring_enabled() const { } +Array Area::get_overlapping_bodies() const { + + ERR_FAIL_COND_V(!monitoring,Array()); + Array ret; + ret.resize(body_map.size()); + int idx=0; + for (const Map<ObjectID,BodyState>::Element *E=body_map.front();E;E=E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize( ret.size() -1 ); //ops + } else { + ret[idx++]=obj; + } + + } + + return ret; +} void Area::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_body_enter_scene","id"),&Area::_body_enter_scene); - ObjectTypeDB::bind_method(_MD("_body_exit_scene","id"),&Area::_body_exit_scene); + ObjectTypeDB::bind_method(_MD("_body_enter_tree","id"),&Area::_body_enter_tree); + ObjectTypeDB::bind_method(_MD("_body_exit_tree","id"),&Area::_body_exit_tree); ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area::set_space_override_mode); ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area::get_space_override_mode); @@ -283,6 +318,8 @@ void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring); ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled); + ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area::get_overlapping_bodies); + ObjectTypeDB::bind_method(_MD("_body_inout"),&Area::_body_inout); @@ -305,6 +342,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru space_override=SPACE_OVERRIDE_DISABLED; set_gravity(9.8);; + locked=false; set_gravity_vector(Vector3(0,-1,0)); gravity_is_point=false; density=0.1; diff --git a/scene/3d/area.h b/scene/3d/area.h index 5558e2c719..40c6d24b5c 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -52,12 +52,13 @@ private: real_t density; int priority; bool monitoring; + bool locked; void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape); - void _body_enter_scene(ObjectID p_id); - void _body_exit_scene(ObjectID p_id); + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); struct ShapePair { @@ -77,7 +78,7 @@ private: struct BodyState { int rc; - bool in_scene; + bool in_tree; VSet<ShapePair> shapes; }; @@ -112,6 +113,8 @@ public: void set_enable_monitoring(bool p_enable); bool is_monitoring_enabled() const; + Array get_overlapping_bodies() const; + Area(); ~Area(); diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index c1cc1f6b68..b55093a779 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -63,3 +63,81 @@ BakedLightInstance::BakedLightInstance() { } +///////////////////////// + + +void BakedLightSampler::set_param(Param p_param,float p_value) { + ERR_FAIL_INDEX(p_param,PARAM_MAX); + params[p_param]=p_value; + VS::get_singleton()->baked_light_sampler_set_param(base,VS::BakedLightSamplerParam(p_param),p_value); +} + +float BakedLightSampler::get_param(Param p_param) const{ + + ERR_FAIL_INDEX_V(p_param,PARAM_MAX,0); + return params[p_param]; + +} + +void BakedLightSampler::set_resolution(int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>32); + resolution=p_resolution; + VS::get_singleton()->baked_light_sampler_set_resolution(base,resolution); +} +int BakedLightSampler::get_resolution() const { + + return resolution; +} + +AABB BakedLightSampler::get_aabb() const { + + float r = get_param(PARAM_RADIUS); + return AABB( Vector3(-r,-r,-r),Vector3(r*2,r*2,r*2)); +} +DVector<Face3> BakedLightSampler::get_faces(uint32_t p_usage_flags) const { + return DVector<Face3>(); +} + +void BakedLightSampler::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_param","param","value"),&BakedLightSampler::set_param); + ObjectTypeDB::bind_method(_MD("get_param","param"),&BakedLightSampler::get_param); + + ObjectTypeDB::bind_method(_MD("set_resolution","resolution"),&BakedLightSampler::set_resolution); + ObjectTypeDB::bind_method(_MD("get_resolution"),&BakedLightSampler::get_resolution); + + + BIND_CONSTANT( PARAM_RADIUS ); + BIND_CONSTANT( PARAM_STRENGTH ); + BIND_CONSTANT( PARAM_ATTENUATION ); + BIND_CONSTANT( PARAM_DETAIL_RATIO ); + BIND_CONSTANT( PARAM_MAX ); + + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_RADIUS); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_STRENGTH); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION); + ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); +// ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),_SCS("set_resolution"),_SCS("get_resolution")); + +} + +BakedLightSampler::BakedLightSampler() { + + base = VS::get_singleton()->baked_light_sampler_create(); + set_base(base); + + params[PARAM_RADIUS]=1.0; + params[PARAM_STRENGTH]=1.0; + params[PARAM_ATTENUATION]=1.0; + params[PARAM_DETAIL_RATIO]=0.1; + resolution=16; + + +} + +BakedLightSampler::~BakedLightSampler(){ + + VS::get_singleton()->free(base); +} diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h index b904ced9a7..0694c813ce 100644 --- a/scene/3d/baked_light_instance.h +++ b/scene/3d/baked_light_instance.h @@ -30,4 +30,46 @@ public: BakedLightInstance(); }; + + +class BakedLightSampler : public VisualInstance { + OBJ_TYPE(BakedLightSampler,VisualInstance); + + +public: + + enum Param { + PARAM_RADIUS=VS::BAKED_LIGHT_SAMPLER_RADIUS, + PARAM_STRENGTH=VS::BAKED_LIGHT_SAMPLER_STRENGTH, + PARAM_ATTENUATION=VS::BAKED_LIGHT_SAMPLER_ATTENUATION, + PARAM_DETAIL_RATIO=VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + PARAM_MAX=VS::BAKED_LIGHT_SAMPLER_MAX + }; + + + +protected: + + RID base; + float params[PARAM_MAX]; + int resolution; + static void _bind_methods(); +public: + + virtual AABB get_aabb() const; + virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + + void set_param(Param p_param,float p_value); + float get_param(Param p_param) const; + + void set_resolution(int p_resolution); + int get_resolution() const; + + BakedLightSampler(); + ~BakedLightSampler(); +}; + +VARIANT_ENUM_CAST( BakedLightSampler::Param ); + + #endif // BAKED_LIGHT_H diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp index b291ce7c72..287515dce7 100644 --- a/scene/3d/body_shape.cpp +++ b/scene/3d/body_shape.cpp @@ -44,7 +44,6 @@ void CollisionShape::_update_body() { - if (get_parent() && get_parent()->cast_to<CollisionObject>()) get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children(); @@ -72,7 +71,7 @@ void CollisionShape::make_convex_from_brothers() { } } - +/* void CollisionShape::_update_indicator() { @@ -300,9 +299,12 @@ void CollisionShape::_update_indicator() { } - +*/ void CollisionShape::_add_to_collision_object(Object* p_cshape) { + if (unparenting) + return; + CollisionObject *co=p_cshape->cast_to<CollisionObject>(); ERR_FAIL_COND(!co); @@ -318,22 +320,25 @@ void CollisionShape::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_WORLD: { - indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); + case NOTIFICATION_ENTER_TREE: { + unparenting=false; + + //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); } break; case NOTIFICATION_TRANSFORM_CHANGED: { - VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); + // VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); if (updating_body) { _update_body(); } } break; - case NOTIFICATION_EXIT_WORLD: { - if (indicator_instance.is_valid()) { + case NOTIFICATION_EXIT_TREE: { + /* if (indicator_instance.is_valid()) { VisualServer::get_singleton()->free(indicator_instance); indicator_instance=RID(); - } + }*/ } break; case NOTIFICATION_UNPARENTED: { + unparenting=true; if (updating_body) _update_body(); } break; @@ -411,15 +416,16 @@ bool CollisionShape::is_trigger() const{ CollisionShape::CollisionShape() { - indicator = VisualServer::get_singleton()->mesh_create(); + //indicator = VisualServer::get_singleton()->mesh_create(); updating_body=true; + unparenting=false; trigger=false; } CollisionShape::~CollisionShape() { if (!shape.is_null()) shape->unregister_owner(this); - VisualServer::get_singleton()->free(indicator); + //VisualServer::get_singleton()->free(indicator); } #if 0 diff --git a/scene/3d/body_shape.h b/scene/3d/body_shape.h index d1cb229f70..b3fbaca178 100644 --- a/scene/3d/body_shape.h +++ b/scene/3d/body_shape.h @@ -37,19 +37,23 @@ class CollisionShape : public Spatial { OBJ_TYPE( CollisionShape, Spatial ); OBJ_CATEGORY("3D Physics Nodes"); + Ref<Shape> shape; + + /* RID _get_visual_instance_rid() const; - Ref<Shape> shape; void _update_indicator(); RID material; RID indicator; RID indicator_instance; + */ void resource_changed(RES res); bool updating_body; + bool unparenting; bool trigger; void _update_body(); diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp index cbc4abb7a9..6bbb957d25 100644 --- a/scene/3d/bone_attachment.cpp +++ b/scene/3d/bone_attachment.cpp @@ -102,12 +102,12 @@ void BoneAttachment::_check_unbind() { void BoneAttachment::set_bone_name(const String& p_name) { - if (is_inside_scene()) + if (is_inside_tree()) _check_unbind(); bone_name=p_name; - if (is_inside_scene()) + if (is_inside_tree()) _check_bind(); } @@ -120,11 +120,11 @@ void BoneAttachment::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { _check_bind(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { _check_unbind(); } break; diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 93a27f7ac1..db69182ca0 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -86,6 +86,10 @@ bool Camera::_set(const StringName& p_name, const Variant& p_value) { set_keep_aspect_mode(KeepAspect(int(p_value))); else if (p_name=="vaspect") set_keep_aspect_mode(p_value?KEEP_WIDTH:KEEP_HEIGHT); + else if (p_name=="h_offset") + h_offset=p_value; + else if (p_name=="v_offset") + v_offset=p_value; else if (p_name=="current") { if (p_value.operator bool()) { make_current(); @@ -121,13 +125,17 @@ bool Camera::_get(const StringName& p_name,Variant &r_ret) const { r_ret= int(keep_aspect); else if (p_name=="current") { - if (is_inside_scene() && get_scene()->is_editor_hint()) { + if (is_inside_tree() && get_tree()->is_editor_hint()) { r_ret=current; } else { r_ret=is_current(); } } else if (p_name=="visible_layers") { r_ret=get_visible_layers(); + } else if (p_name=="h_offset") { + r_ret=get_h_offset(); + } else if (p_name=="v_offset") { + r_ret=get_v_offset(); } else if (p_name=="environment") { r_ret=get_environment(); } else @@ -144,11 +152,11 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const { case PROJECTION_PERSPECTIVE: { - p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_NOEDITOR) ); + p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_NOEDITOR) ); if (keep_aspect==KEEP_WIDTH) - p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) ); + p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) ); else - p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) ); + p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) ); } break; @@ -170,19 +178,23 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const { p_list->push_back( PropertyInfo( Variant::BOOL, "current" ) ); p_list->push_back( PropertyInfo( Variant::INT, "visible_layers",PROPERTY_HINT_ALL_FLAGS ) ); p_list->push_back( PropertyInfo( Variant::OBJECT, "environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment" ) ); + p_list->push_back( PropertyInfo( Variant::REAL, "h_offset" ) ); + p_list->push_back( PropertyInfo( Variant::REAL, "v_offset" ) ); } void Camera::_update_camera() { Transform tr = get_camera_transform(); + tr.origin+=tr.basis.get_axis(1)*v_offset; + tr.origin+=tr.basis.get_axis(0)*h_offset; VisualServer::get_singleton()->camera_set_transform( camera, tr ); // here goes listener stuff // if (viewport_ptr && is_inside_scene() && is_current()) // viewport_ptr->_camera_transform_changed_notify(); - if (is_inside_scene() && is_current()) { + if (is_inside_tree() && is_current()) { if (viewport_ptr) { viewport_ptr->_camera_transform_changed_notify(); } @@ -309,7 +321,7 @@ void Camera::make_current() { current=true; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (viewport_ptr) { @@ -324,7 +336,7 @@ void Camera::_camera_make_next_current(Node *p_exclude) { if (this==p_exclude) return; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (get_viewport()->get_camera()!=NULL) return; @@ -336,14 +348,14 @@ void Camera::_camera_make_next_current(Node *p_exclude) { void Camera::clear_current() { current=false; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (viewport_ptr) { if (viewport_ptr->get_camera()==this) { viewport_ptr->_set_camera(NULL); //a group is used beause this needs to be in order to be deterministic - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this); } } @@ -352,7 +364,7 @@ void Camera::clear_current() { bool Camera::is_current() const { - if (is_inside_scene()) { + if (is_inside_tree()) { if (viewport_ptr) return viewport_ptr->get_camera()==this; } else @@ -462,12 +474,20 @@ Vector3 Camera::project_ray_normal(const Point2& p_pos) const { Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { - if (!is_inside_scene()) { + if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); - ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); + ERR_FAIL_COND_V(!is_inside_tree(),Vector3()); } + +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif Vector3 ray; @@ -479,23 +499,28 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const { cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); float screen_w,screen_h; cm.get_viewport_size(screen_w,screen_h); - ray=Vector3( ((p_pos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); + ray=Vector3( ((cpos.x/viewport_size.width)*2.0-1.0)*screen_w, ((1.0-(cpos.y/viewport_size.height))*2.0-1.0)*screen_h,-near).normalized(); } - return ray; }; Vector3 Camera::project_ray_origin(const Point2& p_pos) const { - if (!is_inside_scene()) { + if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); - ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); + ERR_FAIL_COND_V(!is_inside_tree(),Vector3()); } +#if 0 Size2 viewport_size = viewport_ptr->get_visible_rect().size; + Vector2 cpos = p_pos; +#else + Size2 viewport_size = viewport_ptr->get_camera_rect_size(); + Vector2 cpos = viewport_ptr->get_camera_coords(p_pos); +#endif ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() ); // float aspect = viewport_size.x / viewport_size.y; @@ -505,7 +530,7 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { return get_camera_transform().origin; } else { - Vector2 pos = p_pos / viewport_size; + Vector2 pos = cpos / viewport_size; float vsize,hsize; if (keep_aspect==KEEP_WIDTH) { vsize = size/viewport_size.get_aspect(); @@ -516,6 +541,8 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { } + + Vector3 ray; ray.x = pos.x * (hsize) - hsize/2; ray.y = (1.0 - pos.y) * (vsize) - vsize/2; @@ -527,9 +554,9 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const { Point2 Camera::unproject_position(const Vector3& p_pos) const { - if (!is_inside_scene()) { + if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); - ERR_FAIL_COND_V(!is_inside_scene(),Vector2()); + ERR_FAIL_COND_V(!is_inside_tree(),Vector2()); } Size2 viewport_size = viewport_ptr->get_visible_rect().size; @@ -558,9 +585,9 @@ Point2 Camera::unproject_position(const Vector3& p_pos) const { Vector3 Camera::project_position(const Point2& p_point) const { - if (!is_inside_scene()) { + if (!is_inside_tree()) { ERR_EXPLAIN("Camera is not inside scene."); - ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); + ERR_FAIL_COND_V(!is_inside_tree(),Vector3()); } Size2 viewport_size = viewport_ptr->get_visible_rect().size; @@ -577,7 +604,7 @@ Vector3 Camera::project_position(const Point2& p_point) const { Vector2 point; point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0; - point.y = (p_point.y/viewport_size.y) * 2.0 - 1.0; + point.y = (1.0-(p_point.y/viewport_size.y)) * 2.0 - 1.0; point*=vp_size; Vector3 p(point.x,point.y,-near); @@ -653,8 +680,6 @@ void Camera::_bind_methods() { ObjectTypeDB::bind_method( _MD("get_projection"),&Camera::get_projection ); ObjectTypeDB::bind_method( _MD("set_visible_layers","mask"),&Camera::set_visible_layers ); ObjectTypeDB::bind_method( _MD("get_visible_layers"),&Camera::get_visible_layers ); - ObjectTypeDB::bind_method( _MD("look_at","target","up"),&Camera::look_at ); - ObjectTypeDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Camera::look_at_from_pos ); ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&Camera::set_environment); ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment); ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode); @@ -725,21 +750,26 @@ Vector<Plane> Camera::get_frustum() const { -void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) { - Transform lookat; - lookat.origin=get_camera_transform().origin; - lookat=lookat.looking_at(p_target,p_up_normal); - set_global_transform(lookat); +void Camera::set_v_offset(float p_offset) { + + v_offset=p_offset; + _update_camera();; } -void Camera::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal) { +float Camera::get_v_offset() const { + + return v_offset; +} + +void Camera::set_h_offset(float p_offset) { + h_offset=p_offset; + _update_camera(); +} - Transform lookat; - lookat.origin=p_pos; - lookat=lookat.looking_at(p_target,p_up_normal); - set_global_transform(lookat); +float Camera::get_h_offset() const { + return h_offset; } @@ -757,6 +787,8 @@ Camera::Camera() { set_perspective(60.0,0.1,100.0); keep_aspect=KEEP_HEIGHT; layers=0xfffff; + v_offset=0; + h_offset=0; VisualServer::get_singleton()->camera_set_visible_layers(camera,layers); //active=false; } diff --git a/scene/3d/camera.h b/scene/3d/camera.h index bac8173bb7..de03282021 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -61,6 +61,8 @@ private: float fov; float size; float near,far; + float v_offset; + float h_offset; KeepAspect keep_aspect; RID camera; @@ -137,8 +139,12 @@ public: void set_keep_aspect_mode(KeepAspect p_aspect); KeepAspect get_keep_aspect_mode() const; - void look_at(const Vector3& p_target, const Vector3& p_up_normal); - void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal); + + void set_v_offset(float p_offset); + float get_v_offset() const; + + void set_h_offset(float p_offset); + float get_h_offset() const; Camera(); diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index e9d3e73906..9c388a2883 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -47,6 +47,11 @@ void CollisionObject::_notification(int p_what) { case NOTIFICATION_ENTER_WORLD: { + if (area) + PhysicsServer::get_singleton()->area_set_transform(rid,get_global_transform()); + else + PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform()); + RID space = get_world()->get_space(); if (area) { PhysicsServer::get_singleton()->area_set_space(rid,space); @@ -160,13 +165,13 @@ bool CollisionObject::_get(const StringName& p_name,Variant &r_ret) const { void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const { - p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR) ); + p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); for(int i=0;i<shapes.size();i++) { String path="shapes/"+itos(i)+"/"; - p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) ); - p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); - p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); + p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); + p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); + p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) ); } } @@ -199,9 +204,9 @@ void CollisionObject::_mouse_exit() { } void CollisionObject::_update_pickable() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; - bool pickable = ray_pickable && is_inside_scene() && is_visible(); + bool pickable = ray_pickable && is_inside_tree() && is_visible(); if (area) PhysicsServer::get_singleton()->area_set_ray_pickable(rid,pickable); else diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 5a613f360a..4ab1a1a1ab 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -86,7 +86,7 @@ void CollisionPolygon::_notification(int p_what) { switch(p_what) { case NOTIFICATION_TRANSFORM_CHANGED: { - if (!is_inside_scene()) + if (!is_inside_tree()) break; _update_parent(); diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index a4206894ff..651d20ae71 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -127,7 +127,7 @@ void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color); ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); - ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex); + ObjectTypeDB::bind_method(_MD("add_vertex","pos"),&ImmediateGeometry::add_vertex); ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius"),&ImmediateGeometry::add_sphere); ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp index 4d8c9cf7a5..2f35164f49 100644 --- a/scene/3d/interpolated_camera.cpp +++ b/scene/3d/interpolated_camera.cpp @@ -32,9 +32,9 @@ void InterpolatedCamera::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { - if (get_scene()->is_editor_hint() && enabled) + if (get_tree()->is_editor_hint() && enabled) set_fixed_process(false); } break; @@ -50,7 +50,7 @@ void InterpolatedCamera::_notification(int p_what) { float delta = speed*get_process_delta_time(); Transform target_xform = node->get_global_transform(); - Transform local_transform = get_transform(); + Transform local_transform = get_global_transform(); local_transform = local_transform.interpolate_with(target_xform,delta); set_global_transform(local_transform); @@ -109,7 +109,7 @@ void InterpolatedCamera::set_interpolation_enabled(bool p_enable) { return; enabled=p_enable; if (p_enable) { - if (is_inside_scene() && get_scene()->is_editor_hint()) + if (is_inside_tree() && get_tree()->is_editor_hint()) return; set_process(true); } else @@ -136,7 +136,7 @@ void InterpolatedCamera::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_target_path","target_path"),&InterpolatedCamera::set_target_path); ObjectTypeDB::bind_method(_MD("get_target_path"),&InterpolatedCamera::get_target_path); - ObjectTypeDB::bind_method(_MD("set_target","target"),&InterpolatedCamera::_set_target); + ObjectTypeDB::bind_method(_MD("set_target","target:Camera"),&InterpolatedCamera::_set_target); ObjectTypeDB::bind_method(_MD("set_speed","speed"),&InterpolatedCamera::set_speed); ObjectTypeDB::bind_method(_MD("get_speed"),&InterpolatedCamera::get_speed); diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index e51a9764f6..037350f99a 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -415,11 +415,11 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo float energy=1.0; - if (p_constant>0) + /*if (p_constant>0) energy=1.0/p_constant; //energy is this else energy=8.0; // some high number.. - +*/ if (radius==10000) radius=100; //bug? @@ -432,7 +432,7 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo void Light::_update_visibility() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; @@ -440,10 +440,10 @@ bool editor_ok=true; #ifdef TOOLS_ENABLED if (editor_only) { - if (!get_scene()->is_editor_hint()) { + if (!get_tree()->is_editor_hint()) { editor_ok=false; } else { - editor_ok = (get_scene()->get_edited_scene_root() && (this==get_scene()->get_edited_scene_root() || get_owner()==get_scene()->get_edited_scene_root())); + editor_ok = (get_tree()->get_edited_scene_root() && (this==get_tree()->get_edited_scene_root() || get_owner()==get_tree()->get_edited_scene_root())); } } #endif @@ -456,7 +456,7 @@ bool editor_ok=true; void Light::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE || p_what==NOTIFICATION_VISIBILITY_CHANGED) { + if (p_what==NOTIFICATION_ENTER_TREE || p_what==NOTIFICATION_VISIBILITY_CHANGED) { _update_visibility(); } } @@ -669,7 +669,7 @@ void SpotLight::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,89.9,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ANGLE ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION ); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "spot_attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION ); } diff --git a/scene/3d/light.h b/scene/3d/light.h index 6fb57a269b..5b10a4d816 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -49,7 +49,7 @@ public: PARAM_ENERGY=VisualServer::LIGHT_PARAM_ENERGY, PARAM_ATTENUATION=VisualServer::LIGHT_PARAM_ATTENUATION, PARAM_SPOT_ANGLE=VisualServer::LIGHT_PARAM_SPOT_ANGLE, - PARAM_SPOT_ATTENUATION=VisualServer::LIGHT_PARAM_ATTENUATION, + PARAM_SPOT_ATTENUATION=VisualServer::LIGHT_PARAM_SPOT_ATTENUATION, PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING, PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET, PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE, diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 72d63fa006..d7266e5df7 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -126,7 +126,7 @@ void MeshInstance::_resolve_skeleton_path(){ void MeshInstance::set_skeleton_path(const NodePath &p_skeleton) { skeleton_path = p_skeleton; - if (!is_inside_scene()) + if (!is_inside_tree()) return; _resolve_skeleton_path(); } @@ -226,7 +226,7 @@ void MeshInstance::create_convex_collision() { void MeshInstance::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { _resolve_skeleton_path(); } } diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index d22198d47e..6612d6bf12 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -182,6 +182,41 @@ void Navigation::navmesh_remove(int p_id){ } +void Navigation::_clip_path(Vector<Vector3>& path, Polygon *from_poly, const Vector3& p_to_point, Polygon* p_to_poly) { + + Vector3 from = path[path.size()-1]; + + if (from.distance_to(p_to_point)<CMP_EPSILON) + return; + Plane cut_plane; + cut_plane.normal = (from-p_to_point).cross(up); + if (cut_plane.normal==Vector3()) + return; + cut_plane.normal.normalize(); + cut_plane.d = cut_plane.normal.dot(from); + + + while(from_poly!=p_to_poly) { + + int pe = from_poly->prev_edge; + Vector3 a = _get_vertex(from_poly->edges[pe].point); + Vector3 b = _get_vertex(from_poly->edges[(pe+1)%from_poly->edges.size()].point); + + from_poly=from_poly->edges[pe].C; + ERR_FAIL_COND(!from_poly); + + if (a.distance_to(b)>CMP_EPSILON) { + + Vector3 inters; + if (cut_plane.intersects_segment(a,b,&inters)) { + if (inters.distance_to(p_to_point)>CMP_EPSILON && inters.distance_to(path[path.size()-1])>CMP_EPSILON) { + path.push_back(inters); + } + } + } + } +} + Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector3& p_end, bool p_optimize) { @@ -379,9 +414,12 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector portal_left=left; } else { - apex_point=portal_right; + _clip_path(path,apex_poly,portal_right,right_poly); + + apex_point=portal_right; p=right_poly; left_poly=p; + apex_poly=p; portal_left=apex_point; portal_right=apex_point; path.push_back(apex_point); @@ -396,9 +434,12 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector portal_right=right; } else { + _clip_path(path,apex_poly,portal_left,left_poly); + apex_point=portal_left; p=left_poly; right_poly=p; + apex_poly=p; portal_right=apex_point; portal_left=apex_point; path.push_back(apex_point); @@ -449,10 +490,10 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector } -Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to) { +Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to,const bool& p_use_collision) { - bool use_collision=false; + bool use_collision=p_use_collision; Vector3 closest_point; float closest_point_d=1e20; NavMesh *closest_navmesh=NULL; @@ -592,7 +633,7 @@ void Navigation::_bind_methods() { ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove); ObjectTypeDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation::get_simple_path,DEFVAL(true)); - ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end"),&Navigation::get_closest_point_to_segment); + ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end","use_collision"),&Navigation::get_closest_point_to_segment,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation::get_closest_point); ObjectTypeDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal); diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index 9b6cf5fbc4..19977c3110 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -118,6 +118,7 @@ class Navigation : public Spatial { int last_id; Vector3 up; + void _clip_path(Vector<Vector3>& path,Polygon *from_poly, const Vector3& p_to_point, Polygon* p_to_poly); protected: @@ -134,7 +135,7 @@ public: void navmesh_remove(int p_id); Vector<Vector3> get_simple_path(const Vector3& p_start, const Vector3& p_end,bool p_optimize=true); - Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to); + Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to,const bool& p_use_collision=false); Vector3 get_closest_point(const Vector3& p_point); Vector3 get_closest_point_normal(const Vector3& p_point); diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index db416f24dd..8c52d4c35c 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -114,7 +114,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) { return; enabled=p_enabled; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (!enabled) { @@ -152,7 +152,7 @@ void NavigationMeshInstance::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { Spatial *c=this; while(c) { @@ -178,7 +178,7 @@ void NavigationMeshInstance::_notification(int p_what) { } } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (navigation) { diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index bc5cb1c4a2..8be918fc22 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -26,363 +26,363 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "path.h"
-#include "scene/scene_string_names.h"
-
-void Path::_notification(int p_what) {
-#if 0
- if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_scene() && get_scene()->is_editor_hint()) {
- //draw the curve!!
-
- for(int i=0;i<curve->get_point_count();i++) {
-
- Vector2 prev_p=curve->get_point_pos(i);
-
- for(int j=1;j<=8;j++) {
-
- real_t frac = j/8.0;
- Vector2 p = curve->interpolate(i,frac);
- draw_line(prev_p,p,Color(0.5,0.6,1.0,0.7),2);
- prev_p=p;
- }
- }
- }
-#endif
-}
-
-void Path::_curve_changed() {
-
-
- if (is_inside_scene() && get_scene()->is_editor_hint())
- update_gizmo();
-}
-
-
-void Path::set_curve(const Ref<Curve3D>& p_curve) {
-
- if (curve.is_valid()) {
- curve->disconnect("changed",this,"_curve_changed");
- }
-
- curve=p_curve;
-
- if (curve.is_valid()) {
- curve->connect("changed",this,"_curve_changed");
- }
- _curve_changed();
-
-}
-
-Ref<Curve3D> Path::get_curve() const{
-
- return curve;
-}
-
-void Path::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_curve","curve:Curve3D"),&Path::set_curve);
- ObjectTypeDB::bind_method(_MD("get_curve:Curve3D","curve"),&Path::get_curve);
- ObjectTypeDB::bind_method(_MD("_curve_changed"),&Path::_curve_changed);
-
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), _SCS("set_curve"),_SCS("get_curve"));
-}
-
-Path::Path() {
-
- set_curve(Ref<Curve3D>( memnew( Curve3D ))); //create one by default
-}
-
-
-//////////////
-
-
-void PathFollow::_update_transform() {
-
-
- if (!path)
- return;
-
- Ref<Curve3D> c =path->get_curve();
- if (!c.is_valid())
- return;
-
-
- float o = offset;
- if (loop)
- o=Math::fposmod(o,c->get_baked_length());
-
- Vector3 pos = c->interpolate_baked(o,cubic);
- Transform t=get_transform();
-
-
- if (rotation_mode!=ROTATION_NONE) {
-
- Vector3 n = (c->interpolate_baked(o+lookahead,cubic)-pos).normalized();
-
- if (rotation_mode==ROTATION_Y) {
-
- n.y=0;
- n.normalize();
- }
-
- if (n.length()<CMP_EPSILON) {//nothing, use previous
- n=-t.get_basis().get_axis(2).normalized();
- }
-
-
- Vector3 up = Vector3(0,1,0);
-
- if (rotation_mode==ROTATION_XYZ) {
-
- float tilt = c->interpolate_baked_tilt(o);
- if (tilt!=0) {
-
- Matrix3 rot(-n,tilt); //remember.. lookat will be znegative.. znegative!! we abide by opengl clan.
- up=rot.xform(up);
- }
- }
-
- t.set_look_at(pos,pos+n,up);
-
- } else {
-
- t.origin=pos;
- }
-
- t.origin+=t.basis.get_axis(0)*h_offset + t.basis.get_axis(1)*v_offset;
- set_transform(t);
-
-}
-
-void PathFollow::_notification(int p_what) {
-
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_SCENE: {
-
- Node *parent=get_parent();
- if (parent) {
-
- path=parent->cast_to<Path>();
- if (path) {
- _update_transform();
- }
- }
-
- } break;
- case NOTIFICATION_EXIT_SCENE: {
-
-
- path=NULL;
- } break;
- }
-
-}
-
-void PathFollow::set_cubic_interpolation(bool p_enable) {
-
- cubic=p_enable;
-}
-
-bool PathFollow::get_cubic_interpolation() const {
-
- return cubic;
-}
-
-
-bool PathFollow::_set(const StringName& p_name, const Variant& p_value) {
-
- if (p_name==SceneStringNames::get_singleton()->offset) {
- set_offset(p_value);
- } else if (p_name==SceneStringNames::get_singleton()->unit_offset) {
- set_unit_offset(p_value);
- } else if (p_name==SceneStringNames::get_singleton()->rotation_mode) {
- set_rotation_mode(RotationMode(p_value.operator int()));
- } else if (p_name==SceneStringNames::get_singleton()->v_offset) {
- set_v_offset(p_value);
- } else if (p_name==SceneStringNames::get_singleton()->h_offset) {
- set_h_offset(p_value);
- } else if (String(p_name)=="cubic_interp") {
- set_cubic_interpolation(p_value);
- } else if (String(p_name)=="loop") {
- set_loop(p_value);
- } else if (String(p_name)=="lookahead") {
- set_lookahead(p_value);
- } else
- return false;
-
- return true;
-}
-
-bool PathFollow::_get(const StringName& p_name,Variant &r_ret) const{
-
- if (p_name==SceneStringNames::get_singleton()->offset) {
- r_ret=get_offset();
- } else if (p_name==SceneStringNames::get_singleton()->unit_offset) {
- r_ret=get_unit_offset();
- } else if (p_name==SceneStringNames::get_singleton()->rotation_mode) {
- r_ret=get_rotation_mode();
- } else if (p_name==SceneStringNames::get_singleton()->v_offset) {
- r_ret=get_v_offset();
- } else if (p_name==SceneStringNames::get_singleton()->h_offset) {
- r_ret=get_h_offset();
- } else if (String(p_name)=="cubic_interp") {
- r_ret=cubic;
- } else if (String(p_name)=="loop") {
- r_ret=loop;
- } else if (String(p_name)=="lookahead") {
- r_ret=lookahead;
- } else
- return false;
-
- return true;
-
-}
-void PathFollow::_get_property_list( List<PropertyInfo> *p_list) const{
-
- float max=10000;
- if (path && path->get_curve().is_valid())
- max=path->get_curve()->get_baked_length();
- p_list->push_back( PropertyInfo( Variant::REAL, "offset", PROPERTY_HINT_RANGE,"0,"+rtos(max)+",0.01"));
- p_list->push_back( PropertyInfo( Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE,"0,1,0.0001",PROPERTY_USAGE_EDITOR));
- p_list->push_back( PropertyInfo( Variant::REAL, "h_offset") );
- p_list->push_back( PropertyInfo( Variant::REAL, "v_offset") );
- p_list->push_back( PropertyInfo( Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM,"None,Y,XY,XYZ"));
- p_list->push_back( PropertyInfo( Variant::BOOL, "cubic_interp"));
- p_list->push_back( PropertyInfo( Variant::BOOL, "loop"));
- p_list->push_back( PropertyInfo( Variant::REAL, "lookahead",PROPERTY_HINT_RANGE,"0.001,1024.0,0.001"));
-}
-
-
-void PathFollow::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("set_offset","offset"),&PathFollow::set_offset);
- ObjectTypeDB::bind_method(_MD("get_offset"),&PathFollow::get_offset);
-
- ObjectTypeDB::bind_method(_MD("set_h_offset","h_offset"),&PathFollow::set_h_offset);
- ObjectTypeDB::bind_method(_MD("get_h_offset"),&PathFollow::get_h_offset);
-
- ObjectTypeDB::bind_method(_MD("set_v_offset","v_offset"),&PathFollow::set_v_offset);
- ObjectTypeDB::bind_method(_MD("get_v_offset"),&PathFollow::get_v_offset);
-
- ObjectTypeDB::bind_method(_MD("set_unit_offset","unit_offset"),&PathFollow::set_unit_offset);
- ObjectTypeDB::bind_method(_MD("get_unit_offset"),&PathFollow::get_unit_offset);
-
- ObjectTypeDB::bind_method(_MD("set_rotation_mode","rotation_mode"),&PathFollow::set_rotation_mode);
- ObjectTypeDB::bind_method(_MD("get_rotation_mode"),&PathFollow::get_rotation_mode);
-
- ObjectTypeDB::bind_method(_MD("set_cubic_interpolation","enable"),&PathFollow::set_cubic_interpolation);
- ObjectTypeDB::bind_method(_MD("get_cubic_interpolation"),&PathFollow::get_cubic_interpolation);
-
- ObjectTypeDB::bind_method(_MD("set_loop","loop"),&PathFollow::set_loop);
- ObjectTypeDB::bind_method(_MD("has_loop"),&PathFollow::has_loop);
-
- BIND_CONSTANT( ROTATION_NONE );
- BIND_CONSTANT( ROTATION_Y );
- BIND_CONSTANT( ROTATION_XY );
- BIND_CONSTANT( ROTATION_XYZ );
-
-}
-
-void PathFollow::set_offset(float p_offset) {
-
- offset=p_offset;
- if (path)
- _update_transform();
- _change_notify("offset");
- _change_notify("unit_offset");
-
-}
-
-void PathFollow::set_h_offset(float p_h_offset) {
-
- h_offset=p_h_offset;
- if (path)
- _update_transform();
-
-}
-
-float PathFollow::get_h_offset() const {
-
- return h_offset;
-}
-
-void PathFollow::set_v_offset(float p_v_offset) {
-
- v_offset=p_v_offset;
- if (path)
- _update_transform();
-
-}
-
-float PathFollow::get_v_offset() const {
-
- return v_offset;
-}
-
-
-float PathFollow::get_offset() const{
-
- return offset;
-}
-
-void PathFollow::set_unit_offset(float p_unit_offset) {
-
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
- set_offset(p_unit_offset*path->get_curve()->get_baked_length());
-
-}
-
-float PathFollow::get_unit_offset() const{
-
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
- return get_offset()/path->get_curve()->get_baked_length();
- else
- return 0;
-}
-
-void PathFollow::set_lookahead(float p_lookahead) {
-
- lookahead=p_lookahead;
-
-}
-
-float PathFollow::get_lookahead() const{
-
- return lookahead;
-}
-
-void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) {
-
- rotation_mode=p_rotation_mode;
- _update_transform();
-}
-
-PathFollow::RotationMode PathFollow::get_rotation_mode() const {
-
- return rotation_mode;
-}
-
-void PathFollow::set_loop(bool p_loop) {
-
- loop=p_loop;
-}
-
-bool PathFollow::has_loop() const{
-
- return loop;
-}
-
-
-PathFollow::PathFollow() {
-
- offset=0;
- h_offset=0;
- v_offset=0;
- path=NULL;
- rotation_mode=ROTATION_XYZ;
- cubic=true;
- loop=true;
- lookahead=0.1;
-}
+#include "path.h" +#include "scene/scene_string_names.h" + +void Path::_notification(int p_what) { +#if 0 + if (p_what==NOTIFICATION_DRAW && curve.is_valid() && is_inside_scene() && get_scene()->is_editor_hint()) { + //draw the curve!! + + for(int i=0;i<curve->get_point_count();i++) { + + Vector2 prev_p=curve->get_point_pos(i); + + for(int j=1;j<=8;j++) { + + real_t frac = j/8.0; + Vector2 p = curve->interpolate(i,frac); + draw_line(prev_p,p,Color(0.5,0.6,1.0,0.7),2); + prev_p=p; + } + } + } +#endif +} + +void Path::_curve_changed() { + + + if (is_inside_tree() && get_tree()->is_editor_hint()) + update_gizmo(); +} + + +void Path::set_curve(const Ref<Curve3D>& p_curve) { + + if (curve.is_valid()) { + curve->disconnect("changed",this,"_curve_changed"); + } + + curve=p_curve; + + if (curve.is_valid()) { + curve->connect("changed",this,"_curve_changed"); + } + _curve_changed(); + +} + +Ref<Curve3D> Path::get_curve() const{ + + return curve; +} + +void Path::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_curve","curve:Curve3D"),&Path::set_curve); + ObjectTypeDB::bind_method(_MD("get_curve:Curve3D","curve"),&Path::get_curve); + ObjectTypeDB::bind_method(_MD("_curve_changed"),&Path::_curve_changed); + + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), _SCS("set_curve"),_SCS("get_curve")); +} + +Path::Path() { + + set_curve(Ref<Curve3D>( memnew( Curve3D ))); //create one by default +} + + +////////////// + + +void PathFollow::_update_transform() { + + + if (!path) + return; + + Ref<Curve3D> c =path->get_curve(); + if (!c.is_valid()) + return; + + + float o = offset; + if (loop) + o=Math::fposmod(o,c->get_baked_length()); + + Vector3 pos = c->interpolate_baked(o,cubic); + Transform t=get_transform(); + + + if (rotation_mode!=ROTATION_NONE) { + + Vector3 n = (c->interpolate_baked(o+lookahead,cubic)-pos).normalized(); + + if (rotation_mode==ROTATION_Y) { + + n.y=0; + n.normalize(); + } + + if (n.length()<CMP_EPSILON) {//nothing, use previous + n=-t.get_basis().get_axis(2).normalized(); + } + + + Vector3 up = Vector3(0,1,0); + + if (rotation_mode==ROTATION_XYZ) { + + float tilt = c->interpolate_baked_tilt(o); + if (tilt!=0) { + + Matrix3 rot(-n,tilt); //remember.. lookat will be znegative.. znegative!! we abide by opengl clan. + up=rot.xform(up); + } + } + + t.set_look_at(pos,pos+n,up); + + } else { + + t.origin=pos; + } + + t.origin+=t.basis.get_axis(0)*h_offset + t.basis.get_axis(1)*v_offset; + set_transform(t); + +} + +void PathFollow::_notification(int p_what) { + + + switch(p_what) { + + case NOTIFICATION_ENTER_TREE: { + + Node *parent=get_parent(); + if (parent) { + + path=parent->cast_to<Path>(); + if (path) { + _update_transform(); + } + } + + } break; + case NOTIFICATION_EXIT_TREE: { + + + path=NULL; + } break; + } + +} + +void PathFollow::set_cubic_interpolation(bool p_enable) { + + cubic=p_enable; +} + +bool PathFollow::get_cubic_interpolation() const { + + return cubic; +} + + +bool PathFollow::_set(const StringName& p_name, const Variant& p_value) { + + if (p_name==SceneStringNames::get_singleton()->offset) { + set_offset(p_value); + } else if (p_name==SceneStringNames::get_singleton()->unit_offset) { + set_unit_offset(p_value); + } else if (p_name==SceneStringNames::get_singleton()->rotation_mode) { + set_rotation_mode(RotationMode(p_value.operator int())); + } else if (p_name==SceneStringNames::get_singleton()->v_offset) { + set_v_offset(p_value); + } else if (p_name==SceneStringNames::get_singleton()->h_offset) { + set_h_offset(p_value); + } else if (String(p_name)=="cubic_interp") { + set_cubic_interpolation(p_value); + } else if (String(p_name)=="loop") { + set_loop(p_value); + } else if (String(p_name)=="lookahead") { + set_lookahead(p_value); + } else + return false; + + return true; +} + +bool PathFollow::_get(const StringName& p_name,Variant &r_ret) const{ + + if (p_name==SceneStringNames::get_singleton()->offset) { + r_ret=get_offset(); + } else if (p_name==SceneStringNames::get_singleton()->unit_offset) { + r_ret=get_unit_offset(); + } else if (p_name==SceneStringNames::get_singleton()->rotation_mode) { + r_ret=get_rotation_mode(); + } else if (p_name==SceneStringNames::get_singleton()->v_offset) { + r_ret=get_v_offset(); + } else if (p_name==SceneStringNames::get_singleton()->h_offset) { + r_ret=get_h_offset(); + } else if (String(p_name)=="cubic_interp") { + r_ret=cubic; + } else if (String(p_name)=="loop") { + r_ret=loop; + } else if (String(p_name)=="lookahead") { + r_ret=lookahead; + } else + return false; + + return true; + +} +void PathFollow::_get_property_list( List<PropertyInfo> *p_list) const{ + + float max=10000; + if (path && path->get_curve().is_valid()) + max=path->get_curve()->get_baked_length(); + p_list->push_back( PropertyInfo( Variant::REAL, "offset", PROPERTY_HINT_RANGE,"0,"+rtos(max)+",0.01")); + p_list->push_back( PropertyInfo( Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE,"0,1,0.0001",PROPERTY_USAGE_EDITOR)); + p_list->push_back( PropertyInfo( Variant::REAL, "h_offset") ); + p_list->push_back( PropertyInfo( Variant::REAL, "v_offset") ); + p_list->push_back( PropertyInfo( Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM,"None,Y,XY,XYZ")); + p_list->push_back( PropertyInfo( Variant::BOOL, "cubic_interp")); + p_list->push_back( PropertyInfo( Variant::BOOL, "loop")); + p_list->push_back( PropertyInfo( Variant::REAL, "lookahead",PROPERTY_HINT_RANGE,"0.001,1024.0,0.001")); +} + + +void PathFollow::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_offset","offset"),&PathFollow::set_offset); + ObjectTypeDB::bind_method(_MD("get_offset"),&PathFollow::get_offset); + + ObjectTypeDB::bind_method(_MD("set_h_offset","h_offset"),&PathFollow::set_h_offset); + ObjectTypeDB::bind_method(_MD("get_h_offset"),&PathFollow::get_h_offset); + + ObjectTypeDB::bind_method(_MD("set_v_offset","v_offset"),&PathFollow::set_v_offset); + ObjectTypeDB::bind_method(_MD("get_v_offset"),&PathFollow::get_v_offset); + + ObjectTypeDB::bind_method(_MD("set_unit_offset","unit_offset"),&PathFollow::set_unit_offset); + ObjectTypeDB::bind_method(_MD("get_unit_offset"),&PathFollow::get_unit_offset); + + ObjectTypeDB::bind_method(_MD("set_rotation_mode","rotation_mode"),&PathFollow::set_rotation_mode); + ObjectTypeDB::bind_method(_MD("get_rotation_mode"),&PathFollow::get_rotation_mode); + + ObjectTypeDB::bind_method(_MD("set_cubic_interpolation","enable"),&PathFollow::set_cubic_interpolation); + ObjectTypeDB::bind_method(_MD("get_cubic_interpolation"),&PathFollow::get_cubic_interpolation); + + ObjectTypeDB::bind_method(_MD("set_loop","loop"),&PathFollow::set_loop); + ObjectTypeDB::bind_method(_MD("has_loop"),&PathFollow::has_loop); + + BIND_CONSTANT( ROTATION_NONE ); + BIND_CONSTANT( ROTATION_Y ); + BIND_CONSTANT( ROTATION_XY ); + BIND_CONSTANT( ROTATION_XYZ ); + +} + +void PathFollow::set_offset(float p_offset) { + + offset=p_offset; + if (path) + _update_transform(); + _change_notify("offset"); + _change_notify("unit_offset"); + +} + +void PathFollow::set_h_offset(float p_h_offset) { + + h_offset=p_h_offset; + if (path) + _update_transform(); + +} + +float PathFollow::get_h_offset() const { + + return h_offset; +} + +void PathFollow::set_v_offset(float p_v_offset) { + + v_offset=p_v_offset; + if (path) + _update_transform(); + +} + +float PathFollow::get_v_offset() const { + + return v_offset; +} + + +float PathFollow::get_offset() const{ + + return offset; +} + +void PathFollow::set_unit_offset(float p_unit_offset) { + + if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) + set_offset(p_unit_offset*path->get_curve()->get_baked_length()); + +} + +float PathFollow::get_unit_offset() const{ + + if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) + return get_offset()/path->get_curve()->get_baked_length(); + else + return 0; +} + +void PathFollow::set_lookahead(float p_lookahead) { + + lookahead=p_lookahead; + +} + +float PathFollow::get_lookahead() const{ + + return lookahead; +} + +void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) { + + rotation_mode=p_rotation_mode; + _update_transform(); +} + +PathFollow::RotationMode PathFollow::get_rotation_mode() const { + + return rotation_mode; +} + +void PathFollow::set_loop(bool p_loop) { + + loop=p_loop; +} + +bool PathFollow::has_loop() const{ + + return loop; +} + + +PathFollow::PathFollow() { + + offset=0; + h_offset=0; + v_offset=0; + path=NULL; + rotation_mode=ROTATION_XYZ; + cubic=true; + loop=true; + lookahead=0.1; +} diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 15ec60514a..940a29b5d8 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -92,6 +92,7 @@ void PhysicsBody::remove_collision_exception_with(Node* p_node) { PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(),physics_body->get_rid()); } + void PhysicsBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody::set_layer_mask); ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody::get_layer_mask); @@ -193,7 +194,7 @@ StaticBody::~StaticBody() { -void RigidBody::_body_enter_scene(ObjectID p_id) { +void RigidBody::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; @@ -201,9 +202,9 @@ void RigidBody::_body_enter_scene(ObjectID p_id) { Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(E->get().in_scene); + ERR_FAIL_COND(E->get().in_tree); - E->get().in_scene=true; + E->get().in_tree=true; emit_signal(SceneStringNames::get_singleton()->body_enter,node); for(int i=0;i<E->get().shapes.size();i++) { @@ -213,15 +214,15 @@ void RigidBody::_body_enter_scene(ObjectID p_id) { } -void RigidBody::_body_exit_scene(ObjectID p_id) { +void RigidBody::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = obj ? obj->cast_to<Node>() : NULL; ERR_FAIL_COND(!node); Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(p_id); ERR_FAIL_COND(!E); - ERR_FAIL_COND(!E->get().in_scene); - E->get().in_scene=false; + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree=false; emit_signal(SceneStringNames::get_singleton()->body_exit,node); for(int i=0;i<E->get().shapes.size();i++) { @@ -246,11 +247,11 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, E = contact_monitor->body_map.insert(objid,BodyState()); //E->get().rc=0; - E->get().in_scene=node && node->is_inside_scene(); + E->get().in_tree=node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene,make_binds(objid)); - node->connect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene,make_binds(objid)); - if (E->get().in_scene) { + node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree,make_binds(objid)); + if (E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_enter,node); } } @@ -261,7 +262,7 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, E->get().shapes.insert(ShapePair(p_body_shape,p_local_shape)); - if (E->get().in_scene) { + if (E->get().in_tree) { emit_signal(SceneStringNames::get_singleton()->body_enter_shape,objid,node,p_body_shape,p_local_shape); } @@ -272,21 +273,21 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape, if (node) E->get().shapes.erase(ShapePair(p_body_shape,p_local_shape)); - bool in_scene = E->get().in_scene; + bool in_tree = E->get().in_tree; if (E->get().shapes.empty()) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->enter_scene,this,SceneStringNames::get_singleton()->_body_enter_scene); - node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,SceneStringNames::get_singleton()->_body_exit_scene); - if (in_scene) + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); + if (in_tree) emit_signal(SceneStringNames::get_singleton()->body_exit,obj); } contact_monitor->body_map.erase(E); } - if (node && in_scene) { + if (node && in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exit_shape,objid,obj,p_body_shape,p_local_shape); } @@ -637,6 +638,27 @@ RigidBody::AxisLock RigidBody::get_axis_lock() const { } +Array RigidBody::get_colliding_bodies() const { + + ERR_FAIL_COND_V(!contact_monitor,Array()); + + Array ret; + ret.resize(contact_monitor->body_map.size()); + int idx=0; + for (const Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize( ret.size() -1 ); //ops + } else { + ret[idx++]=obj; + } + + } + + return ret; +} + + void RigidBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_mode","mode"),&RigidBody::set_mode); @@ -682,12 +704,14 @@ void RigidBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_able_to_sleep"),&RigidBody::is_able_to_sleep); ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&RigidBody::_direct_state_changed); - ObjectTypeDB::bind_method(_MD("_body_enter_scene"),&RigidBody::_body_enter_scene); - ObjectTypeDB::bind_method(_MD("_body_exit_scene"),&RigidBody::_body_exit_scene); + ObjectTypeDB::bind_method(_MD("_body_enter_tree"),&RigidBody::_body_enter_tree); + ObjectTypeDB::bind_method(_MD("_body_exit_tree"),&RigidBody::_body_exit_tree); ObjectTypeDB::bind_method(_MD("set_axis_lock","axis_lock"),&RigidBody::set_axis_lock); ObjectTypeDB::bind_method(_MD("get_axis_lock"),&RigidBody::get_axis_lock); + ObjectTypeDB::bind_method(_MD("get_colliding_bodies"),&RigidBody::get_colliding_bodies); + BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState"))); ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode")); @@ -792,7 +816,7 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { colliding=false; - ERR_FAIL_COND_V(!is_inside_scene(),Vector3()); + ERR_FAIL_COND_V(!is_inside_tree(),Vector3()); PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space()); ERR_FAIL_COND_V(!dss,Vector3()); const int max_shapes=32; @@ -829,6 +853,8 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { //motion recover for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),m,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) { collided=true; @@ -907,6 +933,8 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; float lsafe,lunsafe; PhysicsDirectSpaceState::ShapeRestInfo lrest; @@ -989,7 +1017,7 @@ Vector3 KinematicBody::move_to(const Vector3& p_position) { bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) { - ERR_FAIL_COND_V(!is_inside_scene(),false); + ERR_FAIL_COND_V(!is_inside_tree(),false); PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(get_world()->get_space()); ERR_FAIL_COND_V(!dss,false); @@ -1018,6 +1046,8 @@ bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) { //fill exclude list.. for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),0,NULL,0,exclude,get_layer_mask(),mask); if (col) @@ -1029,7 +1059,7 @@ bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) { bool KinematicBody::is_colliding() const { - ERR_FAIL_COND_V(!is_inside_scene(),false); + ERR_FAIL_COND_V(!is_inside_tree(),false); return colliding; } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index a19ad48c87..beec01ff3a 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -56,6 +56,8 @@ public: void add_collision_exception_with(Node* p_node); //must be physicsbody void remove_collision_exception_with(Node* p_node); + + PhysicsBody(); }; @@ -163,7 +165,7 @@ private: struct BodyState { //int rc; - bool in_scene; + bool in_tree; VSet<ShapePair> shapes; }; @@ -176,8 +178,8 @@ private: ContactMonitor *contact_monitor; - void _body_enter_scene(ObjectID p_id); - void _body_exit_scene(ObjectID p_id); + void _body_enter_tree(ObjectID p_id); + void _body_exit_tree(ObjectID p_id); void _body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape); @@ -236,6 +238,7 @@ public: void set_axis_lock(AxisLock p_lock); AxisLock get_axis_lock() const; + Array get_colliding_bodies() const; void apply_impulse(const Vector3& p_pos, const Vector3& p_impulse); diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 8a79e17d87..8d9257a273 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -42,7 +42,7 @@ void Joint::_update_joint(bool p_only_free) { bb=RID(); } - if (p_only_free || !is_inside_scene()) + if (p_only_free || !is_inside_tree()) return; Node *node_a = has_node( get_node_a() ) ? get_node( get_node_a() ) : (Node*)NULL; @@ -131,7 +131,7 @@ void Joint::_notification(int p_what) { case NOTIFICATION_READY: { _update_joint(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (joint.is_valid()) { _update_joint(true); PhysicsServer::get_singleton()->free(joint); diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp index b3378c7698..a30a23aa53 100644 --- a/scene/3d/proximity_group.cpp +++ b/scene/3d/proximity_group.cpp @@ -119,7 +119,7 @@ void ProximityGroup::_notification(int what) { switch (what) { - case NOTIFICATION_EXIT_SCENE: + case NOTIFICATION_EXIT_TREE: ++group_version; clear_groups(); break; @@ -135,7 +135,7 @@ void ProximityGroup::broadcast(String p_name, Variant p_params) { E = groups.front(); while (E) { - get_scene()->call_group(SceneMainLoop::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_name, p_params); + get_tree()->call_group(SceneTree::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_name, p_params); E = E->next(); }; diff --git a/scene/3d/quad.cpp b/scene/3d/quad.cpp index 78dd56141c..8ee232fef4 100644 --- a/scene/3d/quad.cpp +++ b/scene/3d/quad.cpp @@ -31,7 +31,7 @@ void Quad::_update() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; Vector3 normal; @@ -171,14 +171,14 @@ void Quad::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (pending_update) _update(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { pending_update=true; diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index e36e2da14f..639a86e759 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -33,7 +33,7 @@ void RayCast::set_cast_to(const Vector3& p_point) { cast_to=p_point; - if (is_inside_scene() && get_scene()->is_editor_hint()) + if (is_inside_tree() && get_tree()->is_editor_hint()) update_gizmo(); } @@ -72,7 +72,7 @@ Vector3 RayCast::get_collision_normal() const{ void RayCast::set_enabled(bool p_enabled) { enabled=p_enabled; - if (is_inside_scene() && !get_scene()->is_editor_hint()) + if (is_inside_tree() && !get_tree()->is_editor_hint()) set_fixed_process(p_enabled); if (!p_enabled) collided=false; @@ -91,35 +91,22 @@ void RayCast::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { - if (enabled && !get_scene()->is_editor_hint()) { + if (enabled && !get_tree()->is_editor_hint()) { set_fixed_process(true); - Node *p = get_parent(); - while( p && p->cast_to<Spatial>() ) { - - CollisionObject *co = p->cast_to<CollisionObject>(); - if (co) { - - exception=co->get_rid(); - exceptions.insert(exception); - } - - p=p->get_parent(); - } } else set_fixed_process(false); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (enabled) { set_fixed_process(false); } - exceptions.erase(exception); } break; case NOTIFICATION_FIXED_PROCESS: { @@ -143,7 +130,7 @@ void RayCast::_notification(int p_what) { PhysicsDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exceptions)) { + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude)) { collided=true; against=rr.collider_id; @@ -160,6 +147,41 @@ void RayCast::_notification(int p_what) { } } +void RayCast::add_exception_rid(const RID& p_rid) { + + exclude.insert(p_rid); +} + +void RayCast::add_exception(const Object* p_object){ + + ERR_FAIL_NULL(p_object); + CollisionObject *co=((Object*)p_object)->cast_to<CollisionObject>(); + if (!co) + return; + add_exception_rid(co->get_rid()); +} + +void RayCast::remove_exception_rid(const RID& p_rid) { + + exclude.erase(p_rid); +} + +void RayCast::remove_exception(const Object* p_object){ + + ERR_FAIL_NULL(p_object); + CollisionObject *co=((Object*)p_object)->cast_to<CollisionObject>(); + if (!co) + return; + remove_exception_rid(co->get_rid()); +} + + +void RayCast::clear_exceptions(){ + + exclude.clear(); +} + + void RayCast::_bind_methods() { @@ -176,6 +198,14 @@ void RayCast::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_point"),&RayCast::get_collision_point); ObjectTypeDB::bind_method(_MD("get_collision_normal"),&RayCast::get_collision_normal); + ObjectTypeDB::bind_method(_MD("add_exception_rid","rid"),&RayCast::add_exception_rid); + ObjectTypeDB::bind_method(_MD("add_exception","node"),&RayCast::add_exception); + + ObjectTypeDB::bind_method(_MD("remove_exception_rid","rid"),&RayCast::remove_exception_rid); + ObjectTypeDB::bind_method(_MD("remove_exception","node"),&RayCast::remove_exception); + + ObjectTypeDB::bind_method(_MD("clear_exceptions"),&RayCast::clear_exceptions); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to")); } diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h index 96606b1628..0239c61b67 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -45,8 +45,7 @@ class RayCast : public Spatial { Vector3 cast_to; - RID exception; - Set<RID> exceptions; + Set<RID> exclude; protected: @@ -66,6 +65,12 @@ public: Vector3 get_collision_point() const; Vector3 get_collision_normal() const; + void add_exception_rid(const RID& p_rid); + void add_exception(const Object* p_object); + void remove_exception_rid(const RID& p_rid); + void remove_exception(const Object* p_object); + void clear_exceptions(); + RayCast(); }; diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp index fa1d3ecf6b..3f9e6c7f13 100644 --- a/scene/3d/room_instance.cpp +++ b/scene/3d/room_instance.cpp @@ -147,7 +147,7 @@ void Room::set_room( const Ref<RoomBounds>& p_room ) { set_base(RID()); } - if (!is_inside_scene()) + if (!is_inside_tree()) return; diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 858ee4e4ad..f53ee7d6bf 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -237,6 +237,21 @@ Transform Skeleton::get_bone_transform(int p_bone) const { return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse; } + +void Skeleton::set_bone_global_pose(int p_bone,const Transform& p_pose) { + + ERR_FAIL_INDEX(p_bone,bones.size()); + if (bones[p_bone].parent==-1) { + + set_bone_pose(p_bone,bones[p_bone].rest_global_inverse * p_pose); //fast + } else { + + set_bone_pose(p_bone, bones[p_bone].rest.affine_inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); //slow + + } + +} + Transform Skeleton::get_bone_global_pose(int p_bone) const { ERR_FAIL_INDEX_V(p_bone,bones.size(),Transform()); @@ -389,7 +404,7 @@ void Skeleton::clear_bones() { void Skeleton::set_bone_pose(int p_bone, const Transform& p_pose) { ERR_FAIL_INDEX( p_bone, bones.size() ); - ERR_FAIL_COND( !is_inside_scene() ); + ERR_FAIL_COND( !is_inside_tree() ); bones[p_bone].pose=p_pose; @@ -427,7 +442,7 @@ void Skeleton::_make_dirty() { if (dirty) return; - if (!is_inside_scene()) { + if (!is_inside_tree()) { dirty=true; return; } @@ -519,6 +534,7 @@ void Skeleton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose); ObjectTypeDB::bind_method(_MD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose); + ObjectTypeDB::bind_method(_MD("set_bone_global_pose","bone_idx","pose"),&Skeleton::set_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose); ObjectTypeDB::bind_method(_MD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose); diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 3e0ab0afd7..c61946a4c7 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -118,6 +118,8 @@ public: Transform get_bone_transform(int p_bone) const; Transform get_bone_global_pose(int p_bone) const; + void set_bone_global_pose(int p_bone,const Transform& p_pose); + void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index d304095d33..6e11855543 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -76,7 +76,7 @@ void Spatial::_notify_dirty() { if (!data.ignore_notification && !xform_change.in_list()) { - get_scene()->xform_change_list.add(&xform_change); + get_tree()->xform_change_list.add(&xform_change); } } @@ -91,7 +91,7 @@ void Spatial::_update_local_transform() const { } void Spatial::_propagate_transform_changed(Spatial *p_origin) { - if (!is_inside_scene()) { + if (!is_inside_tree()) { return; } @@ -110,7 +110,7 @@ void Spatial::_propagate_transform_changed(Spatial *p_origin) { if (!data.ignore_notification && !xform_change.in_list()) { - get_scene()->xform_change_list.add(&xform_change); + get_tree()->xform_change_list.add(&xform_change); } data.dirty|=DIRTY_GLOBAL; @@ -121,7 +121,7 @@ void Spatial::_propagate_transform_changed(Spatial *p_origin) { void Spatial::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { Node *p = get_parent(); if (p) @@ -132,7 +132,7 @@ void Spatial::_notification(int p_what) { else data.C=NULL; - if (data.toplevel && !get_scene()->is_editor_hint()) { + if (data.toplevel && !get_tree()->is_editor_hint()) { if (data.parent) { data.local_transform = data.parent->get_global_transform() * get_transform(); @@ -147,11 +147,11 @@ void Spatial::_notification(int p_what) { notification(NOTIFICATION_ENTER_WORLD); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { notification(NOTIFICATION_EXIT_WORLD,true); if (xform_change.in_list()) - get_scene()->xform_change_list.remove(&xform_change); + get_tree()->xform_change_list.remove(&xform_change); if (data.C) data.parent->data.children.erase(data.C); data.parent=NULL; @@ -177,10 +177,10 @@ void Spatial::_notification(int p_what) { get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_enter_world,NULL,0); } #ifdef TOOLS_ENABLED - if (get_scene()->is_editor_hint()) { + if (get_tree()->is_editor_hint()) { // get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this); - get_scene()->call_group(0,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this); + get_tree()->call_group(0,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this); if (!data.gizmo_disabled) { if (data.gizmo.is_valid()) @@ -257,7 +257,7 @@ Transform Spatial::get_transform() const { } Transform Spatial::get_global_transform() const { - ERR_FAIL_COND_V(!is_inside_scene(), Transform()); + ERR_FAIL_COND_V(!is_inside_tree(), Transform()); if (data.dirty & DIRTY_GLOBAL) { @@ -460,7 +460,7 @@ void Spatial::set_as_toplevel(bool p_enabled) { if (data.toplevel==p_enabled) return; - if (is_inside_scene() && !get_scene()->is_editor_hint()) { + if (is_inside_tree() && !get_tree()->is_editor_hint()) { if (p_enabled) set_transform(get_global_transform()); @@ -537,7 +537,7 @@ void Spatial::show() { data.visible=true; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (!data.parent || is_visible()) { @@ -593,6 +593,97 @@ bool Spatial::_is_visible_() const { return !is_hidden(); } +void Spatial::rotate(const Vector3& p_normal,float p_radians) { + + Transform t =get_transform(); + t.basis.rotate(p_normal,p_radians); + set_transform(t); +} + +void Spatial::rotate_x(float p_radians) { + + Transform t =get_transform(); + t.basis.rotate(Vector3(1,0,0),p_radians); + set_transform(t); + +} + +void Spatial::rotate_y(float p_radians){ + + Transform t =get_transform(); + t.basis.rotate(Vector3(0,1,0),p_radians); + set_transform(t); + +} +void Spatial::rotate_z(float p_radians){ + + Transform t =get_transform(); + t.basis.rotate(Vector3(0,0,1),p_radians); + set_transform(t); + +} + +void Spatial::translate(const Vector3& p_offset){ + + Transform t =get_transform(); + t.origin+=p_offset; + set_transform(t); + +} +void Spatial::scale(const Vector3& p_ratio){ + + Transform t =get_transform(); + t.basis.scale(p_ratio); + set_transform(t); + +} +void Spatial::global_rotate(const Vector3& p_normal,float p_radians){ + + Matrix3 rotation(p_normal,p_radians); + Transform t = get_global_transform(); + t.basis= rotation * t.basis; + set_global_transform(t); + +} +void Spatial::global_translate(const Vector3& p_offset){ + Transform t = get_global_transform(); + t.origin+=p_offset; + set_global_transform(t); + +} + +void Spatial::orthonormalize() { + + Transform t = get_transform(); + t.orthonormalize(); + set_transform(t); + +} + +void Spatial::set_identity() { + + set_transform(Transform()); + +} + + +void Spatial::look_at(const Vector3& p_target, const Vector3& p_up_normal) { + + Transform lookat; + lookat.origin=get_global_transform().origin; + lookat=lookat.looking_at(p_target,p_up_normal); + set_global_transform(lookat); +} + +void Spatial::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal) { + + Transform lookat; + lookat.origin=p_pos; + lookat=lookat.looking_at(p_target,p_up_normal); + set_global_transform(lookat); + +} + void Spatial::_bind_methods() { @@ -633,6 +724,28 @@ void Spatial::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_); ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_); + void rotate(const Vector3& p_normal,float p_radians); + void rotate_x(float p_radians); + void rotate_y(float p_radians); + void rotate_z(float p_radians); + void translate(const Vector3& p_offset); + void scale(const Vector3& p_ratio); + void global_rotate(const Vector3& p_normal,float p_radians); + void global_translate(const Vector3& p_offset); + + ObjectTypeDB::bind_method( _MD("rotate","normal","radians"),&Spatial::rotate ); + ObjectTypeDB::bind_method( _MD("global_rotate","normal","radians"),&Spatial::global_rotate ); + ObjectTypeDB::bind_method( _MD("rotate_x","radians"),&Spatial::rotate_x ); + ObjectTypeDB::bind_method( _MD("rotate_y","radians"),&Spatial::rotate_y ); + ObjectTypeDB::bind_method( _MD("rotate_z","radians"),&Spatial::rotate_z ); + ObjectTypeDB::bind_method( _MD("translate","offset"),&Spatial::translate ); + ObjectTypeDB::bind_method( _MD("global_translate","offset"),&Spatial::global_translate ); + ObjectTypeDB::bind_method( _MD("orthonormalize"),&Spatial::orthonormalize ); + ObjectTypeDB::bind_method( _MD("set_identity"),&Spatial::set_identity ); + + ObjectTypeDB::bind_method( _MD("look_at","target","up"),&Spatial::look_at ); + ObjectTypeDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Spatial::look_at_from_pos ); + BIND_CONSTANT( NOTIFICATION_TRANSFORM_CHANGED ); BIND_CONSTANT( NOTIFICATION_ENTER_WORLD ); BIND_CONSTANT( NOTIFICATION_EXIT_WORLD ); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 7036ef63ca..f2cde8f1e6 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -130,7 +130,7 @@ public: enum { - NOTIFICATION_TRANSFORM_CHANGED=SceneMainLoop::NOTIFICATION_TRANSFORM_CHANGED, + NOTIFICATION_TRANSFORM_CHANGED=SceneTree::NOTIFICATION_TRANSFORM_CHANGED, NOTIFICATION_ENTER_WORLD=41, NOTIFICATION_EXIT_WORLD=42, NOTIFICATION_VISIBILITY_CHANGED=43, @@ -167,6 +167,21 @@ public: Transform get_relative_transform(const Node *p_parent) const; + void rotate(const Vector3& p_normal,float p_radians); + void rotate_x(float p_radians); + void rotate_y(float p_radians); + void rotate_z(float p_radians); + void translate(const Vector3& p_offset); + void scale(const Vector3& p_ratio); + void global_rotate(const Vector3& p_normal,float p_radians); + void global_translate(const Vector3& p_offset); + + void look_at(const Vector3& p_target, const Vector3& p_up_normal); + void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal); + + void orthonormalize(); + void set_identity(); + void show(); void hide(); bool is_visible() const; diff --git a/scene/3d/spatial_sample_player.cpp b/scene/3d/spatial_sample_player.cpp index b4a5d3bc1b..6dc71e06ad 100644 --- a/scene/3d/spatial_sample_player.cpp +++ b/scene/3d/spatial_sample_player.cpp @@ -103,6 +103,7 @@ void SpatialSamplePlayer::_notification(int p_what) { void SpatialSamplePlayer::set_sample_library(const Ref<SampleLibrary>& p_library) { library=p_library; + _change_notify(); } Ref<SampleLibrary> SpatialSamplePlayer::get_sample_library() const { diff --git a/scene/3d/spatial_stream_player.cpp b/scene/3d/spatial_stream_player.cpp index 25448498cb..51009662d6 100644 --- a/scene/3d/spatial_stream_player.cpp +++ b/scene/3d/spatial_stream_player.cpp @@ -74,7 +74,7 @@ Ref<AudioStream> SpatialStreamPlayer::get_stream() const { void SpatialStreamPlayer::play() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (stream.is_null()) return; @@ -89,7 +89,7 @@ void SpatialStreamPlayer::play() { void SpatialStreamPlayer::stop() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (stream.is_null()) return; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 334a15e724..35f6523c6a 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -37,7 +37,7 @@ void SpriteBase3D::_propagate_color_changed() { void SpriteBase3D::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { if (!pending_update) _im_update(); @@ -52,7 +52,7 @@ void SpriteBase3D::_notification(int p_what) { } } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { if (parent_sprite) { @@ -275,6 +275,9 @@ void SpriteBase3D::_bind_methods() { BIND_CONSTANT( ALPHA_CUT_DISABLED ); BIND_CONSTANT( ALPHA_CUT_DISCARD ); BIND_CONSTANT( ALPHA_CUT_OPAQUE_PREPASS ); + + + } @@ -494,6 +497,8 @@ void Sprite3D::set_frame(int p_frame) { frame=p_frame; _queue_update(); + emit_signal(SceneStringNames::get_singleton()->frame_changed); + } int Sprite3D::get_frame() const { @@ -579,6 +584,8 @@ void Sprite3D::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); + ADD_SIGNAL(MethodInfo("frame_changed")); + } Sprite3D::Sprite3D() { @@ -722,6 +729,8 @@ void AnimatedSprite3D::_bind_methods(){ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_SIGNAL(MethodInfo("frame_changed")); + } @@ -764,6 +773,7 @@ void AnimatedSprite3D::set_frame(int p_frame){ frame=p_frame; _queue_update(); + emit_signal(SceneStringNames::get_singleton()->frame_changed); } int AnimatedSprite3D::get_frame() const{ diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 4cf905e4ee..ba30c118f0 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -57,7 +57,7 @@ public: void VehicleWheel::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { if (!get_parent()) return; @@ -73,7 +73,7 @@ void VehicleWheel::_notification(int p_what) { m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized(); } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { if (!get_parent()) return; diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index 60e311cefe..d4ef2931e9 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -183,7 +183,7 @@ void VisibilityEnabler::_find_nodes(Node* p_node) { if (add) { - p_node->connect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed",varray(p_node),CONNECT_ONESHOT); + p_node->connect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed",varray(p_node),CONNECT_ONESHOT); nodes[p_node]=meta; _change_node_state(p_node,false); } @@ -200,9 +200,9 @@ void VisibilityEnabler::_find_nodes(Node* p_node) { void VisibilityEnabler::_notification(int p_what){ - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) return; @@ -215,9 +215,9 @@ void VisibilityEnabler::_notification(int p_what){ } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) return; @@ -228,7 +228,7 @@ void VisibilityEnabler::_notification(int p_what){ if (!visible) _change_node_state(E->key(),true); - E->key()->disconnect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed"); + E->key()->disconnect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed"); } nodes.clear(); @@ -271,7 +271,7 @@ void VisibilityEnabler::_node_removed(Node* p_node) { if (!visible) _change_node_state(p_node,true); - p_node->disconnect(SceneStringNames::get_singleton()->exit_scene,this,"_node_removed"); + p_node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed"); nodes.erase(p_node); } diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index af535e139f..45c7fa912c 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -50,17 +50,24 @@ void VisualInstance::_notification(int p_what) { // CHECK ROOM Spatial * parent = get_parent_spatial(); Room *room=NULL; + bool is_geom = cast_to<GeometryInstance>(); while(parent) { room = parent->cast_to<Room>(); if (room) break; - else - parent=parent->get_parent_spatial(); + + if (is_geom && parent->cast_to<BakedLightSampler>()) { + VS::get_singleton()->instance_geometry_set_baked_light_sampler(get_instance(),parent->cast_to<BakedLightSampler>()->get_instance()); + break; + } + + parent=parent->get_parent_spatial(); } + if (room) { VisualServer::get_singleton()->instance_set_room(instance,room->get_instance()); @@ -85,6 +92,7 @@ void VisualInstance::_notification(int p_what) { VisualServer::get_singleton()->instance_set_scenario( instance, RID() ); VisualServer::get_singleton()->instance_set_room(instance,RID()); VisualServer::get_singleton()->instance_attach_skeleton( instance, RID() ); + VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); } break; @@ -249,7 +257,7 @@ void GeometryInstance::_find_baked_light() { void GeometryInstance::_update_visibility() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; _change_notify("geometry/visible"); @@ -302,6 +310,17 @@ int GeometryInstance::get_baked_light_texture_id() const{ return baked_light_texture_id; } +void GeometryInstance::set_extra_cull_margin(float p_margin) { + + ERR_FAIL_COND(p_margin<0); + extra_cull_margin=p_margin; + VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(),extra_cull_margin); +} + +float GeometryInstance::get_extra_cull_margin() const{ + + return extra_cull_margin; +} void GeometryInstance::_bind_methods() { @@ -320,6 +339,9 @@ void GeometryInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id); ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id); + ObjectTypeDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin); + ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin); + ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE); @@ -328,6 +350,7 @@ void GeometryInstance::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/receive_shadows"), _SCS("set_flag"), _SCS("get_flag"),FLAG_RECEIVE_SHADOWS); ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_begin",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_begin"), _SCS("get_draw_range_begin")); ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_end",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_end"), _SCS("get_draw_range_end")); + ADD_PROPERTY( PropertyInfo( Variant::REAL, "geometry/extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin")); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE); @@ -351,13 +374,13 @@ void GeometryInstance::_bind_methods() { GeometryInstance::GeometryInstance() { draw_begin=0; draw_end=0; + for(int i=0;i<FLAG_MAX;i++) { + flags[i]=false; + } + flags[FLAG_VISIBLE]=true; flags[FLAG_CAST_SHADOW]=true; flags[FLAG_RECEIVE_SHADOWS]=true; - flags[FLAG_BILLBOARD]=false; - flags[FLAG_BILLBOARD_FIX_Y]=false; - flags[FLAG_DEPH_SCALE]=false; - flags[FLAG_VISIBLE_IN_ALL_ROOMS]=false; baked_light_instance=NULL; baked_light_texture_id=0; VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0); diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index bbb49a2e78..e08acbe9a2 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -47,6 +47,7 @@ class VisualInstance : public Spatial { RID _get_visual_instance_rid() const; + protected: @@ -107,6 +108,7 @@ private: void _find_baked_light(); BakedLightInstance *baked_light_instance; int baked_light_texture_id; + float extra_cull_margin; void _baked_light_changed(); void _update_visibility(); @@ -131,6 +133,9 @@ public: void set_baked_light_texture_id(int p_id); int get_baked_light_texture_id() const; + void set_extra_cull_margin(float p_margin); + float get_extra_cull_margin() const; + GeometryInstance(); }; diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 38cfe0d8a9..46eb8d7e88 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -30,7 +30,7 @@ -void AnimationCache::_node_exit_scene(Node *p_node) { +void AnimationCache::_node_exit_tree(Node *p_node) { //it is one shot, so it disconnects upon arrival @@ -59,7 +59,7 @@ void AnimationCache::_clear_cache() { while(connected_nodes.size()) { - connected_nodes.front()->get()->disconnect("exit_scene",this,"_node_exit_scene"); + connected_nodes.front()->get()->disconnect("exit_tree",this,"_node_exit_tree"); connected_nodes.erase(connected_nodes.front()); } path_cache.clear();; @@ -73,7 +73,7 @@ void AnimationCache::_update_cache() { cache_valid=false; ERR_FAIL_COND(!root); - ERR_FAIL_COND(!root->is_inside_scene()); + ERR_FAIL_COND(!root->is_inside_tree()); ERR_FAIL_COND(animation.is_null()); for(int i=0;i<animation->get_track_count();i++) { @@ -206,7 +206,7 @@ void AnimationCache::_update_cache() { if (!connected_nodes.has(path.node)) { connected_nodes.insert(path.node); - path.node->connect("exit_scene",this,"_node_exit_scene",Node::make_binds(path.node),CONNECT_ONESHOT); + path.node->connect("exit_tree",this,"_node_exit_tree",Node::make_binds(path.node),CONNECT_ONESHOT); } @@ -368,7 +368,7 @@ void AnimationCache::set_animation(const Ref<Animation>& p_animation) { void AnimationCache::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_node_exit_scene"),&AnimationCache::_node_exit_scene); + ObjectTypeDB::bind_method(_MD("_node_exit_tree"),&AnimationCache::_node_exit_tree); ObjectTypeDB::bind_method(_MD("_animation_changed"),&AnimationCache::_animation_changed); } diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h index 72ee8f1860..d00b122faa 100644 --- a/scene/animation/animation_cache.h +++ b/scene/animation/animation_cache.h @@ -58,7 +58,7 @@ class AnimationCache : public Object { bool cache_dirty; bool cache_valid; - void _node_exit_scene(Node *p_node); + void _node_exit_tree(Node *p_node); void _clear_cache(); void _update_cache(); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 88fabb3489..f9d36138a2 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -189,7 +189,7 @@ void AnimationPlayer::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (!processing) { //make sure that a previous process state was not saved @@ -202,7 +202,7 @@ void AnimationPlayer::_notification(int p_what) { } break; case NOTIFICATION_READY: { - if (!get_scene()->is_editor_hint() && animation_set.has(autoplay)) { + if (!get_tree()->is_editor_hint() && animation_set.has(autoplay)) { play(autoplay); } } break; @@ -221,7 +221,7 @@ void AnimationPlayer::_notification(int p_what) { if (processing) _animation_process( get_fixed_process_delta_time() ); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { stop_all(); clear_caches(); @@ -261,8 +261,8 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) { } { - if (!child->is_connected("exit_scene",this,"_node_removed")) - child->connect("exit_scene",this,"_node_removed",make_binds(child),CONNECT_ONESHOT); + if (!child->is_connected("exit_tree",this,"_node_removed")) + child->connect("exit_tree",this,"_node_removed",make_binds(child),CONNECT_ONESHOT); } TrackNodeCacheKey key; @@ -348,7 +348,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p Animation *a=p_anim->animation.operator->(); - bool can_call = is_inside_scene() && !get_scene()->is_editor_hint(); + bool can_call = is_inside_tree() && !get_tree()->is_editor_hint(); for (int i=0;i<a->get_track_count();i++) { @@ -374,7 +374,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p Error err = a->transform_track_interpolate(i,p_time,&loc,&rot,&scale); - ERR_CONTINUE(err!=OK); //used for testing, should be removed + //ERR_CONTINUE(err!=OK); //used for testing, should be removed if (err!=OK) @@ -922,12 +922,12 @@ void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float _set_process(true); // always process when starting an animation playing = true; - if (is_inside_scene() && get_scene()->is_editor_hint()) + if (is_inside_tree() && get_tree()->is_editor_hint()) return; // no next in this case StringName next=animation_get_next(p_name); - if (next!=StringName()) { + if (next!=StringName() && animation_set.has(next)) { queue(next); } } @@ -1178,6 +1178,19 @@ NodePath AnimationPlayer::get_root() const { return root; } +void AnimationPlayer::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String pf = p_function; + if (p_function=="play" || p_function=="remove_animation" || p_function=="has_animation" || p_function=="queue") { + List<StringName> al; + get_animation_list(&al); + for (List<StringName>::Element *E=al.front();E;E=E->next()) { + + r_options->push_back("\""+String(E->get())+"\""); + } + } + Node::get_argument_options(p_function,p_idx,r_options); +} void AnimationPlayer::_bind_methods() { diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 038c43d569..8ac5d96bf3 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -289,6 +289,9 @@ public: NodePath get_root() const; void clear_caches(); ///< must be called by hand if an animation was modified after added + + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; + AnimationPlayer(); ~AnimationPlayer(); diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 2d1821bc5c..5172907d18 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -83,7 +83,8 @@ bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) ERR_FAIL_COND_V(nt==NODE_MAX,false); - add_node(nt,id); + if (nt!=NODE_OUTPUT) + add_node(nt,id); node_set_pos(id,pos); @@ -1586,7 +1587,7 @@ void AnimationTreePlayer::_update_sources() { if (master==NodePath()) return; - if (!is_inside_scene()) + if (!is_inside_tree()) return; Node *m = get_node(master); @@ -1662,7 +1663,7 @@ void AnimationTreePlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("node_get_type","id"),&AnimationTreePlayer::node_get_type); ObjectTypeDB::bind_method(_MD("node_get_input_count","id"),&AnimationTreePlayer::node_get_input_count); - ObjectTypeDB::bind_method(_MD("node_get_input_sourcre","id","idx"),&AnimationTreePlayer::node_get_input_source); + ObjectTypeDB::bind_method(_MD("node_get_input_source","id","idx"),&AnimationTreePlayer::node_get_input_source); ObjectTypeDB::bind_method(_MD("animation_node_set_animation","id","animation:Animation"),&AnimationTreePlayer::animation_node_set_animation); ObjectTypeDB::bind_method(_MD("animation_node_get_animation:Animation","id"),&AnimationTreePlayer::animation_node_get_animation); diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 7e7d57c3c2..8b87ecf711 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -75,7 +75,7 @@ void Tween::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (!processing) { //make sure that a previous process state was not saved @@ -102,7 +102,7 @@ void Tween::_notification(int p_what) { if (processing) _tween_process( get_fixed_process_delta_time() ); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { stop_all(); } break; @@ -124,32 +124,35 @@ void Tween::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tween_process_mode"),&Tween::get_tween_process_mode); ObjectTypeDB::bind_method(_MD("start"),&Tween::start ); - ObjectTypeDB::bind_method(_MD("reset","node","key"),&Tween::reset ); + ObjectTypeDB::bind_method(_MD("reset","object","key"),&Tween::reset ); ObjectTypeDB::bind_method(_MD("reset_all"),&Tween::reset_all ); - ObjectTypeDB::bind_method(_MD("stop","node","key"),&Tween::stop ); + ObjectTypeDB::bind_method(_MD("stop","object","key"),&Tween::stop ); ObjectTypeDB::bind_method(_MD("stop_all"),&Tween::stop_all ); - ObjectTypeDB::bind_method(_MD("resume","node","key"),&Tween::resume ); + ObjectTypeDB::bind_method(_MD("resume","object","key"),&Tween::resume ); ObjectTypeDB::bind_method(_MD("resume_all"),&Tween::resume_all ); - ObjectTypeDB::bind_method(_MD("remove","node","key"),&Tween::remove ); + ObjectTypeDB::bind_method(_MD("remove","object","key"),&Tween::remove ); ObjectTypeDB::bind_method(_MD("remove_all"),&Tween::remove_all ); ObjectTypeDB::bind_method(_MD("seek","time"),&Tween::seek ); ObjectTypeDB::bind_method(_MD("tell"),&Tween::tell ); ObjectTypeDB::bind_method(_MD("get_runtime"),&Tween::get_runtime ); - ObjectTypeDB::bind_method(_MD("interpolate_property","node","property","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_property, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("interpolate_method","node","method","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_method, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("interpolate_callback","node","callback","times_in_sec","args"),&Tween::interpolate_callback, DEFVAL(Variant()) ); - ObjectTypeDB::bind_method(_MD("follow_property","node","property","initial_val","target","target_property","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_property, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("follow_method","node","method","initial_val","target","target_method","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_method, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("targeting_property","node","property","initial","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_property, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("targeting_method","node","method","initial","initial_method","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_method, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("interpolate_property","object","property","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_property, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("interpolate_method","object","method","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_method, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("interpolate_callback","object","times_in_sec","callback","arg1", "arg2","arg3","arg4","arg5"),&Tween::interpolate_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) ); + ObjectTypeDB::bind_method(_MD("interpolate_deferred_callback","object","times_in_sec","callback","arg1","arg2","arg3","arg4","arg5"),&Tween::interpolate_deferred_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) ); + ObjectTypeDB::bind_method(_MD("follow_property","object","property","initial_val","target","target_property","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_property, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("follow_method","object","method","initial_val","target","target_method","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_method, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("targeting_property","object","property","initial","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_property, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("targeting_method","object","method","initial","initial_method","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_method, DEFVAL(0) ); - ADD_SIGNAL( MethodInfo("tween_start", PropertyInfo( Variant::OBJECT,"node"), PropertyInfo( Variant::STRING,"key")) ); - ADD_SIGNAL( MethodInfo("tween_step", PropertyInfo( Variant::OBJECT,"node"), PropertyInfo( Variant::STRING,"key"), PropertyInfo( Variant::REAL,"elapsed"), PropertyInfo( Variant::OBJECT,"value")) ); - ADD_SIGNAL( MethodInfo("tween_complete", PropertyInfo( Variant::OBJECT,"node"), PropertyInfo( Variant::STRING,"key")) ); + ADD_SIGNAL( MethodInfo("tween_start", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key")) ); + ADD_SIGNAL( MethodInfo("tween_step", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key"), PropertyInfo( Variant::REAL,"elapsed"), PropertyInfo( Variant::OBJECT,"value")) ); + ADD_SIGNAL( MethodInfo("tween_complete", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key")) ); ADD_PROPERTY( PropertyInfo( Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_tween_process_mode"), _SCS("get_tween_process_mode")); - //ADD_PROPERTY( PropertyInfo( Variant::BOOL, "activate"), _SCS("set_active"), _SCS("is_active")); + + BIND_CONSTANT(TWEEN_PROCESS_FIXED); + BIND_CONSTANT(TWEEN_PROCESS_IDLE); BIND_CONSTANT(TRANS_LINEAR); BIND_CONSTANT(TRANS_SINE); @@ -181,19 +184,19 @@ Variant& Tween::_get_initial_val(InterpolateData& p_data) { case TARGETING_PROPERTY: case TARGETING_METHOD: { - Node *node = get_node(p_data.target); - ERR_FAIL_COND_V(node == NULL,p_data.initial_val); + Object *object = ObjectDB::get_instance(p_data.target_id); + ERR_FAIL_COND_V(object == NULL,p_data.initial_val); static Variant initial_val; if(p_data.type == TARGETING_PROPERTY) { bool valid = false; - initial_val = node->get(p_data.target_key, &valid); + initial_val = object->get(p_data.target_key, &valid); ERR_FAIL_COND_V(!valid,p_data.initial_val); } else { Variant::CallError error; - initial_val = node->call(p_data.target_key, NULL, 0, error); + initial_val = object->call(p_data.target_key, NULL, 0, error); ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK,p_data.initial_val); } return initial_val; @@ -213,7 +216,7 @@ Variant& Tween::_get_delta_val(InterpolateData& p_data) { case FOLLOW_PROPERTY: case FOLLOW_METHOD: { - Node *target = get_node(p_data.target); + Object *target = ObjectDB::get_instance(p_data.target_id); ERR_FAIL_COND_V(target == NULL,p_data.initial_val); Variant final_val; @@ -264,6 +267,11 @@ Variant Tween::_run_equation(InterpolateData& p_data) { switch(initial_val.get_type()) { + + case Variant::BOOL: + result = ((int) _run_equation(p_data.trans_type, p_data.ease_type, p_data.elapsed - p_data.delay, (int) initial_val, (int) delta_val, p_data.times_in_sec)) >= 0.5; + break; + case Variant::INT: result = (int) _run_equation(p_data.trans_type, p_data.ease_type, p_data.elapsed - p_data.delay, (int) initial_val, (int) delta_val, p_data.times_in_sec); break; @@ -409,7 +417,7 @@ Variant Tween::_run_equation(InterpolateData& p_data) { bool Tween::_apply_tween_value(InterpolateData& p_data, Variant& value) { - Object *object = get_node(p_data.path); + Object *object = ObjectDB::get_instance(p_data.id); ERR_FAIL_COND_V(object == NULL, false); switch(p_data.type) { @@ -452,6 +460,7 @@ void Tween::_tween_process(float p_delta) { return; p_delta *= speed_scale; + pending_update ++; // if repeat and all interpolates was finished then reset all interpolates if(repeat) { bool all_finished = true; @@ -476,7 +485,7 @@ void Tween::_tween_process(float p_delta) { if(!data.active || data.finish) continue; - Object *object = get_node(data.path); + Object *object = ObjectDB::get_instance(data.id); if(object == NULL) continue; @@ -505,11 +514,33 @@ void Tween::_tween_process(float p_delta) { if(data.finish) { Variant::CallError error; - if (data.arg.get_type() != Variant::NIL) { - Variant *arg[1] = { &data.arg }; - object->call(data.key, (const Variant **) arg, 1, error); - } else { - object->call(data.key, NULL, 0, error); + if (data.call_deferred) { + + switch (data.args) { + case 0: + object->call_deferred(data.key); break; + case 1: + object->call_deferred(data.key, data.arg[0]); break; + case 2: + object->call_deferred(data.key, data.arg[0], data.arg[1]); break; + case 3: + object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2]); break; + case 4: + object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2], data.arg[3]); break; + case 5: + object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2], data.arg[3], data.arg[4]); break; + } + + } + else { + Variant *arg[5] = { + &data.arg[0], + &data.arg[1], + &data.arg[2], + &data.arg[3], + &data.arg[4], + }; + object->call(data.key, (const Variant **) arg, data.args, error); } } continue; @@ -523,6 +554,7 @@ void Tween::_tween_process(float p_delta) { if(data.finish) emit_signal("tween_complete",object,data.key); } + pending_update --; } void Tween::set_tween_process_mode(TweenProcessMode p_mode) { @@ -598,16 +630,17 @@ bool Tween::start() { return true; } -bool Tween::reset(Node *p_node, String p_key) { +bool Tween::reset(Object *p_object, String p_key) { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) { + if(object == p_object && data.key == p_key) { data.elapsed = 0; data.finish = false; @@ -615,11 +648,13 @@ bool Tween::reset(Node *p_node, String p_key) { _apply_tween_value(data, data.initial_val); } } + pending_update --; return true; } bool Tween::reset_all() { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); @@ -628,20 +663,23 @@ bool Tween::reset_all() { if(data.delay == 0) _apply_tween_value(data, data.initial_val); } + pending_update --; return true; } -bool Tween::stop(Node *p_node, String p_key) { +bool Tween::stop(Object *p_object, String p_key) { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) + if(object == p_object && data.key == p_key) data.active = false; } + pending_update --; return true; } @@ -650,28 +688,32 @@ bool Tween::stop_all() { set_active(false); _set_process(false); + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); data.active = false; } + pending_update --; return true; } -bool Tween::resume(Node *p_node, String p_key) { +bool Tween::resume(Object *p_object, String p_key) { set_active(true); _set_process(true); + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) + if(object == p_object && data.key == p_key) data.active = true; } + pending_update --; return true; } @@ -680,23 +722,26 @@ bool Tween::resume_all() { set_active(true); _set_process(true); + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); data.active = true; } + pending_update --; return true; } -bool Tween::remove(Node *p_node, String p_key) { +bool Tween::remove(Object *p_object, String p_key) { + ERR_FAIL_COND_V(pending_update != 0, false); for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) { + if(object == p_object && data.key == p_key) { interpolates.erase(E); return true; } @@ -706,6 +751,7 @@ bool Tween::remove(Node *p_node, String p_key) { bool Tween::remove_all() { + ERR_FAIL_COND_V(pending_update != 0, false); set_active(false); _set_process(false); interpolates.clear(); @@ -714,6 +760,7 @@ bool Tween::remove_all() { bool Tween::seek(real_t p_time) { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); @@ -744,11 +791,13 @@ bool Tween::seek(real_t p_time) { _apply_tween_value(data, result); } + pending_update --; return true; } real_t Tween::tell() const { + pending_update ++; real_t pos = 0; for(const List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { @@ -756,11 +805,13 @@ real_t Tween::tell() const { if(data.elapsed > pos) pos = data.elapsed; } + pending_update --; return pos; } real_t Tween::get_runtime() const { + pending_update ++; real_t runtime = 0; for(const List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { @@ -769,6 +820,7 @@ real_t Tween::get_runtime() const { if(t > runtime) runtime = t; } + pending_update --; return runtime; } @@ -779,6 +831,12 @@ bool Tween::_calc_delta_val(const Variant& p_initial_val, const Variant& p_final Variant& delta_val = p_delta_val; switch(initial_val.get_type()) { + + case Variant::BOOL: + //delta_val = p_final_val; + delta_val = (int) p_final_val - (int) p_initial_val; + break; + case Variant::INT: delta_val = (int) final_val - (int) initial_val; break; @@ -873,7 +931,7 @@ bool Tween::_calc_delta_val(const Variant& p_initial_val, const Variant& p_final return true; } -bool Tween::interpolate_property(Node *p_node +bool Tween::interpolate_property(Object *p_object , String p_property , Variant p_initial_val , Variant p_final_val @@ -882,11 +940,12 @@ bool Tween::interpolate_property(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial_val.get_type() != p_final_val.get_type(), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -894,7 +953,7 @@ bool Tween::interpolate_property(Node *p_node ERR_FAIL_COND_V(p_delay < 0, false); bool prop_valid = false; - p_node->get(p_property,&prop_valid); + p_object->get(p_property,&prop_valid); ERR_FAIL_COND_V(!prop_valid, false); InterpolateData data; @@ -903,7 +962,7 @@ bool Tween::interpolate_property(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_property; data.initial_val = p_initial_val; data.final_val = p_final_val; @@ -919,7 +978,7 @@ bool Tween::interpolate_property(Node *p_node return true; } -bool Tween::interpolate_method(Node *p_node +bool Tween::interpolate_method(Object *p_object , String p_method , Variant p_initial_val , Variant p_final_val @@ -928,18 +987,19 @@ bool Tween::interpolate_method(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial_val.get_type() != p_final_val.get_type(), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_method), false); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); InterpolateData data; data.active = true; @@ -947,7 +1007,7 @@ bool Tween::interpolate_method(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_method; data.initial_val = p_initial_val; data.final_val = p_final_val; @@ -963,47 +1023,123 @@ bool Tween::interpolate_method(Node *p_node return true; } -bool Tween::interpolate_callback(Node *p_node +bool Tween::interpolate_callback(Object *p_object + , real_t p_times_in_sec , String p_callback + , VARIANT_ARG_DECLARE +) { + + ERR_FAIL_COND_V(pending_update != 0, false); + ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(p_times_in_sec < 0, false); + + ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); + + InterpolateData data; + data.active = true; + data.type = INTER_CALLBACK; + data.finish = false; + data.call_deferred = false; + data.elapsed = 0; + + data.id = p_object->get_instance_ID(); + data.key = p_callback; + data.times_in_sec = p_times_in_sec; + data.delay = 0; + + int args=0; + if (p_arg5.get_type()!=Variant::NIL) + args=5; + else if (p_arg4.get_type()!=Variant::NIL) + args=4; + else if (p_arg3.get_type()!=Variant::NIL) + args=3; + else if (p_arg2.get_type()!=Variant::NIL) + args=2; + else if (p_arg1.get_type()!=Variant::NIL) + args=1; + else + args=0; + + data.args = args; + data.arg[0] = p_arg1; + data.arg[1] = p_arg2; + data.arg[2] = p_arg3; + data.arg[3] = p_arg4; + data.arg[4] = p_arg5; + + pending_update ++; + interpolates.push_back(data); + pending_update --; + return true; +} + +bool Tween::interpolate_deferred_callback(Object *p_object , real_t p_times_in_sec - , Variant p_arg + , String p_callback + , VARIANT_ARG_DECLARE ) { - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(pending_update != 0, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_callback), false); + ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); InterpolateData data; data.active = true; data.type = INTER_CALLBACK; data.finish = false; + data.call_deferred = true; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_callback; data.times_in_sec = p_times_in_sec; data.delay = 0; - data.arg = p_arg; + int args=0; + if (p_arg5.get_type()!=Variant::NIL) + args=5; + else if (p_arg4.get_type()!=Variant::NIL) + args=4; + else if (p_arg3.get_type()!=Variant::NIL) + args=3; + else if (p_arg2.get_type()!=Variant::NIL) + args=2; + else if (p_arg1.get_type()!=Variant::NIL) + args=1; + else + args=0; + + data.args = args; + data.arg[0] = p_arg1; + data.arg[1] = p_arg2; + data.arg[2] = p_arg3; + data.arg[3] = p_arg4; + data.arg[4] = p_arg5; + + pending_update ++; interpolates.push_back(data); + pending_update --; return true; } -bool Tween::follow_property(Node *p_node +bool Tween::follow_property(Object *p_object , String p_property , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_property , real_t p_times_in_sec , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_target == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -1011,7 +1147,7 @@ bool Tween::follow_property(Node *p_node ERR_FAIL_COND_V(p_delay < 0, false); bool prop_valid = false; - p_node->get(p_property,&prop_valid); + p_object->get(p_property,&prop_valid); ERR_FAIL_COND_V(!prop_valid, false); bool target_prop_valid = false; @@ -1028,10 +1164,10 @@ bool Tween::follow_property(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_property; data.initial_val = p_initial_val; - data.target = p_target->get_path(); + data.target_id = p_target->get_instance_ID(); data.target_key = p_target_property; data.times_in_sec = p_times_in_sec; data.trans_type = p_trans_type; @@ -1042,27 +1178,28 @@ bool Tween::follow_property(Node *p_node return true; } -bool Tween::follow_method(Node *p_node +bool Tween::follow_method(Object *p_object , String p_method , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_method , real_t p_times_in_sec , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_target == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_method), false); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); ERR_FAIL_COND_V(!p_target->has_method(p_target_method), false); Variant::CallError error; @@ -1079,10 +1216,10 @@ bool Tween::follow_method(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_method; data.initial_val = p_initial_val; - data.target = p_target->get_path(); + data.target_id = p_target->get_instance_ID(); data.target_key = p_target_method; data.times_in_sec = p_times_in_sec; data.trans_type = p_trans_type; @@ -1093,9 +1230,9 @@ bool Tween::follow_method(Node *p_node return true; } -bool Tween::targeting_property(Node *p_node +bool Tween::targeting_property(Object *p_object , String p_property - , Node *p_initial + , Object *p_initial , String p_initial_property , Variant p_final_val , real_t p_times_in_sec @@ -1103,10 +1240,11 @@ bool Tween::targeting_property(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -1114,7 +1252,7 @@ bool Tween::targeting_property(Node *p_node ERR_FAIL_COND_V(p_delay < 0, false); bool prop_valid = false; - p_node->get(p_property,&prop_valid); + p_object->get(p_property,&prop_valid); ERR_FAIL_COND_V(!prop_valid, false); bool initial_prop_valid = false; @@ -1131,9 +1269,9 @@ bool Tween::targeting_property(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_property; - data.target = p_initial->get_path(); + data.target_id = p_initial->get_instance_ID(); data.target_key = p_initial_property; data.initial_val = initial_val; data.final_val = p_final_val; @@ -1150,9 +1288,9 @@ bool Tween::targeting_property(Node *p_node } -bool Tween::targeting_method(Node *p_node +bool Tween::targeting_method(Object *p_object , String p_method - , Node *p_initial + , Object *p_initial , String p_initial_method , Variant p_final_val , real_t p_times_in_sec @@ -1160,17 +1298,18 @@ bool Tween::targeting_method(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_method), false); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); ERR_FAIL_COND_V(!p_initial->has_method(p_initial_method), false); Variant::CallError error; @@ -1187,9 +1326,9 @@ bool Tween::targeting_method(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_method; - data.target = p_initial->get_path(); + data.target_id = p_initial->get_instance_ID(); data.target_key = p_initial_method; data.initial_val = initial_val; data.final_val = p_final_val; @@ -1213,6 +1352,7 @@ Tween::Tween() { active=false; repeat=false; speed_scale=1; + pending_update=0; } Tween::~Tween() { diff --git a/scene/animation/tween.h b/scene/animation/tween.h index c9d9863397..d34c9e6ba2 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -54,15 +54,17 @@ public: TRANS_CIRC, TRANS_BOUNCE, TRANS_BACK, - TRANS_COUNT, + + TRANS_COUNT, }; enum EaseType { EASE_IN, EASE_OUT, EASE_IN_OUT, - EASE_OUT_IN, - EASE_COUNT, + EASE_OUT_IN, + + EASE_COUNT, }; private: @@ -81,19 +83,21 @@ private: bool active; InterpolateType type; bool finish; + bool call_deferred; real_t elapsed; - NodePath path; + ObjectID id; StringName key; Variant initial_val; Variant delta_val; Variant final_val; - NodePath target; + ObjectID target_id; StringName target_key; real_t times_in_sec; TransitionType trans_type; EaseType ease_type; real_t delay; - Variant arg; + int args; + Variant arg[5]; }; String autoplay; @@ -102,6 +106,7 @@ private: bool active; bool repeat; float speed_scale; + mutable int pending_update; List<InterpolateData> interpolates; @@ -142,20 +147,20 @@ public: float get_speed() const; bool start(); - bool reset(Node *p_node, String p_key); + bool reset(Object *p_node, String p_key); bool reset_all(); - bool stop(Node *p_node, String p_key); + bool stop(Object *p_node, String p_key); bool stop_all(); - bool resume(Node *p_node, String p_key); + bool resume(Object *p_node, String p_key); bool resume_all(); - bool remove(Node *p_node, String p_key); + bool remove(Object *p_node, String p_key); bool remove_all(); bool seek(real_t p_time); real_t tell() const; real_t get_runtime() const; - bool interpolate_property(Node *p_node + bool interpolate_property(Object *p_node , String p_property , Variant p_initial_val , Variant p_final_val @@ -165,7 +170,7 @@ public: , real_t p_delay = 0 ); - bool interpolate_method(Node *p_node + bool interpolate_method(Object *p_node , String p_method , Variant p_initial_val , Variant p_final_val @@ -175,16 +180,22 @@ public: , real_t p_delay = 0 ); - bool interpolate_callback(Node *p_node + bool interpolate_callback(Object *p_object + , real_t p_times_in_sec , String p_callback + , VARIANT_ARG_DECLARE + ); + + bool interpolate_deferred_callback(Object *p_object , real_t p_times_in_sec - , Variant p_arg = Variant() + , String p_callback + , VARIANT_ARG_DECLARE ); - bool follow_property(Node *p_node + bool follow_property(Object *p_node , String p_property , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_property , real_t p_times_in_sec , TransitionType p_trans_type @@ -192,10 +203,10 @@ public: , real_t p_delay = 0 ); - bool follow_method(Node *p_node + bool follow_method(Object *p_node , String p_method , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_method , real_t p_times_in_sec , TransitionType p_trans_type @@ -203,9 +214,9 @@ public: , real_t p_delay = 0 ); - bool targeting_property(Node *p_node + bool targeting_property(Object *p_node , String p_property - , Node *p_initial + , Object *p_initial , String p_initial_property , Variant p_final_val , real_t p_times_in_sec @@ -214,9 +225,9 @@ public: , real_t p_delay = 0 ); - bool targeting_method(Node *p_node + bool targeting_method(Object *p_node , String p_method - , Node *p_initial + , Object *p_initial , String p_initial_method , Variant p_final_val , real_t p_times_in_sec diff --git a/scene/audio/event_player.cpp b/scene/audio/event_player.cpp index e5b2be53ca..dc46f4711c 100644 --- a/scene/audio/event_player.cpp +++ b/scene/audio/event_player.cpp @@ -33,13 +33,13 @@ void EventPlayer::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { //set_idle_process(false); //don't annoy - if (playback.is_valid() && autoplay && !get_scene()->is_editor_hint()) + if (playback.is_valid() && autoplay && !get_tree()->is_editor_hint()) play(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { stop(); //wathever it may be doing, stop } break; @@ -75,7 +75,7 @@ Ref<EventStream> EventPlayer::get_stream() const { void EventPlayer::play() { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); if (playback.is_null()) { return; } @@ -93,7 +93,7 @@ void EventPlayer::play() { void EventPlayer::stop() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (playback.is_null()) return; @@ -241,7 +241,7 @@ bool EventPlayer::is_paused() const { void EventPlayer::_set_play(bool p_play) { _play=p_play; - if (is_inside_scene()) { + if (is_inside_tree()) { if(_play) play(); else diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp index 90994f01b4..bf1c5e97a3 100644 --- a/scene/audio/sample_player.cpp +++ b/scene/audio/sample_player.cpp @@ -498,6 +498,7 @@ bool SamplePlayer::is_active() const { void SamplePlayer::set_sample_library(const Ref<SampleLibrary>& p_library) { library=p_library; + _change_notify(); } Ref<SampleLibrary> SamplePlayer::get_sample_library() const { diff --git a/scene/audio/sound_room_params.cpp b/scene/audio/sound_room_params.cpp index 3e0a64b3f1..f1067f12e0 100644 --- a/scene/audio/sound_room_params.cpp +++ b/scene/audio/sound_room_params.cpp @@ -53,8 +53,8 @@ void SoundRoomParams::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { -#if 0 + case NOTIFICATION_ENTER_TREE: { +//#if 0 Node *n=this; Room *room_instance=NULL; while(n) { @@ -74,14 +74,14 @@ void SoundRoomParams::_notification(int p_what) { if (room_instance) { room=room_instance->get_sound_room(); } else { - room=get_scene()->get_default_world()->get_sound_space(); + room=get_viewport()->find_world()->get_sound_space(); } _update_sound_room(); -#endif +//#endif } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { room=RID(); diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index 5084c1295b..73025fb52c 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -33,13 +33,13 @@ void StreamPlayer::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { //set_idle_process(false); //don't annoy - if (stream.is_valid() && autoplay && !get_scene()->is_editor_hint()) + if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) play(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { stop(); //wathever it may be doing, stop } break; @@ -75,7 +75,7 @@ Ref<AudioStream> StreamPlayer::get_stream() const { void StreamPlayer::play() { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); if (stream.is_null()) return; if (stream->is_playing()) @@ -91,7 +91,7 @@ void StreamPlayer::play() { void StreamPlayer::stop() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (stream.is_null()) return; @@ -214,7 +214,7 @@ bool StreamPlayer::is_paused() const { void StreamPlayer::_set_play(bool p_play) { _play=p_play; - if (is_inside_scene()) { + if (is_inside_tree()) { if(_play) play(); else diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index ac2417d539..bbe15da1cc 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -30,7 +30,7 @@ #include "os/keyboard.h" #include "print_string.h" #include "button_group.h" - +#include "scene/scene_string_names.h" void BaseButton::_input_event(InputEvent p_event) { @@ -56,13 +56,25 @@ void BaseButton::_input_event(InputEvent p_event) { if (!toggle_mode) { //mouse press attempt + status.press_attempt=true; + status.pressing_inside=true; + pressed(); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed,NULL,0,ce); + } + emit_signal("pressed"); } else { status.pressed=!status.pressed; pressed(); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed,NULL,0,ce); + } emit_signal("pressed"); toggled(status.pressed); @@ -71,8 +83,15 @@ void BaseButton::_input_event(InputEvent p_event) { } - } + } else { + if (status.press_attempt && status.pressing_inside) { +// released(); + emit_signal("released"); + } + status.press_attempt=false; + } + update(); break; } @@ -85,14 +104,19 @@ void BaseButton::_input_event(InputEvent p_event) { if (status.press_attempt &&status.pressing_inside) { - + if (!toggle_mode) { //mouse press attempt - + pressed(); - emit_signal("pressed"); + if (get_script_instance()) { + Variant::CallError ce; + get_script_instance()->call(SceneStringNames::get_singleton()->_pressed,NULL,0,ce); + } + + emit_signal("pressed"); } else { - + status.pressed=!status.pressed; pressed(); @@ -100,11 +124,15 @@ void BaseButton::_input_event(InputEvent p_event) { toggled(status.pressed); emit_signal("toggled",status.pressed); - + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_toggled,status.pressed); + } + + } - + } - + status.press_attempt=false; } @@ -167,6 +195,9 @@ void BaseButton::_input_event(InputEvent p_event) { emit_signal("pressed"); toggled(status.pressed); + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_toggled,status.pressed); + } emit_signal("toggled",status.pressed); } } @@ -201,7 +232,7 @@ void BaseButton::_notification(int p_what) { } } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { CanvasItem *ci=this; while(ci) { @@ -217,7 +248,7 @@ void BaseButton::_notification(int p_what) { } } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { if (group) group->_remove_button(this); @@ -248,12 +279,12 @@ void BaseButton::set_disabled(bool p_disabled) { set_focus_mode(FOCUS_NONE); else set_focus_mode(FOCUS_ALL); -}; +} bool BaseButton::is_disabled() const { return status.disabled; -}; +} void BaseButton::set_pressed(bool p_pressed) { @@ -336,6 +367,8 @@ bool BaseButton::get_click_on_press() const { } + + void BaseButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&BaseButton::_input_event); @@ -348,13 +381,25 @@ void BaseButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_disabled"),&BaseButton::is_disabled); ObjectTypeDB::bind_method(_MD("set_click_on_press","enable"),&BaseButton::set_click_on_press); ObjectTypeDB::bind_method(_MD("get_click_on_press"),&BaseButton::get_click_on_press); + ObjectTypeDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode); + + BIND_VMETHOD(MethodInfo("_pressed")); + BIND_VMETHOD(MethodInfo("_toggled",PropertyInfo(Variant::BOOL,"pressed"))); ADD_SIGNAL( MethodInfo("pressed" ) ); + ADD_SIGNAL( MethodInfo("released" ) ); ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) ); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode")); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press")); + + BIND_CONSTANT( DRAW_NORMAL ); + BIND_CONSTANT( DRAW_PRESSED ); + BIND_CONSTANT( DRAW_HOVER ); + BIND_CONSTANT( DRAW_DISABLED ); + } BaseButton::BaseButton() { diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index a2c640b9cf..a376591ebb 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -61,15 +61,8 @@ class BaseButton : public Control { protected: - enum DrawMode { - DRAW_NORMAL, - DRAW_PRESSED, - DRAW_HOVER, - DRAW_DISABLED, - }; - DrawMode get_draw_mode() const; virtual void pressed(); virtual void toggled(bool p_pressed); @@ -78,7 +71,16 @@ protected: void _notification(int p_what); public: - + + enum DrawMode { + DRAW_NORMAL, + DRAW_PRESSED, + DRAW_HOVER, + DRAW_DISABLED, + }; + + DrawMode get_draw_mode() const; + /* Signals */ bool is_pressed() const; ///< return wether button is pressed (toggled in) @@ -101,4 +103,6 @@ public: }; +VARIANT_ENUM_CAST( BaseButton::DrawMode ); + #endif diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 216c6d7122..5ed60e88f8 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -44,7 +44,7 @@ void BoxContainer::_resort() { Size2i new_size=get_size();; - int sep=get_constant("separation",vertical?"VBoxContainer":"HBoxContainer"); + int sep=get_constant("separation");//,vertical?"VBoxContainer":"HBoxContainer"); bool first=true; int children_count=0; @@ -202,7 +202,7 @@ Size2 BoxContainer::get_minimum_size() const { /* Calculate MINIMUM SIZE */ Size2i minimum; - int sep=get_constant("separation",vertical?"VBoxContainer":"HBoxContainer"); + int sep=get_constant("separation");//,vertical?"VBoxContainer":"HBoxContainer"); bool first=true; diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 58b323c24d..94cc0a8d51 100644 --- a/scene/gui/button_group.cpp +++ b/scene/gui/button_group.cpp @@ -117,7 +117,7 @@ BaseButton *ButtonGroup::get_focused_button() const{ int ButtonGroup::get_pressed_button_index() const { //in tree order, this is bizarre - ERR_FAIL_COND_V(!is_inside_scene(),0); + ERR_FAIL_COND_V(!is_inside_tree(),0); BaseButton *pressed = get_pressed_button(); if (!pressed) diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp new file mode 100644 index 0000000000..309152ba8f --- /dev/null +++ b/scene/gui/check_box.cpp @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* check_button.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 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 */ +/* "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 "check_box.h" + +#include "servers/visual_server.h" +#include "button_group.h" + + +void CheckBox::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + RID ci = get_canvas_item(); + + Ref<Texture> on=Control::get_icon(is_radio() ? "radio_checked" : "checked"); + Ref<Texture> off=Control::get_icon(is_radio() ? "radio_unchecked" : "unchecked"); + + Vector2 ofs; + ofs.x = 0; + ofs.y = int((get_size().height - on->get_height())/2); + + if (is_pressed()) + on->draw(ci,ofs); + else + off->draw(ci,ofs); + + + } +} + +bool CheckBox::is_radio() +{ + Node* parent = this; + do { + parent = parent->get_parent(); + if (dynamic_cast< ButtonGroup* >(parent)) + break; + } while (parent); + + return (parent != 0); +} + +CheckBox::CheckBox(const String &p_text): + Button(p_text) +{ + set_toggle_mode(true); + set_text_align(ALIGN_LEFT); + +} + +CheckBox::~CheckBox() +{ +} diff --git a/scene/gui/empty_control.h b/scene/gui/check_box.h index 993af45ac4..171fd55351 100644 --- a/scene/gui/empty_control.h +++ b/scene/gui/check_box.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* empty_control.h */ +/* check_box.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -26,23 +26,30 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EMPTY_CONTROL_H
-#define EMPTY_CONTROL_H
-
-#include "scene/gui/control.h"
-
-class EmptyControl : public Control {
-
- OBJ_TYPE(EmptyControl,Control);
- Size2 minsize;
-protected:
- static void _bind_methods();
-public:
- virtual Size2 get_minimum_size() const;
- void set_minsize(const Size2& p_size);
- Size2 get_minsize() const;
-
- EmptyControl();
-};
-
-#endif // EMPTY_CONTROL_H
+#ifndef CHECK_BOX_H +#define CHECK_BOX_H + + +#include "scene/gui/button.h" +/** +@author Mariano Suligoy <marianognu.esyrpg@gmail.com> +*/ +class CheckBox : public Button { + + OBJ_TYPE( CheckBox, Button ); + + +protected: + void _notification(int p_what); + + bool is_radio(); + + +public: + + CheckBox(const String& p_text=String()); + ~CheckBox(); + +}; + +#endif diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 193649c815..d944b804a5 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -352,6 +352,7 @@ void ColorPickerButton::set_color(const Color& p_color){ picker->set_color(p_color); + update(); } Color ColorPickerButton::get_color() const{ diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 6543a0388d..bb61723acf 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -67,7 +67,7 @@ void Container::remove_child_notify(Node *p_child) { void Container::_sort_children() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; notification(NOTIFICATION_SORT_CHILDREN); @@ -101,7 +101,7 @@ void Container::fit_child_in_rect(Control *p_child,const Rect2& p_rect) { void Container::queue_sort() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (pending_sort) @@ -115,7 +115,7 @@ void Container::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { pending_sort=false; queue_sort(); } break; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index fc24294a70..c539dc3284 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -183,7 +183,7 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) { void Control::_update_minimum_size() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; data.pending_min_size_update=false; @@ -341,7 +341,7 @@ void Control::_notification(int p_notification) { switch(p_notification) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (data.window==this) { @@ -365,7 +365,7 @@ void Control::_notification(int p_notification) { window->drag_attempted=false; window->drag_preview=NULL; - if (get_scene()->is_editor_hint()) { + if (get_tree()->is_editor_hint()) { Node *n = this; while(n) { @@ -385,7 +385,7 @@ void Control::_notification(int p_notification) { _size_changed(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (data.window) { @@ -630,7 +630,7 @@ void Control::_notification(int p_notification) { } } break; - case SceneMainLoop::NOTIFICATION_WM_UNFOCUS_REQUEST: { + case SceneTree::NOTIFICATION_WM_UNFOCUS_REQUEST: { if (!window) return; @@ -710,7 +710,7 @@ void Control::drop_data(const Point2& p_point,const Variant& p_data){ void Control::force_drag(const Variant& p_data,Control *p_control) { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!data.window); ERR_FAIL_COND(p_data.get_type()==Variant::NIL); @@ -728,8 +728,8 @@ void Control::set_drag_preview(Control *p_control) { ERR_FAIL_NULL(p_control); ERR_FAIL_COND( !((Object*)p_control)->cast_to<Control>()); - ERR_FAIL_COND(!is_inside_scene() || !data.window); - ERR_FAIL_COND(p_control->is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree() || !data.window); + ERR_FAIL_COND(p_control->is_inside_tree()); ERR_FAIL_COND(p_control->get_parent()!=NULL); if (data.window->window->drag_preview) { @@ -940,67 +940,67 @@ void Control::_window_input_event(InputEvent p_event) { case InputEvent::MOUSE_BUTTON: { - window->key_event_accepted=false; + window->key_event_accepted=false; - Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y)); - if (p_event.mouse_button.pressed) { + Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y)); + if (p_event.mouse_button.pressed) { - Size2 pos = mpos; - if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) { + Size2 pos = mpos; + if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) { - //do not steal mouse focus and stuff + //do not steal mouse focus and stuff - } else { + } else { - _window_sort_modal_stack(); - while (!window->modal_stack.empty()) { + _window_sort_modal_stack(); + while (!window->modal_stack.empty()) { - Control *top = window->modal_stack.back()->get(); - if (!top->has_point(top->get_global_transform().affine_inverse().xform(pos))) { + Control *top = window->modal_stack.back()->get(); + if (!top->has_point(top->get_global_transform().affine_inverse().xform(pos))) { - if (top->data.modal_exclusive) { - //cancel event, sorry, modal exclusive EATS UP ALL - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); - get_scene()->set_input_as_handled(); - return; // no one gets the event if exclusive NO ONE - } + if (top->data.modal_exclusive) { + //cancel event, sorry, modal exclusive EATS UP ALL + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); + return; // no one gets the event if exclusive NO ONE + } - top->notification(NOTIFICATION_MODAL_CLOSE); - top->_modal_stack_remove(); - top->hide(); - } else { - break; + top->notification(NOTIFICATION_MODAL_CLOSE); + top->_modal_stack_remove(); + top->hide(); + } else { + break; + } } - } - Matrix32 parent_xform; + Matrix32 parent_xform; - if (data.parent_canvas_item) - parent_xform=data.parent_canvas_item->get_global_transform(); + if (data.parent_canvas_item) + parent_xform=data.parent_canvas_item->get_global_transform(); - window->mouse_focus = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform); - //print_line("has mf "+itos(window->mouse_focus!=NULL)); - window->mouse_focus_button=p_event.mouse_button.button_index; + window->mouse_focus = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform); + //print_line("has mf "+itos(window->mouse_focus!=NULL)); + window->mouse_focus_button=p_event.mouse_button.button_index; - if (!window->mouse_focus) { - break; - } + if (!window->mouse_focus) { + break; + } - if (p_event.mouse_button.button_index==BUTTON_LEFT) { - window->drag_accum=Vector2(); - window->drag_attempted=false; - window->drag_data=Variant(); - } + if (p_event.mouse_button.button_index==BUTTON_LEFT) { + window->drag_accum=Vector2(); + window->drag_attempted=false; + window->drag_data=Variant(); + } - } + } p_event.mouse_button.global_x = pos.x; p_event.mouse_button.global_y = pos.y; @@ -1020,8 +1020,8 @@ void Control::_window_input_event(InputEvent p_event) { /*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) { - print_line(String(window->mouse_focus->get_path())+" - "+pos); - }*/ + print_line(String(window->mouse_focus->get_path())+" - "+pos); + }*/ #endif if (window->mouse_focus->get_focus_mode()!=FOCUS_NONE && window->mouse_focus!=window->key_focus && p_event.mouse_button.button_index==BUTTON_LEFT) { @@ -1033,9 +1033,11 @@ void Control::_window_input_event(InputEvent p_event) { if (window->mouse_focus->can_process()) { _window_call_input(window->mouse_focus,p_event); } - - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); - get_scene()->set_input_as_handled(); + + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); + + window->tooltip_popup->hide(); } else { @@ -1079,8 +1081,8 @@ void Control::_window_input_event(InputEvent p_event) { } - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); - get_scene()->set_input_as_handled(); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); } } break; @@ -1126,6 +1128,7 @@ void Control::_window_input_event(InputEvent p_event) { over = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform); } + if (window->drag_data.get_type()==Variant::NIL && over && !window->modal_stack.empty()) { Control *top = window->modal_stack.back()->get(); @@ -1147,7 +1150,7 @@ void Control::_window_input_event(InputEvent p_event) { window->mouse_over=over; - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_tooltip"); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_tooltip"); if (window->drag_preview) { window->drag_preview->set_pos(pos); @@ -1203,8 +1206,8 @@ void Control::_window_input_event(InputEvent p_event) { - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); - get_scene()->set_input_as_handled(); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); if (window->drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) { @@ -1230,7 +1233,7 @@ void Control::_window_input_event(InputEvent p_event) { if (window->key_event_accepted) { - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); break; } } @@ -1290,7 +1293,7 @@ void Control::_window_input_event(InputEvent p_event) { if (next) { next->grab_focus(); - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); } } @@ -1305,7 +1308,7 @@ Control *Control::get_window() const { bool Control::is_window() const { - return (is_inside_scene() && window); + return (is_inside_tree() && window); } @@ -1325,9 +1328,12 @@ Size2 Control::get_minimum_size() const { Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const { - const Ref<Texture>* tex = data.icon_override.getptr(p_name); - if (tex) - return *tex; + if (p_type==StringName()) { + + const Ref<Texture>* tex = data.icon_override.getptr(p_name); + if (tex) + return *tex; + } StringName type = p_type?p_type:get_type_name(); @@ -1353,12 +1359,11 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const { - - const Ref<StyleBox>* style = data.style_override.getptr(p_name); - - - if (style) - return *style; + if (p_type==StringName()) { + const Ref<StyleBox>* style = data.style_override.getptr(p_name); + if (style) + return *style; + } StringName type = p_type?p_type:get_type_name(); @@ -1381,10 +1386,12 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p } Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const { - - const Ref<Font>* font = data.font_override.getptr(p_name); - if (font) - return *font; + + if (p_type==StringName()) { + const Ref<Font>* font = data.font_override.getptr(p_name); + if (font) + return *font; + } StringName type = p_type?p_type:get_type_name(); @@ -1410,10 +1417,12 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c } Color Control::get_color(const StringName& p_name,const StringName& p_type) const { - - const Color* color = data.color_override.getptr(p_name); - if (color) - return *color; + + if (p_type==StringName()) { + const Color* color = data.color_override.getptr(p_name); + if (color) + return *color; + } StringName type = p_type?p_type:get_type_name(); // try with custom themes @@ -1437,10 +1446,12 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons } int Control::get_constant(const StringName& p_name,const StringName& p_type) const { - - const int* constant = data.constant_override.getptr(p_name); - if (constant) - return *constant; + + if (p_type==StringName()) { + const int* constant = data.constant_override.getptr(p_name); + if (constant) + return *constant; + } StringName type = p_type?p_type:get_type_name(); // try with custom themes @@ -1467,9 +1478,11 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con bool Control::has_icon(const StringName& p_name,const StringName& p_type) const { - const Ref<Texture>* tex = data.icon_override.getptr(p_name); - if (tex) - return true; + if (p_type==StringName()) { + const Ref<Texture>* tex = data.icon_override.getptr(p_name); + if (tex) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1494,11 +1507,12 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const } bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const { - - const Ref<StyleBox>* style = data.style_override.getptr(p_name); - - if (style) - return true; + if (p_type==StringName()) { + const Ref<StyleBox>* style = data.style_override.getptr(p_name); + + if (style) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1523,9 +1537,11 @@ bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) co } bool Control::has_font(const StringName& p_name,const StringName& p_type) const { - const Ref<Font>* font = data.font_override.getptr(p_name); - if (font) - return true; + if (p_type==StringName()) { + const Ref<Font>* font = data.font_override.getptr(p_name); + if (font) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1551,9 +1567,11 @@ bool Control::has_font(const StringName& p_name,const StringName& p_type) const } bool Control::has_color(const StringName& p_name,const StringName& p_type) const { - const Color* color = data.color_override.getptr(p_name); - if (color) - return true; + if (p_type==StringName()) { + const Color* color = data.color_override.getptr(p_name); + if (color) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1578,10 +1596,13 @@ bool Control::has_color(const StringName& p_name,const StringName& p_type) const } bool Control::has_constant(const StringName& p_name,const StringName& p_type) const { - - const int* constant = data.constant_override.getptr(p_name); - if (constant) - return true; + + if (p_type==StringName()) { + + const int* constant = data.constant_override.getptr(p_name); + if (constant) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1607,7 +1628,7 @@ bool Control::has_constant(const StringName& p_name,const StringName& p_type) co Size2 Control::get_parent_area_size() const { - ERR_FAIL_COND_V(!is_inside_scene(),Size2()); + ERR_FAIL_COND_V(!is_inside_tree(),Size2()); Size2 parent_size; @@ -1624,7 +1645,7 @@ Size2 Control::get_parent_area_size() const { void Control::_size_changed() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; Size2 parent_size = get_parent_area_size(); @@ -1677,7 +1698,7 @@ void Control::_size_changed() { float Control::_get_parent_range(int p_idx) const { - if (!is_inside_scene()) { + if (!is_inside_tree()) { return 1.0; @@ -1748,7 +1769,7 @@ float Control::_a2s(float p_val, AnchorType p_anchor,float p_range) const { void Control::set_anchor(Margin p_margin,AnchorType p_anchor) { - if (!is_inside_scene()) { + if (!is_inside_tree()) { data.anchor[p_margin]=p_anchor; } else { @@ -1980,7 +2001,7 @@ void Control::add_constant_override(const StringName& p_name, int p_constant) { void Control::set_focus_mode(FocusMode p_focus_mode) { - if (is_inside_scene() && p_focus_mode == FOCUS_NONE && data.focus_mode!=FOCUS_NONE && has_focus()) + if (is_inside_tree() && p_focus_mode == FOCUS_NONE && data.focus_mode!=FOCUS_NONE && has_focus()) release_focus(); data.focus_mode=p_focus_mode; @@ -2178,7 +2199,7 @@ bool Control::has_focus() const { void Control::grab_focus() { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!data.window); if (data.focus_mode==FOCUS_NONE) @@ -2188,7 +2209,7 @@ void Control::grab_focus() { if (data.window->window->key_focus && data.window->window->key_focus==this) return; - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_window_remove_focus"); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_window_remove_focus"); data.window->window->key_focus=this; notification(NOTIFICATION_FOCUS_ENTER); #ifdef DEBUG_ENABLED @@ -2202,13 +2223,13 @@ void Control::grab_focus() { void Control::release_focus() { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!data.window); if (!has_focus()) return; - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,"windows","_window_remove_focus"); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_window_remove_focus"); //data.window->window->key_focus=this; //notification(NOTIFICATION_FOCUS_ENTER); update(); @@ -2217,12 +2238,12 @@ void Control::release_focus() { bool Control::is_toplevel_control() const { - return is_inside_scene() && (!data.parent_canvas_item && !window && is_set_as_toplevel()); + return is_inside_tree() && (!data.parent_canvas_item && !window && is_set_as_toplevel()); } void Control::show_modal(bool p_exclusive) { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!data.SI && data.window!=this); ERR_FAIL_COND(!data.window); @@ -2248,7 +2269,10 @@ void Control::_window_sort_subwindows() { if (!window->subwindow_order_dirty) return; + window->modal_stack.sort_custom<CComparator>(); + window->subwindows.sort_custom<CComparator>(); + window->subwindow_order_dirty=false; } @@ -2282,7 +2306,7 @@ void Control::_modal_stack_remove() { if (!pfoc) return; - if (!pfoc->is_inside_scene() || !pfoc->is_visible()) + if (!pfoc->is_inside_tree() || !pfoc->is_visible()) return; pfoc->grab_focus(); } else { @@ -2332,13 +2356,13 @@ void Control::set_theme(const Ref<Theme>& p_theme) { void Control::_window_accept_event() { window->key_event_accepted=true; - if (is_inside_scene()) - get_scene()->set_input_as_handled(); + if (is_inside_tree()) + get_tree()->set_input_as_handled(); } void Control::accept_event() { - if (is_inside_scene() && get_window()) + if (is_inside_tree() && get_window()) get_window()->_window_accept_event(); } @@ -2585,7 +2609,7 @@ float Control::get_stretch_ratio() const { void Control::grab_click_focus() { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); if (data.window && data.window->window->mouse_focus) { @@ -2620,7 +2644,7 @@ void Control::grab_click_focus() { void Control::minimum_size_changed() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (data.pending_min_size_update) @@ -2663,9 +2687,15 @@ bool Control::is_stopping_mouse() const { Control *Control::get_focus_owner() const { - ERR_FAIL_COND_V(!is_inside_scene(),NULL); - ERR_FAIL_COND_V(!window,NULL); - return window->key_focus; + ERR_FAIL_COND_V(!is_inside_tree(),NULL); + ERR_FAIL_COND_V(!data.window,NULL); + return data.window->window->key_focus; +} + + +void Control::warp_mouse(const Point2& p_to_pos) { + ERR_FAIL_COND(!is_inside_tree()); + get_viewport()->warp_mouse(get_global_transform().xform(p_to_pos)); } void Control::_bind_methods() { @@ -2764,6 +2794,9 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview); + ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse); + + BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size")); BIND_VMETHOD(MethodInfo(Variant::OBJECT,"get_drag_data",PropertyInfo(Variant::VECTOR2,"pos"))); @@ -2836,7 +2869,7 @@ void Control::_bind_methods() { BIND_CONSTANT( SIZE_EXPAND_FILL ); ADD_SIGNAL( MethodInfo("resized") ); - ADD_SIGNAL( MethodInfo("input_event") ); + ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) ); ADD_SIGNAL( MethodInfo("mouse_enter") ); ADD_SIGNAL( MethodInfo("mouse_exit") ); ADD_SIGNAL( MethodInfo("focus_enter") ); diff --git a/scene/gui/control.h b/scene/gui/control.h index 64b5a9b661..7e14bff098 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -380,7 +380,7 @@ public: void grab_click_focus(); - + void warp_mouse(const Point2& p_to_pos); Control(); ~Control(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index ac0ded03ab..30e0241f23 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -93,7 +93,7 @@ void WindowDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { close_button->set_normal_texture( get_icon("close","WindowDialog")); close_button->set_pressed_texture( get_icon("close","WindowDialog")); @@ -297,7 +297,7 @@ void AcceptDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_label"),&AcceptDialog::get_label); ObjectTypeDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok); ObjectTypeDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok); - ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_cancel,DEFVAL(false),DEFVAL("")); + ObjectTypeDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL("")); ObjectTypeDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel); ObjectTypeDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered); ObjectTypeDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter); @@ -328,8 +328,8 @@ AcceptDialog::AcceptDialog() { label->set_anchor(MARGIN_RIGHT,ANCHOR_END); label->set_anchor(MARGIN_BOTTOM,ANCHOR_END); label->set_begin( Point2( margin, margin) ); - label->set_end( Point2( margin, button_margin) ); - label->set_autowrap(true); + label->set_end( Point2( margin, button_margin+10) ); + //label->set_autowrap(true); add_child(label); hbc = memnew( HBoxContainer ); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index a7ff1431bd..2e8a84e39b 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -29,6 +29,8 @@ #include "file_dialog.h" #include "scene/gui/label.h" #include "print_string.h" +#include "os/keyboard.h" + FileDialog::GetIconFunc FileDialog::get_icon_func=NULL; @@ -156,7 +158,6 @@ void FileDialog::_action_pressed() { if (mode==MODE_SAVE_FILE) { - String ext = f.extension(); bool valid=false; if (filter->get_selected()==filter->get_item_count()-1) { @@ -184,7 +185,8 @@ void FileDialog::_action_pressed() { if (idx>=0 && idx<filters.size()) { String flt=filters[idx].get_slice(";",0); - for (int j=0;j<flt.get_slice_count(",");j++) { + int filterSliceCount=flt.get_slice_count(","); + for (int j=0;j<filterSliceCount;j++) { String str = (flt.get_slice(",",j).strip_edges()); if (f.match(str)) { @@ -192,6 +194,13 @@ void FileDialog::_action_pressed() { break; } } + + if (!valid && filterSliceCount>0) { + String str = (flt.get_slice(",",0).strip_edges()); + f+=str.substr(1, str.length()-1); + file->set_text(f.get_file()); + valid=true; + } } else { valid=true; } @@ -271,13 +280,20 @@ void FileDialog::update_file_list() { List<String> dirs; bool isdir; + bool ishidden; + bool show_hidden = show_hidden_files; String item; + while ((item=dir_access->get_next(&isdir))!="") { - - if (!isdir) - files.push_back(item); - else - dirs.push_back(item); + + ishidden = dir_access->current_is_hidden(); + + if (show_hidden || !ishidden) { + if (!isdir) + files.push_back(item); + else + dirs.push_back(item); + } } dirs.sort_custom<NoCaseComparator>(); @@ -609,6 +625,9 @@ void FileDialog::_update_drives() { } } +bool FileDialog::default_show_hidden_files=true; + + void FileDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_tree_selected"),&FileDialog::_tree_selected); @@ -633,6 +652,8 @@ void FileDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&FileDialog::get_vbox); ObjectTypeDB::bind_method(_MD("set_access","access"),&FileDialog::set_access); ObjectTypeDB::bind_method(_MD("get_access"),&FileDialog::get_access); + ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&FileDialog::set_show_hidden_files); + ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files); ObjectTypeDB::bind_method(_MD("_select_drive"),&FileDialog::_select_drive); ObjectTypeDB::bind_method(_MD("_make_dir"),&FileDialog::_make_dir); ObjectTypeDB::bind_method(_MD("_make_dir_confirm"),&FileDialog::_make_dir_confirm); @@ -657,9 +678,23 @@ void FileDialog::_bind_methods() { } +void FileDialog::set_show_hidden_files(bool p_show) { + show_hidden_files=p_show; + invalidate(); +} + +bool FileDialog::is_showing_hidden_files() const { + return show_hidden_files; +} + +void FileDialog::set_default_show_hidden_files(bool p_show) { + default_show_hidden_files=p_show; +} FileDialog::FileDialog() { - + + show_hidden_files=true; + VBoxContainer *vbc = memnew( VBoxContainer ); add_child(vbc); set_child_rect(vbc); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index bda1797696..6b35035829 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -89,6 +89,10 @@ private: Vector<String> filters; + + static bool default_show_hidden_files; + bool show_hidden_files; + bool invalidated; void update_dir(); @@ -141,6 +145,11 @@ public: void set_access(Access p_access); Access get_access() const; + void set_show_hidden_files(bool p_show); + bool is_showing_hidden_files() const; + + static void set_default_show_hidden_files(bool p_show); + void invalidate(); FileDialog(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp new file mode 100644 index 0000000000..3cd0dd3d16 --- /dev/null +++ b/scene/gui/graph_edit.cpp @@ -0,0 +1,586 @@ +#include "graph_edit.h" +#include "os/input.h" +#include "os/keyboard.h" +bool GraphEditFilter::has_point(const Point2& p_point) const { + + return ge->_filter_input(p_point); +} + + +GraphEditFilter::GraphEditFilter(GraphEdit *p_edit) { + + ge=p_edit; +} + + +Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) { + + if (is_node_connected(p_from,p_from_port,p_to,p_to_port)) + return OK; + Connection c; + c.from=p_from; + c.from_port=p_from_port; + c.to=p_to; + c.to_port=p_to_port; + connections.push_back(c); + top_layer->update(); + + return OK; +} + +bool GraphEdit::is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) { + + for(List<Connection>::Element *E=connections.front();E;E=E->next()) { + + if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) + return true; + } + + return false; + +} + +void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port){ + + + for(List<Connection>::Element *E=connections.front();E;E=E->next()) { + + if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) { + + connections.erase(E); + top_layer->update(); + return; + } + } +} + +void GraphEdit::get_connection_list(List<Connection> *r_connections) const { + + *r_connections=connections; +} + + +void GraphEdit::_scroll_moved(double) { + + + _update_scroll_offset(); + top_layer->update(); +} + +void GraphEdit::_update_scroll_offset() { + + for(int i=0;i<get_child_count();i++) { + + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) + continue; + + Point2 pos=gn->get_offset(); + pos-=Point2(h_scroll->get_val(),v_scroll->get_val()); + gn->set_pos(pos); + } + +} + +void GraphEdit::_update_scroll() { + + if (updating) + return; + + updating=true; + Rect2 screen; + for(int i=0;i<get_child_count();i++) { + + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) + continue; + + Rect2 r; + r.pos=gn->get_offset(); + r.size=gn->get_size(); + screen = screen.merge(r); + } + + screen.pos-=get_size(); + screen.size+=get_size()*2.0; + + + h_scroll->set_min(screen.pos.x); + h_scroll->set_max(screen.pos.x+screen.size.x); + h_scroll->set_page(get_size().x); + if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page()) + h_scroll->hide(); + else + h_scroll->show(); + + v_scroll->set_min(screen.pos.y); + v_scroll->set_max(screen.pos.y+screen.size.y); + v_scroll->set_page(get_size().y); + + if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page()) + v_scroll->hide(); + else + v_scroll->show(); + + _update_scroll_offset(); + updating=false; +} + + +void GraphEdit::_graph_node_raised(Node* p_gn) { + + GraphNode *gn=p_gn->cast_to<GraphNode>(); + ERR_FAIL_COND(!gn); + gn->raise(); + top_layer->raise(); + +} + + +void GraphEdit::_graph_node_moved(Node *p_gn) { + + GraphNode *gn=p_gn->cast_to<GraphNode>(); + ERR_FAIL_COND(!gn); + + //gn->set_pos(gn->get_offset()+scroll_offset); + + top_layer->update(); +} + +void GraphEdit::add_child_notify(Node *p_child) { + + top_layer->call_deferred("raise"); //top layer always on top! + GraphNode *gn = p_child->cast_to<GraphNode>(); + if (gn) { + gn->connect("offset_changed",this,"_graph_node_moved",varray(gn)); + gn->connect("raise_request",this,"_graph_node_raised",varray(gn)); + _graph_node_moved(gn); + gn->set_stop_mouse(false); + } +} + +void GraphEdit::remove_child_notify(Node *p_child) { + + top_layer->call_deferred("raise"); //top layer always on top! + GraphNode *gn = p_child->cast_to<GraphNode>(); + if (gn) { + gn->disconnect("offset_changed",this,"_graph_node_moved"); + gn->disconnect("raise_request",this,"_graph_node_raised"); + } +} + +void GraphEdit::_notification(int p_what) { + + if (p_what==NOTIFICATION_READY) { + Size2 size = top_layer->get_size(); + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + + v_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0); + v_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,0); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + h_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,0); + h_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0); + h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height); + h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + } + if (p_what==NOTIFICATION_DRAW) { + VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + + } + + if (p_what==NOTIFICATION_RESIZED) { + _update_scroll(); + top_layer->update(); + } +} + +bool GraphEdit::_filter_input(const Point2& p_point) { + + Ref<Texture> port =get_icon("port","GraphNode"); + + float grab_r=port->get_width()*0.5; + for(int i=get_child_count()-1;i>=0;i--) { + + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) + continue; + + for(int j=0;j<gn->get_connection_output_count();j++) { + + Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); + if (pos.distance_to(p_point)<grab_r) + return true; + + + } + + for(int j=0;j<gn->get_connection_input_count();j++) { + + Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); + if (pos.distance_to(p_point)<grab_r) + return true; + + + } + + } + + return false; +} + +void GraphEdit::_top_layer_input(const InputEvent& p_ev) { + + if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) { + + Ref<Texture> port =get_icon("port","GraphNode"); + Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); + float grab_r=port->get_width()*0.5; + for(int i=get_child_count()-1;i>=0;i--) { + + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) + continue; + + for(int j=0;j<gn->get_connection_output_count();j++) { + + Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); + if (pos.distance_to(mpos)<grab_r) { + + connecting=true; + connecting_from=gn->get_name(); + connecting_index=j; + connecting_out=true; + connecting_type=gn->get_connection_output_type(j); + connecting_color=gn->get_connection_output_color(j); + connecting_target=false; + connecting_to=pos; + return; + } + + + } + + for(int j=0;j<gn->get_connection_input_count();j++) { + + Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); + + if (pos.distance_to(mpos)<grab_r) { + + if (right_disconnects) { + //check disconnect + for (List<Connection>::Element*E=connections.front();E;E=E->next()) { + + if (E->get().to==gn->get_name() && E->get().to_port==j) { + + Node*fr = get_node(String(E->get().from)); + if (fr && fr->cast_to<GraphNode>()) { + + connecting_from=E->get().from; + connecting_index=E->get().from_port; + connecting_out=true; + connecting_type=fr->cast_to<GraphNode>()->get_connection_output_type(E->get().from_port); + connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port); + connecting_target=false; + connecting_to=pos; + + emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); + fr = get_node(String(connecting_from)); //maybe it was erased + if (fr && fr->cast_to<GraphNode>()) { + connecting=true; + } + return; + } + + } + } + } + + + connecting=true; + connecting_from=gn->get_name(); + connecting_index=j; + connecting_out=false; + connecting_type=gn->get_connection_input_type(j); + connecting_color=gn->get_connection_input_color(j); + connecting_target=false; + connecting_to=pos; + return; + } + + + } + } + } + + if (p_ev.type==InputEvent::MOUSE_MOTION && connecting) { + + connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); + connecting_target=false; + top_layer->update(); + + Ref<Texture> port =get_icon("port","GraphNode"); + Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); + float grab_r=port->get_width()*0.5; + for(int i=get_child_count()-1;i>=0;i--) { + + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (!gn) + continue; + + if (!connecting_out) { + for(int j=0;j<gn->get_connection_output_count();j++) { + + Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); + int type =gn->get_connection_output_type(j); + if (type==connecting_type && pos.distance_to(mpos)<grab_r) { + + connecting_target=true; + connecting_to=pos; + connecting_target_to=gn->get_name(); + connecting_target_index=j; + return; + } + + + } + } else { + + for(int j=0;j<gn->get_connection_input_count();j++) { + + Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); + int type =gn->get_connection_input_type(j); + if (type==connecting_type && pos.distance_to(mpos)<grab_r) { + connecting_target=true; + connecting_to=pos; + connecting_target_to=gn->get_name(); + connecting_target_index=j; + return; + } + } + } + } + } + + if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && !p_ev.mouse_button.pressed) { + + if (connecting && connecting_target) { + + String from = connecting_from; + int from_slot = connecting_index; + String to =connecting_target_to; + int to_slot = connecting_target_index; + + if (!connecting_out) { + SWAP(from,to); + SWAP(from_slot,to_slot); + } + emit_signal("connection_request",from,from_slot,to,to_slot); + + } + connecting=false; + top_layer->update(); + + } + + + +} + +void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) { + + static const int steps = 20; + + Rect2 r; + r.pos=p_from; + r.expand_to(p_to); + Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1); + bool flip = sign.x * sign.y < 0; + + Vector2 prev; + for(int i=0;i<=steps;i++) { + + float d = i/float(steps); + float c=-Math::cos(d*Math_PI) * 0.5+0.5; + if (flip) + c=1.0-c; + Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height); + + if (i>0) { + + top_layer->draw_line(prev,p,p_color,2); + } + + prev=p; + } +} + +void GraphEdit::_top_layer_draw() { + + _update_scroll(); + + if (connecting) { + + Node *fromn = get_node(connecting_from); + ERR_FAIL_COND(!fromn); + GraphNode *from = fromn->cast_to<GraphNode>(); + ERR_FAIL_COND(!from); + Vector2 pos; + if (connecting_out) + pos=from->get_connection_output_pos(connecting_index); + else + pos=from->get_connection_input_pos(connecting_index); + pos+=from->get_pos(); + + Vector2 topos; + topos=connecting_to; + + Color col=connecting_color; + + if (connecting_target) { + col.r+=0.4; + col.g+=0.4; + col.b+=0.4; + } + _draw_cos_line(pos,topos,col); + } + + List<List<Connection>::Element* > to_erase; + for(List<Connection>::Element *E=connections.front();E;E=E->next()) { + + NodePath fromnp(E->get().from); + + Node * from = get_node(fromnp); + if (!from) { + to_erase.push_back(E); + continue; + } + + GraphNode *gfrom = from->cast_to<GraphNode>(); + + if (!gfrom) { + to_erase.push_back(E); + continue; + } + + NodePath tonp(E->get().to); + Node * to = get_node(tonp); + if (!to) { + to_erase.push_back(E); + continue; + } + + GraphNode *gto = to->cast_to<GraphNode>(); + + if (!gto) { + to_erase.push_back(E); + continue; + } + + Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_pos(); + Color color = gfrom->get_connection_output_color(E->get().from_port); + Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_pos(); + _draw_cos_line(frompos,topos,color); + + } + + while(to_erase.size()) { + connections.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + //draw connections +} + +void GraphEdit::_input_event(const InputEvent& p_ev) { + + if (p_ev.type==InputEvent::MOUSE_MOTION && (p_ev.mouse_motion.button_mask&BUTTON_MASK_MIDDLE || (p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { + h_scroll->set_val( h_scroll->get_val() - p_ev.mouse_motion.relative_x ); + v_scroll->set_val( v_scroll->get_val() - p_ev.mouse_motion.relative_y ); + } +} + +void GraphEdit::clear_connections() { + + connections.clear(); + update(); +} + + +void GraphEdit::set_right_disconnects(bool p_enable) { + + right_disconnects=p_enable; +} + +bool GraphEdit::is_right_disconnects_enabled() const{ + + return right_disconnects; +} + +Array GraphEdit::_get_connection_list() const { + + List<Connection> conns; + get_connection_list(&conns); + Array arr; + for(List<Connection>::Element *E=conns.front();E;E=E->next()) { + Dictionary d; + d["from"]=E->get().from; + d["from_port"]=E->get().from_port; + d["to"]=E->get().to; + d["to_port"]=E->get().to_port; + arr.push_back(d); + } + return arr; +} +void GraphEdit::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node); + ObjectTypeDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected); + ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node); + ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list); + + ObjectTypeDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects); + ObjectTypeDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled); + + ObjectTypeDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved); + ObjectTypeDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised); + + ObjectTypeDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input); + ObjectTypeDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw); + ObjectTypeDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved); + + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event); + + ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); + ADD_SIGNAL(MethodInfo("disconnection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); + +} + + + +GraphEdit::GraphEdit() { + top_layer=NULL; + top_layer=memnew(GraphEditFilter(this)); + add_child(top_layer); + top_layer->set_stop_mouse(false); + top_layer->set_area_as_parent_rect(); + top_layer->connect("draw",this,"_top_layer_draw"); + top_layer->set_stop_mouse(false); + top_layer->connect("input_event",this,"_top_layer_input"); + + h_scroll = memnew(HScrollBar); + h_scroll->set_name("_h_scroll"); + top_layer->add_child(h_scroll); + + v_scroll = memnew(VScrollBar); + v_scroll->set_name("_v_scroll"); + top_layer->add_child(v_scroll); + updating=false; + connecting=false; + right_disconnects=false; + + h_scroll->connect("value_changed", this,"_scroll_moved"); + v_scroll->connect("value_changed", this,"_scroll_moved"); +} diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h new file mode 100644 index 0000000000..0a9da73ab6 --- /dev/null +++ b/scene/gui/graph_edit.h @@ -0,0 +1,100 @@ +#ifndef GRAPH_EDIT_H +#define GRAPH_EDIT_H + +#include "scene/gui/graph_node.h" +#include "scene/gui/scroll_bar.h" + +class GraphEdit; + +class GraphEditFilter : public Control { + + OBJ_TYPE(GraphEditFilter,Control); + +friend class GraphEdit; + GraphEdit *ge; + virtual bool has_point(const Point2& p_point) const; + +public: + + + GraphEditFilter(GraphEdit *p_edit); +}; + +class GraphEdit : public Control { + + OBJ_TYPE(GraphEdit,Control); +public: + + struct Connection { + StringName from; + StringName to; + int from_port; + int to_port; + + }; +private: + + HScrollBar* h_scroll; + VScrollBar* v_scroll; + + + bool connecting; + String connecting_from; + bool connecting_out; + int connecting_index; + int connecting_type; + Color connecting_color; + bool connecting_target; + Vector2 connecting_to; + String connecting_target_to; + int connecting_target_index; + + + + bool right_disconnects; + bool updating; + List<Connection> connections; + + void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color); + + void _graph_node_raised(Node* p_gn); + void _graph_node_moved(Node *p_gn); + + void _update_scroll(); + void _scroll_moved(double); + void _input_event(const InputEvent& p_ev); + + GraphEditFilter *top_layer; + void _top_layer_input(const InputEvent& p_ev); + void _top_layer_draw(); + void _update_scroll_offset(); + + Array _get_connection_list() const; + +friend class GraphEditFilter; + bool _filter_input(const Point2& p_point); +protected: + + static void _bind_methods(); + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + void _notification(int p_what); + +public: + + Error connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); + bool is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); + void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); + void clear_connections(); + + GraphEditFilter *get_top_layer() const { return top_layer; } + void get_connection_list(List<Connection> *r_connections) const; + + void set_right_disconnects(bool p_enable); + bool is_right_disconnects_enabled() const; + + + GraphEdit(); +}; + +#endif // GRAPHEdit_H diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp new file mode 100644 index 0000000000..444b37855f --- /dev/null +++ b/scene/gui/graph_node.cpp @@ -0,0 +1,583 @@ +#include "graph_node.h" +#include "method_bind_ext.inc" + + +bool GraphNode::_set(const StringName& p_name, const Variant& p_value) { + + if (!p_name.operator String().begins_with("slot/")) + return false; + + int idx=p_name.operator String().get_slice("/",1).to_int(); + String what = p_name.operator String().get_slice("/",2); + + + Slot si; + if (slot_info.has(idx)) + si=slot_info[idx]; + + + if (what=="left_enabled") + si.enable_left=p_value; + else if (what=="left_type") + si.type_left=p_value; + else if (what=="left_color") + si.color_left=p_value; + else if (what=="right_enabled") + si.enable_right=p_value; + else if (what=="right_type") + si.type_right=p_value; + else if (what=="right_color") + si.color_right=p_value; + else + return false; + + set_slot(idx,si.enable_left,si.type_left,si.color_left,si.enable_right,si.type_right,si.color_right); + update(); + return true; +} + +bool GraphNode::_get(const StringName& p_name,Variant &r_ret) const{ + + + + if (!p_name.operator String().begins_with("slot/")) { + return false; + } + + int idx=p_name.operator String().get_slice("/",1).to_int(); + String what = p_name.operator String().get_slice("/",2); + + + + Slot si; + if (slot_info.has(idx)) + si=slot_info[idx]; + + if (what=="left_enabled") + r_ret=si.enable_left; + else if (what=="left_type") + r_ret=si.type_left; + else if (what=="left_color") + r_ret=si.color_left; + else if (what=="right_enabled") + r_ret=si.enable_right; + else if (what=="right_type") + r_ret=si.type_right; + else if (what=="right_color") + r_ret=si.color_right; + else + return false; + + return true; +} +void GraphNode::_get_property_list( List<PropertyInfo> *p_list) const{ + + int idx=0; + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c || c->is_set_as_toplevel() ) + continue; + + String base="slot/"+itos(idx)+"/"; + + p_list->push_back(PropertyInfo(Variant::BOOL,base+"left_enabled")); + p_list->push_back(PropertyInfo(Variant::INT,base+"left_type")); + p_list->push_back(PropertyInfo(Variant::COLOR,base+"left_color")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"right_enabled")); + p_list->push_back(PropertyInfo(Variant::INT,base+"right_type")); + p_list->push_back(PropertyInfo(Variant::COLOR,base+"right_color")); + + idx++; + } +} + + +void GraphNode::_resort() { + + + + int sep=get_constant("separation"); + Ref<StyleBox> sb=get_stylebox("frame"); + bool first=true; + + Size2 minsize; + + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + minsize.y+=size.y; + minsize.x=MAX(minsize.x,size.x); + + if (first) + first=false; + else + minsize.y+=sep; + + } + + + int vofs=0; + int w = get_size().x - sb->get_minimum_size().x; + + + cache_y.clear(); + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + Rect2 r(sb->get_margin(MARGIN_LEFT),sb->get_margin(MARGIN_TOP)+vofs,w,size.y); + + fit_child_in_rect(c,r); + cache_y.push_back(vofs+size.y*0.5); + + if (vofs>0) + vofs+=sep; + vofs+=size.y; + + + } + + _change_notify(); + update(); + connpos_dirty=true; + + +} + + +void GraphNode::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + Ref<StyleBox> sb=get_stylebox("frame"); + Ref<Texture> port =get_icon("port"); + Ref<Texture> close =get_icon("close"); + int close_offset = get_constant("close_offset"); + Ref<Font> title_font = get_font("title_font"); + int title_offset = get_constant("title_offset"); + Color title_color = get_color("title_color"); + Point2i icofs = -port->get_size()*0.5; + int edgeofs=get_constant("port_offset"); + icofs.y+=sb->get_margin(MARGIN_TOP); + draw_style_box(sb,Rect2(Point2(),get_size())); + + int w = get_size().width-sb->get_minimum_size().x; + + if (show_close) + w-=close->get_width(); + + draw_string(title_font,Point2(sb->get_margin(MARGIN_LEFT),-title_font->get_height()+title_font->get_ascent()+title_offset),title,title_color,w); + if (show_close) { + Vector2 cpos = Point2(w+sb->get_margin(MARGIN_LEFT),-close->get_height()+close_offset); + draw_texture(close,cpos); + close_rect.pos=cpos; + close_rect.size=close->get_size(); + } else { + close_rect=Rect2(); + } + + for (Map<int,Slot>::Element *E=slot_info.front();E;E=E->next()) { + + if (E->key() < 0 || E->key()>=cache_y.size()) + continue; + if (!slot_info.has(E->key())) + continue; + const Slot &s=slot_info[E->key()]; + //left + if (s.enable_left) + port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left); + if (s.enable_right) + port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right); + + } + } + + if (p_what==NOTIFICATION_SORT_CHILDREN) { + + _resort(); + } + +} + + +void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) { + + ERR_FAIL_COND(p_idx<0); + + if (!p_enable_left && p_type_left==0 && p_color_left==Color(1,1,1,1) && !p_enable_right && p_type_right==0 && p_color_right==Color(1,1,1,1)) { + slot_info.erase(p_idx); + return; + } + + Slot s; + s.enable_left=p_enable_left; + s.type_left=p_type_left; + s.color_left=p_color_left; + s.enable_right=p_enable_right; + s.type_right=p_type_right; + s.color_right=p_color_right; + slot_info[p_idx]=s; + update(); + connpos_dirty=true; + +} + +void GraphNode::clear_slot(int p_idx){ + + slot_info.erase(p_idx); + update(); + connpos_dirty=true; + +} +void GraphNode::clear_all_slots(){ + + slot_info.clear(); + update(); + connpos_dirty=true; + +} +bool GraphNode::is_slot_enabled_left(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return false; + return slot_info[p_idx].enable_left; + +} + +int GraphNode::get_slot_type_left(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return 0; + return slot_info[p_idx].type_left; + +} + +Color GraphNode::get_slot_color_left(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return Color(1,1,1,1); + return slot_info[p_idx].color_left; + +} + +bool GraphNode::is_slot_enabled_right(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return false; + return slot_info[p_idx].enable_right; + +} + + + +int GraphNode::get_slot_type_right(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return 0; + return slot_info[p_idx].type_right; + +} + +Color GraphNode::get_slot_color_right(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return Color(1,1,1,1); + return slot_info[p_idx].color_right; + +} + +Size2 GraphNode::get_minimum_size() const { + + Ref<Font> title_font = get_font("title_font"); + + int sep=get_constant("separation"); + Ref<StyleBox> sb=get_stylebox("frame"); + bool first=true; + + Size2 minsize; + minsize.x=title_font->get_string_size(title).x; + if (show_close) { + Ref<Texture> close =get_icon("close"); + minsize.x+=sep+close->get_width(); + } + + + for(int i=0;i<get_child_count();i++) { + + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + minsize.y+=size.y; + minsize.x=MAX(minsize.x,size.x); + + if (first) + first=false; + else + minsize.y+=sep; + } + + return minsize+sb->get_minimum_size(); +} + +void GraphNode::set_title(const String& p_title) { + + title=p_title; + minimum_size_changed(); + update(); + +} + +String GraphNode::get_title() const{ + + return title; +} + +void GraphNode::set_offset(const Vector2& p_offset) { + + offset=p_offset; + emit_signal("offset_changed"); + update(); +} + +Vector2 GraphNode::get_offset() const { + + return offset; +} + + + +void GraphNode::set_show_close_button(bool p_enable){ + + show_close=p_enable; + update(); +} +bool GraphNode::is_close_button_visible() const{ + + return show_close; +} + +void GraphNode::_connpos_update() { + + + int edgeofs=get_constant("port_offset"); + int sep=get_constant("separation"); + + Ref<StyleBox> sb=get_stylebox("frame"); + Ref<Texture> port =get_icon("port"); + conn_input_cache.clear(); + conn_output_cache.clear(); + int vofs=0; + + int idx=0; + + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + int y = sb->get_margin(MARGIN_TOP)+vofs; + int h = size.y; + + + if (slot_info.has(idx)) { + + if (slot_info[idx].enable_left) { + ConnCache cc; + cc.pos=Point2i(edgeofs,y+h/2); + cc.type=slot_info[idx].type_left; + cc.color=slot_info[idx].color_left; + conn_input_cache.push_back(cc); + } + if (slot_info[idx].enable_right) { + ConnCache cc; + cc.pos=Point2i(get_size().width-edgeofs,y+h/2); + cc.type=slot_info[idx].type_right; + cc.color=slot_info[idx].color_right; + conn_output_cache.push_back(cc); + } + } + + if (vofs>0) + vofs+=sep; + vofs+=size.y; + idx++; + + } + + + connpos_dirty=false; +} + +int GraphNode::get_connection_input_count() { + + if (connpos_dirty) + _connpos_update(); + + return conn_input_cache.size(); + +} +int GraphNode::get_connection_output_count() { + + if (connpos_dirty) + _connpos_update(); + + return conn_output_cache.size(); + +} + + +Vector2 GraphNode::get_connection_input_pos(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Vector2()); + return conn_input_cache[p_idx].pos; +} + +int GraphNode::get_connection_input_type(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),0); + return conn_input_cache[p_idx].type; +} + +Color GraphNode::get_connection_input_color(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Color()); + return conn_input_cache[p_idx].color; +} + +Vector2 GraphNode::get_connection_output_pos(int p_idx){ + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Vector2()); + return conn_output_cache[p_idx].pos; + +} + +int GraphNode::get_connection_output_type(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),0); + return conn_output_cache[p_idx].type; +} + +Color GraphNode::get_connection_output_color(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Color()); + return conn_output_cache[p_idx].color; +} + +void GraphNode::_input_event(const InputEvent& p_ev) { + + if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + + Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); + if (close_rect.size!=Size2() && close_rect.has_point(mpos)) { + emit_signal("close_request"); + return; + } + + drag_from=get_offset(); + drag_accum=Vector2(); + dragging=true; + emit_signal("raise_request"); + + } + + if (p_ev.type==InputEvent::MOUSE_BUTTON && !p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + + dragging=false; + emit_signal("dragged",drag_from,get_offset()); //useful for undo/redo + } + + if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) { + + drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + set_offset(drag_from+drag_accum); + } + +} + + +void GraphNode::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title); + ObjectTypeDB::bind_method(_MD("get_title"),&GraphNode::get_title); + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphNode::_input_event); + + ObjectTypeDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right"),&GraphNode::set_slot); + ObjectTypeDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot); + ObjectTypeDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots); + ObjectTypeDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left); + ObjectTypeDB::bind_method(_MD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left); + ObjectTypeDB::bind_method(_MD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left); + ObjectTypeDB::bind_method(_MD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right); + ObjectTypeDB::bind_method(_MD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right); + ObjectTypeDB::bind_method(_MD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right); + + ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset); + ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset); + + ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count); + ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count); + + ObjectTypeDB::bind_method(_MD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos); + ObjectTypeDB::bind_method(_MD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type); + ObjectTypeDB::bind_method(_MD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color); + ObjectTypeDB::bind_method(_MD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos); + ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type); + ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color); + + + ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button); + ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible); + + ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible")); + + ADD_SIGNAL(MethodInfo("offset_changed")); + ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to"))); + ADD_SIGNAL(MethodInfo("raise_request")); + ADD_SIGNAL(MethodInfo("close_request")); +} + +GraphNode::GraphNode() { + + dragging=false; + show_close=false; + connpos_dirty=true; +} diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h new file mode 100644 index 0000000000..0d5cbf8dd3 --- /dev/null +++ b/scene/gui/graph_node.h @@ -0,0 +1,101 @@ +#ifndef GRAPH_NODE_H +#define GRAPH_NODE_H + +#include "scene/gui/container.h" + +class GraphNode : public Container { + + OBJ_TYPE(GraphNode,Container); + + + + struct Slot { + bool enable_left; + int type_left; + Color color_left; + bool enable_right; + int type_right; + Color color_right; + + + Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); }; + }; + + String title; + bool show_close; + Vector2 offset; + + Rect2 close_rect; + + Vector<int> cache_y; + + struct ConnCache { + Vector2 pos; + int type; + Color color; + }; + + Vector<ConnCache> conn_input_cache; + Vector<ConnCache> conn_output_cache; + + Map<int,Slot> slot_info; + + bool connpos_dirty; + + void _connpos_update(); + void _resort(); + + Vector2 drag_from; + Vector2 drag_accum; + bool dragging; +protected: + + void _input_event(const InputEvent& p_ev); + void _notification(int p_what); + static void _bind_methods(); + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + + + + void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right); + void clear_slot(int p_idx); + void clear_all_slots(); + bool is_slot_enabled_left(int p_idx) const; + int get_slot_type_left(int p_idx) const; + Color get_slot_color_left(int p_idx) const; + bool is_slot_enabled_right(int p_idx) const; + int get_slot_type_right(int p_idx) const; + Color get_slot_color_right(int p_idx) const; + + void set_title(const String& p_title); + String get_title() const; + + void set_offset(const Vector2& p_offset); + Vector2 get_offset() const; + + void set_show_close_button(bool p_enable); + bool is_close_button_visible() const; + + int get_connection_input_count() ; + int get_connection_output_count() ; + Vector2 get_connection_input_pos(int p_idx); + int get_connection_input_type(int p_idx); + Color get_connection_input_color(int p_idx); + Vector2 get_connection_output_pos(int p_idx); + int get_connection_output_type(int p_idx); + Color get_connection_output_color(int p_idx); + + + virtual Size2 get_minimum_size() const; + + GraphNode(); +}; + + +#endif // GRAPH_NODE_H diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index f54345cdb8..582693eb3a 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -226,5 +226,6 @@ Size2 GridContainer::get_minimum_size() const { GridContainer::GridContainer() { + set_stop_mouse(false); columns=1; } diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 36940655d4..892e4c9bc7 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -72,6 +72,7 @@ void Label::_notification(int p_what) { if (clip && !autowrap) VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + if (word_cache_dirty) regenerate_word_cache(); @@ -87,7 +88,8 @@ void Label::_notification(int p_what) { bool use_outlinde = get_constant("shadow_as_outline"); Point2 shadow_ofs(get_constant("shadow_offset_x"),get_constant("shadow_offset_y")); - + VisualServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(),font.is_valid() && font->is_distance_field_hint()); + int font_h = font->get_height(); int line_from=(int)get_val(); // + p_exposed.pos.y / font_h; int lines_visible = size.y/font_h; @@ -339,7 +341,7 @@ int Label::get_longest_line_width() const { int Label::get_line_count() const { - if (!is_inside_scene()) + if (!is_inside_tree()) return 1; if (word_cache_dirty) const_cast<Label*>(this)->regenerate_word_cache(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index a77a40327f..68c990033a 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -572,7 +572,7 @@ void LineEdit::set_cursor_pos(int p_pos) { // set_window_pos(cursor_pos-get_window_lengt//h()); // } - if (!is_inside_scene()) { + if (!is_inside_tree()) { window_pos=cursor_pos; return; diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 7353744d07..d10ca20fc3 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -84,6 +84,7 @@ void MenuButton::pressed() { popup->set_parent_rect( Rect2(Point2(gp-popup->get_global_pos()),get_size())); popup->popup(); popup->call_deferred("grab_click_focus"); + popup->set_invalidate_click_until_motion(); } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index fa4a313115..78cc1bcdef 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -192,7 +192,7 @@ void OptionButton::_select(int p_idx,bool p_emit) { set_text( popup->get_item_text( current ) ); set_icon( popup->get_item_icon( current ) ); - if (is_inside_scene() && p_emit) + if (is_inside_tree() && p_emit) emit_signal("item_selected",current); } diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 65ad02723c..d58cb3da79 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -51,11 +51,18 @@ void Popup::_fix_size() { Control *window = get_window(); ERR_FAIL_COND(!window); - + +#if 0 Point2 pos = get_pos(); Size2 size = get_size(); Point2 window_size = window==this ? get_parent_area_size() :window->get_size(); +#else + Point2 pos = get_global_pos(); + Size2 size = get_size(); + Point2 window_size = get_viewport_rect().size; + +#endif if (pos.x+size.width > window_size.width) pos.x=window_size.width-size.width; if (pos.x<0) @@ -65,8 +72,14 @@ void Popup::_fix_size() { pos.y=window_size.height-size.height; if (pos.y<0) pos.y=0; +#if 0 if (pos!=get_pos()) set_pos(pos); +#else + if (pos!=get_pos()) + set_global_pos(pos); + +#endif } @@ -81,6 +94,8 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { Control *c=get_child(i)->cast_to<Control>(); if (!c) continue; + if (c->is_hidden()) + continue; Size2 minsize = c->get_combined_minimum_size(); @@ -101,6 +116,8 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { } + print_line(String(c->get_type())+": "+minsize); + total_minsize.width = MAX( total_minsize.width, minsize.width ); total_minsize.height = MAX( total_minsize.height, minsize.height ); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index c2dc1318c9..1fd1d8adc8 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -30,6 +30,7 @@ #include "print_string.h" #include "os/keyboard.h" #include "translation.h" +#include "os/input.h" String PopupMenu::_get_accel_text(uint32_t p_accel) const { @@ -318,6 +319,10 @@ void PopupMenu::_input_event(const InputEvent &p_event) { int over=_get_mouse_over(Point2(b.x,b.y)); + if (invalidated_click) { + invalidated_click=false; + break; + } if (over<0 || items[over].separator || items[over].disabled) break; //non-activable @@ -336,6 +341,13 @@ void PopupMenu::_input_event(const InputEvent &p_event) { case InputEvent::MOUSE_MOTION: { + if (invalidated_click) { + moved+=Vector2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y); + if (moved.length()>4) + invalidated_click=false; + + } + const InputEventMouseMotion &m=p_event.mouse_motion; for(List<Rect2>::Element *E=autohide_areas.front();E;E=E->next()) { @@ -855,7 +867,7 @@ void PopupMenu::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_check_item,DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1)); ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text); ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon); ObjectTypeDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator); @@ -893,12 +905,17 @@ void PopupMenu::_bind_methods() { } + +void PopupMenu::set_invalidate_click_until_motion() { + moved=Vector2(); + invalidated_click=true; +} + PopupMenu::PopupMenu() { idcount=0; mouse_over=-1; - set_focus_mode(FOCUS_ALL); set_as_toplevel(true); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index b150be1008..d825ea2b68 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -70,6 +70,8 @@ class PopupMenu : public Popup { void _activate_submenu(int over); void _submenu_timeout(); + bool invalidated_click; + Vector2 moved; Array _get_items() const; void _set_items(const Array& p_items); @@ -88,7 +90,7 @@ public: void add_icon_check_item(const Ref<Texture>& p_icon,const String& p_label,int p_ID=-1,uint32_t p_accel=0); void add_check_item(const String& p_label,int p_ID=-1,uint32_t p_accel=0); void add_submenu_item(const String& p_label,const String& p_submenu, int p_ID=-1); - + void set_item_text(int p_idx,const String& p_text); void set_item_icon(int p_idx,const Ref<Texture>& p_icon); void set_item_checked(int p_idx,bool p_checked); @@ -134,6 +136,8 @@ public: void add_autohide_area(const Rect2& p_area); void clear_autohide_areas(); + void set_invalidate_click_until_motion(); + PopupMenu(); ~PopupMenu(); diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index bc0fa9675e..4d0b678925 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -42,7 +42,7 @@ void Range::Shared::emit_value_changed() { for (Set<Range*>::Element *E=owners.front();E;E=E->next()) { Range *r=E->get(); - if (!r->is_inside_scene()) + if (!r->is_inside_tree()) continue; r->_value_changed_notify(); } @@ -59,7 +59,7 @@ void Range::Shared::emit_changed() { for (Set<Range*>::Element *E=owners.front();E;E=E->next()) { Range *r=E->get(); - if (!r->is_inside_scene()) + if (!r->is_inside_tree()) continue; r->_changed_notify(); } diff --git a/scene/gui/reference_frame.cpp b/scene/gui/reference_frame.cpp index 679c2cc1e2..44ba3a8972 100644 --- a/scene/gui/reference_frame.cpp +++ b/scene/gui/reference_frame.cpp @@ -32,9 +32,9 @@ void ReferenceFrame::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { - if (!is_inside_scene()) + if (!is_inside_tree()) return; - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) draw_style_box(get_stylebox("border"),Rect2(Point2(),get_size())) ; } } diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index c661a804b3..aaf96114c6 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -293,7 +293,7 @@ void ScrollBar::_notification(int p_what) { } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { if (has_node(drag_slave_path)) { @@ -303,16 +303,16 @@ void ScrollBar::_notification(int p_what) { if (drag_slave) { drag_slave->connect("input_event",this,"_drag_slave_input"); - drag_slave->connect("exit_scene",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); + drag_slave->connect("exit_tree",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); } } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { if (drag_slave) { drag_slave->disconnect("input_event",this,"_drag_slave_input"); - drag_slave->disconnect("exit_scene",this,"_drag_slave_exit"); + drag_slave->disconnect("exit_tree",this,"_drag_slave_exit"); } drag_slave=NULL; @@ -635,18 +635,18 @@ void ScrollBar::_drag_slave_input(const InputEvent& p_input) { void ScrollBar::set_drag_slave(const NodePath& p_path) { - if (is_inside_scene()) { + if (is_inside_tree()) { if (drag_slave) { drag_slave->disconnect("input_event",this,"_drag_slave_input"); - drag_slave->disconnect("exit_scene",this,"_drag_slave_exit"); + drag_slave->disconnect("exit_tree",this,"_drag_slave_exit"); } } drag_slave=NULL; drag_slave_path=p_path; - if (is_inside_scene()) { + if (is_inside_tree()) { if (has_node(p_path)) { Node *n = get_node(p_path); @@ -655,7 +655,7 @@ void ScrollBar::set_drag_slave(const NodePath& p_path) { if (drag_slave) { drag_slave->connect("input_event",this,"_drag_slave_input"); - drag_slave->connect("exit_scene",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); + drag_slave->connect("exit_tree",this,"_drag_slave_exit",varray(),CONNECT_ONESHOT); } } } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index c8f9ed16b5..95354df519 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -169,7 +169,7 @@ void ScrollContainer::_update_scrollbar_pos() { void ScrollContainer::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_SCENE || p_what == NOTIFICATION_THEME_CHANGED) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { call_deferred("_update_scrollbar_pos"); }; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 59f4386996..9ac67e92f5 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -122,7 +122,7 @@ void SpinBox::_notification(int p_what) { //_value_changed(0); - } else if (p_what==NOTIFICATION_ENTER_SCENE) { + } else if (p_what==NOTIFICATION_ENTER_TREE) { _value_changed(0); } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 2d6f3cd27a..12a8a83f26 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -602,6 +602,39 @@ void TabContainer::get_translatable_strings(List<String> *p_strings) const { } +Size2 TabContainer::get_minimum_size() const { + + Size2 ms; + + for(int i=0;i<get_child_count();i++) { + + Control *c = get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + if (!c->has_meta("_tab_name")) + continue; + + if (!c->is_visible()) + continue; + + Size2 cms = c->get_minimum_size(); + ms.x=MAX(ms.x,cms.x); + ms.y=MAX(ms.y,cms.y); + } + + Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); + Ref<Font> font = get_font("font"); + + ms.y+=MAX(tab_bg->get_minimum_size().y,tab_fg->get_minimum_size().y); + ms.y+=font->get_height(); + + return ms; +} + void TabContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&TabContainer::_input_event); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index d5b6a2b503..df7b03e040 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -85,6 +85,8 @@ public: void set_current_tab(int p_current); int get_current_tab() const; + virtual Size2 get_minimum_size() const; + virtual void get_translatable_strings(List<String> *p_strings) const; TabContainer(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 6aabfa35a8..b26b55f076 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -26,7 +26,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ - /*****f********************************************/ +/*****f********************************************/ /* text_edit.cpp */ /*************************************************/ /* This file is part of: */ @@ -40,38 +40,38 @@ #include "text_edit.h" #include "os/keyboard.h" #include "os/os.h" - + #include "globals.h" #include "message_queue.h" #define TAB_PIXELS static bool _is_text_char(CharType c) { - + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; } static bool _is_symbol(CharType c) { - + return c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t'); } static bool _is_pair_right_symbol(CharType c) { return - c == '"' || - c == '\'' || - c == ')' || - c == ']' || - c == '}'; + c == '"' || + c == '\'' || + c == ')' || + c == ']' || + c == '}'; } static bool _is_pair_left_symbol(CharType c) { return - c == '"' || - c == '\'' || - c == '(' || - c == '[' || - c == '{'; + c == '"' || + c == '\'' || + c == '(' || + c == '[' || + c == '{'; } static bool _is_pair_symbol(CharType c) { @@ -93,81 +93,81 @@ static CharType _get_right_pair_symbol(CharType c) { } void TextEdit::Text::set_font(const Ref<Font>& p_font) { - + font=p_font; } void TextEdit::Text::set_tab_size(int p_tab_size) { - + tab_size=p_tab_size; } void TextEdit::Text::_update_line_cache(int p_line) const { - + int w =0; int tab_w=font->get_char_size(' ').width; - + int len = text[p_line].data.length(); const CharType *str = text[p_line].data.c_str(); - + //update width - + for(int i=0;i<len;i++) { if (str[i]=='\t') { - + int left = w%tab_w; if (left==0) w+=tab_w; else w+=tab_w-w%tab_w; // is right... - + } else { - + w+=font->get_char_size(str[i],str[i+1]).width; } } - - + + text[p_line].width_cache=w; - + //update regions - + text[p_line].region_info.clear(); - + for(int i=0;i<len;i++) { - + if (!_is_symbol(str[i])) continue; if (str[i]=='\\') { i++; //skip quoted anything continue; } - + int left=len-i; - + for(int j=0;j<color_regions->size();j++) { - + const ColorRegion& cr=color_regions->operator [](j); - + /* BEGIN */ - + int lr=cr.begin_key.length(); if (lr==0 || lr>left) continue; - + const CharType* kc = cr.begin_key.c_str(); - + bool match=true; - + for(int k=0;k<lr;k++) { if (kc[k]!=str[i+k]) { match=false; break; } } - + if (match) { - + ColorRegionInfo cri; cri.end=false; cri.region=j; @@ -175,26 +175,26 @@ void TextEdit::Text::_update_line_cache(int p_line) const { i+=lr-1; break; } - + /* END */ - + lr=cr.end_key.length(); if (lr==0 || lr>left) continue; - + kc = cr.end_key.c_str(); - + match=true; - + for(int k=0;k<lr;k++) { if (kc[k]!=str[i+k]) { match=false; break; } } - + if (match) { - + ColorRegionInfo cri; cri.end=true; cri.region=j; @@ -202,72 +202,72 @@ void TextEdit::Text::_update_line_cache(int p_line) const { i+=lr-1; break; } - + } } - - + + } const Map<int,TextEdit::Text::ColorRegionInfo>& TextEdit::Text::get_color_region_info(int p_line) { - + Map<int,ColorRegionInfo> *cri=NULL; ERR_FAIL_INDEX_V(p_line,text.size(),*cri); //enjoy your crash - + if (text[p_line].width_cache==-1) { _update_line_cache(p_line); } - + return text[p_line].region_info; } int TextEdit::Text::get_line_width(int p_line) const { - + ERR_FAIL_INDEX_V(p_line,text.size(),-1); - + if (text[p_line].width_cache==-1) { _update_line_cache(p_line); } - + return text[p_line].width_cache; } void TextEdit::Text::clear_caches() { - + for(int i=0;i<text.size();i++) text[i].width_cache=-1; - + } void TextEdit::Text::clear() { - - + + text.clear();; insert(0,""); } int TextEdit::Text::get_max_width() const { //quite some work.. but should be fast enough. - + int max = 0; - + for(int i=0;i<text.size();i++) max=MAX(max,get_line_width(i)); return max; - + } void TextEdit::Text::set(int p_line,const String& p_text) { - + ERR_FAIL_INDEX(p_line,text.size()); - + text[p_line].width_cache=-1; text[p_line].data=p_text; } void TextEdit::Text::insert(int p_at,const String& p_text) { - + Line line; line.marked=false; line.breakpoint=false; @@ -276,114 +276,114 @@ void TextEdit::Text::insert(int p_at,const String& p_text) { text.insert(p_at,line); } void TextEdit::Text::remove(int p_at) { - + text.remove(p_at); } void TextEdit::_update_scrollbars() { - - + + Size2 size = get_size(); Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - - - + + + v_scroll->set_begin( Point2(size.width - vmin.width, cache.style_normal->get_margin(MARGIN_TOP)) ); v_scroll->set_end( Point2(size.width, size.height - cache.style_normal->get_margin(MARGIN_TOP) - cache.style_normal->get_margin(MARGIN_BOTTOM)) ); - + h_scroll->set_begin( Point2( 0, size.height - hmin.height) ); h_scroll->set_end( Point2(size.width-vmin.width, size.height) ); - - + + int hscroll_rows = ((hmin.height-1)/get_row_height())+1; int visible_rows = get_visible_rows(); - int total_rows = text.size() * cache.line_spacing; - + int total_rows = text.size(); + int vscroll_pixels = v_scroll->get_combined_minimum_size().width; int visible_width = size.width - cache.style_normal->get_minimum_size().width; int total_width = text.get_max_width(); - + bool use_hscroll=true; bool use_vscroll=true; - + if (total_rows <= visible_rows && total_width <= visible_width) { //thanks yessopie for this clever bit of logic use_hscroll=false; use_vscroll=false; - + } else { - + if (total_rows > visible_rows && total_width <= visible_width - vscroll_pixels) { //thanks yessopie for this clever bit of logic use_hscroll=false; } - + if (total_rows <= visible_rows - hscroll_rows && total_width > visible_width) { //thanks yessopie for this clever bit of logic use_vscroll=false; } } - + updating_scrolls=true; - + if (use_vscroll) { - + v_scroll->show(); v_scroll->set_max(total_rows); v_scroll->set_page(visible_rows); - + v_scroll->set_val(cursor.line_ofs); - + } else { cursor.line_ofs = 0; v_scroll->hide(); } - + if (use_hscroll) { - + h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); h_scroll->set_val(cursor.x_ofs); } else { - + h_scroll->hide(); } - - - + + + updating_scrolls=false; } void TextEdit::_notification(int p_what) { - + switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { - + case NOTIFICATION_ENTER_TREE: { + _update_caches(); if (cursor_changed_dirty) MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); if (text_changed_dirty) MessageQueue::get_singleton()->push_call(this,"_text_changed_emit"); - + } break; case NOTIFICATION_RESIZED: { - + cache.size=get_size(); adjust_viewport_to_cursor(); - - + + } break; case NOTIFICATION_THEME_CHANGED: { - + _update_caches(); }; case NOTIFICATION_DRAW: { - + int line_number_char_count=0; - + { int lc=text.size()+1; cache.line_number_w=0; @@ -391,20 +391,20 @@ void TextEdit::_notification(int p_what) { cache.line_number_w+=1; lc/=10; }; - + if (line_numbers) { - + line_number_char_count=cache.line_number_w; cache.line_number_w=(cache.line_number_w+1)*cache.font->get_char_size('0').width; } else { cache.line_number_w=0; } - - + + } _update_scrollbars(); - - + + RID ci = get_canvas_item(); int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w; int xmargin_end=cache.size.width-cache.style_normal->get_margin(MARGIN_RIGHT); @@ -412,77 +412,233 @@ void TextEdit::_notification(int p_what) { cache.style_normal->draw(ci,Rect2(Point2(),cache.size)); if (has_focus()) cache.style_focus->draw(ci,Rect2(Point2(),cache.size)); - - + + int ascent=cache.font->get_ascent(); - + int visible_rows = get_visible_rows(); - + int tab_w = cache.font->get_char_size(' ').width*tab_size; - + Color color = cache.font_color; int in_region=-1; - + if (syntax_coloring) { - + if (custom_bg_color.a>0.01) { - + Point2i ofs = Point2i(cache.style_normal->get_offset())/2.0; VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),custom_bg_color); } //compute actual region to start (may be inside say, a comment). //slow in very large documments :( but ok for source! - + for(int i=0;i<cursor.line_ofs;i++) { - + const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(i); - + if (in_region>=0 && color_regions[in_region].line_only) { in_region=-1; //reset regions that end at end of line } - + for( const Map<int,Text::ColorRegionInfo>::Element* E= cri_map.front();E;E=E->next() ) { - + const Text::ColorRegionInfo &cri=E->get(); - + if (in_region==-1) { - + if (!cri.end) { - + in_region=cri.region; } } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise - + if (cri.end || color_regions[cri.region].eq) { - + in_region=-1; } } } } } - + + int brace_open_match_line=-1; + int brace_open_match_column=-1; + bool brace_open_matching=false; + bool brace_open_mismatch=false; + int brace_close_match_line=-1; + int brace_close_match_column=-1; + bool brace_close_matching=false; + bool brace_close_mismatch=false; + + + if (brace_matching_enabled) { + + if (cursor.column<text[cursor.line].length()) { + //check for open + CharType c = text[cursor.line][cursor.column]; + CharType closec=0; + + if (c=='[') { + closec=']'; + } else if (c=='{') { + closec='}'; + } else if (c=='(') { + closec=')'; + } + + if (closec!=0) { + + int stack=1; + + + for(int i=cursor.line;i<text.size();i++) { + + int from = i==cursor.line?cursor.column+1:0; + for(int j=from;j<text[i].length();j++) { + + CharType cc = text[i][j]; + //ignore any brackets inside a string + if (cc== '"' | cc == '\'') { + CharType quotation = cc; + do { + j++; + if (!(j<text[i].length())) { + break; + } + cc=text[i][j]; + //skip over escaped quotation marks inside strings + if (cc=='\\') { + bool escaped = true; + while (j+1<text[i].length() && text[i][j+1]=='\\') { + escaped=!escaped; + j++; + } + if (escaped) { + j++; + continue; + } + } + } while (cc!= quotation); + } else if (cc==c) + stack++; + else if (cc==closec) + stack--; + + if (stack==0) { + brace_open_match_line=i; + brace_open_match_column=j; + brace_open_matching=true; + + break; + } + } + if (brace_open_match_line!=-1) + break; + } + + if (!brace_open_matching) + brace_open_mismatch=true; + + + } + } + + if (cursor.column>0) { + CharType c = text[cursor.line][cursor.column-1]; + CharType closec=0; + + + + if (c==']') { + closec='['; + } else if (c=='}') { + closec='{'; + } else if (c==')') { + closec='('; + } + + if (closec!=0) { + + int stack=1; + + + for(int i=cursor.line;i>=0;i--) { + + int from = i==cursor.line?cursor.column-2:text[i].length()-1; + for(int j=from;j>=0;j--) { + + CharType cc = text[i][j]; + //ignore any brackets inside a string + if (cc== '"' | cc == '\'') { + CharType quotation = cc; + do { + j--; + if (!(j>=0)) { + break; + } + cc=text[i][j]; + //skip over escaped quotation marks inside strings + if (cc==quotation) { + bool escaped = false; + while (j-1>=0 && text[i][j-1]=='\\') { + escaped=!escaped; + j--; + } + if (escaped) { + j--; + cc='\\'; + continue; + } + } + } while (cc!= quotation); + } else if (cc==c) + stack++; + else if (cc==closec) + stack--; + + if (stack==0) { + brace_close_match_line=i; + brace_close_match_column=j; + brace_close_matching=true; + + break; + } + } + if (brace_close_match_line!=-1) + break; + } + + if (!brace_close_matching) + brace_close_mismatch=true; + + + } + + + } + } + + int deregion=0; //force it to clear inrgion Point2 cursor_pos; - + for (int i=0;i<visible_rows;i++) { - + int line=i+cursor.line_ofs; - + if (line<0 || line>=(int)text.size()) continue; - - - + const String &str=text[line]; - + int char_margin=xmargin_beg-cursor.x_ofs; int char_ofs=0; int ofs_y=i*get_row_height()+cache.line_spacing/2; bool prev_is_char=false; bool in_keyword=false; Color keyword_color; - + if (cache.line_number_w) { Color fcol = cache.font_color; fcol.a*=0.4; @@ -490,167 +646,191 @@ void TextEdit::_notification(int p_what) { while (fc.length() < line_number_char_count) { fc="0"+fc; } - + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,fcol); } - + const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); - - + + if (text.is_marked(line)) { - + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.mark_color); } - + if (text.is_breakpoint(line)) { - + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); } - - + + if (line==cursor.line) { - + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); - + } for (int j=0;j<str.length();j++) { - + //look for keyword - + if (deregion>0) { deregion--; if (deregion==0) in_region=-1; } if (syntax_coloring && deregion==0) { - - + + color = cache.font_color; //reset //find keyword bool is_char = _is_text_char(str[j]); bool is_symbol=_is_symbol(str[j]); - + if (j==0 && in_region>=0 && color_regions[in_region].line_only) { in_region=-1; //reset regions that end at end of line } - + if (is_symbol && cri_map.has(j)) { - - + + const Text::ColorRegionInfo &cri=cri_map[j]; - + if (in_region==-1) { - + if (!cri.end) { - + in_region=cri.region; } } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise - + if (cri.end || color_regions[cri.region].eq) { - + deregion=color_regions[cri.region].eq?color_regions[cri.region].begin_key.length():color_regions[cri.region].end_key.length(); } } } - + if (!is_char) in_keyword=false; - + if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { - + int to=j; while(_is_text_char(str[to]) && to<str.length()) to++; - + uint32_t hash = String::hash(&str[j],to-j); StrRange range(&str[j],to-j); - + const Color *col=keywords.custom_getptr(range,hash); - + if (col) { - + in_keyword=true; keyword_color=*col; } } - - + + if (in_region>=0) color=color_regions[in_region].color; else if (in_keyword) color=keyword_color; else if (is_symbol) color=symbol_color; - + prev_is_char=is_char; - + } int char_w; - + //handle tabulator - - + + if (str[j]=='\t') { int left = char_ofs%tab_w; if (left==0) char_w=tab_w; else char_w=tab_w-char_ofs%tab_w; // is right... - + } else { char_w=cache.font->get_char_size(str[j],str[j+1]).width; } - + if ( (char_ofs+char_margin)<xmargin_beg) { char_ofs+=char_w; continue; } - + if ( (char_ofs+char_margin+char_w)>=xmargin_end) { if (syntax_coloring) continue; else break; } - + bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column)); - - + + if (in_selection) { //inside selection! VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color); } - - - + + + if (brace_matching_enabled) { + if ( (brace_open_match_line==line && brace_open_match_column==j) || + (cursor.column==j && cursor.line==line && (brace_open_matching||brace_open_mismatch))) { + + if (brace_open_mismatch) + color=cache.brace_mismatch_color; + cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),'_',str[j+1],in_selection?cache.font_selected_color:color); + + } + + if ( + (brace_close_match_line==line && brace_close_match_column==j) || + (cursor.column==j+1 && cursor.line==line && (brace_close_matching||brace_close_mismatch))) { + + + if (brace_close_mismatch) + color=cache.brace_mismatch_color; + cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),'_',str[j+1],in_selection?cache.font_selected_color:color); + + } + } + + if (str[j]>=32) cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + else if (draw_tabs && str[j]=='\t') { int yofs= (get_row_height() - cache.tab_icon->get_height())/2; cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); } - - + + if (cursor.column==j && cursor.line==line) { - + cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); - - + + } char_ofs+=char_w; - + } - + if (cursor.column==str.length() && cursor.line==line) { - + cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); - + } } - + + if (completion_active) { // code completion box Ref<StyleBox> csb = get_stylebox("completion"); @@ -658,17 +838,18 @@ void TextEdit::_notification(int p_what) { int maxlines = get_constant("completion_lines"); int cmax_width = get_constant("completion_max_width")*cache.font->get_char_size('x').x; Color existing = get_color("completion_existing"); + existing.a=0.2; int scrollw = get_constant("completion_scroll_width"); Color scrollc = get_color("completion_scroll_color"); - - - + + + int lines = MIN(completion_options.size(),maxlines); int w=0; int h=lines*get_row_height(); int nofs = cache.font->get_string_size(completion_base).width; - - + + if (completion_options.size() < 50) { for(int i=0;i<completion_options.size();i++) { int w2=MIN(cache.font->get_string_size(completion_options[i]).x,cmax_width); @@ -678,67 +859,135 @@ void TextEdit::_notification(int p_what) { } else { w=cmax_width; } - + int th = h + csb->get_minimum_size().y; if (cursor_pos.y+get_row_height()+th > get_size().height) { completion_rect.pos.y=cursor_pos.y-th; } else { completion_rect.pos.y=cursor_pos.y+get_row_height()+csb->get_offset().y; + } - + if (cursor_pos.x-nofs+w+scrollw > get_size().width) { completion_rect.pos.x=get_size().width-w-scrollw; } else { completion_rect.pos.x=cursor_pos.x-nofs; } - - completion_rect.size.width=w; + + completion_rect.size.width=w+2; completion_rect.size.height=h; if (completion_options.size()<=maxlines) scrollw=0; - + draw_style_box(csb,Rect2(completion_rect.pos-csb->get_offset(),completion_rect.size+csb->get_minimum_size()+Size2(scrollw,0))); - - + + int line_from = CLAMP(completion_index - lines/2, 0, completion_options.size() - lines); draw_style_box(csel,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height()))); - + draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); - + + + + for(int i=0;i<lines;i++) { - + int l = line_from + i; ERR_CONTINUE( l < 0 || l>= completion_options.size()); - draw_string(cache.font,Point2(completion_rect.pos.x,completion_rect.pos.y+i*get_row_height()+cache.font->get_ascent()),completion_options[l],cache.font_color,completion_rect.size.width); + Color text_color = cache.font_color; + for(int j=0;j<color_regions.size();j++) { + if (completion_options[l].begins_with(color_regions[j].begin_key)) { + text_color=color_regions[j].color; + } + } + draw_string(cache.font,Point2(completion_rect.pos.x,completion_rect.pos.y+i*get_row_height()+cache.font->get_ascent()),completion_options[l],text_color,completion_rect.size.width); } - + if (scrollw) { //draw a small scroll rectangle to show a position in the options float r = maxlines / (float)completion_options.size(); float o = line_from / (float)completion_options.size(); draw_rect(Rect2(completion_rect.pos.x+completion_rect.size.width,completion_rect.pos.y+o*completion_rect.size.y,scrollw,completion_rect.size.y*r),scrollc); } - + completion_line_ofs=line_from; - + } - - - + + if (completion_hint!="") { + + Ref<StyleBox> sb = get_stylebox("panel","TooltipPanel"); + Ref<Font> font = cache.font; + Color font_color = get_color("font_color","TooltipLabel"); + + + int max_w=0; + int sc = completion_hint.get_slice_count("\n"); + int offset=0; + int spacing=0; + for(int i=0;i<sc;i++) { + + String l = completion_hint.get_slice("\n",i); + int len = font->get_string_size(l).x; + max_w = MAX(len,max_w); + if (i==0) { + offset = font->get_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x; + } else { + spacing+=cache.line_spacing; + } + + + } + + + + Size2 size = Size2(max_w,sc*font->get_height()+spacing); + Size2 minsize = size+sb->get_minimum_size(); + + + if (completion_hint_offset==-0xFFFF) { + completion_hint_offset=cursor_pos.x-offset; + } + + + Point2 hint_ofs = Vector2(completion_hint_offset,cursor_pos.y-minsize.y); + draw_style_box(sb,Rect2(hint_ofs,minsize)); + + spacing=0; + for(int i=0;i<sc;i++) { + int begin=0; + int end=0; + String l = completion_hint.get_slice("\n",i); + + if (l.find(String::chr(0xFFFF))!=-1) { + begin = font->get_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x; + end = font->get_string_size(l.substr(0,l.rfind(String::chr(0xFFFF)))).x; + } + + draw_string(font,hint_ofs+sb->get_offset()+Vector2(0,font->get_ascent()+font->get_height()*i+spacing),l.replace(String::chr(0xFFFF),""),font_color); + if (end>0) { + Vector2 b = hint_ofs+sb->get_offset()+Vector2(begin,font->get_height()+font->get_height()*i+spacing-1); + draw_line(b,b+Vector2(end-begin,0),font_color); + } + spacing+=cache.line_spacing; + } + } + + } break; case NOTIFICATION_FOCUS_ENTER: { - + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); - + } break; case NOTIFICATION_FOCUS_EXIT: { - + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - + } break; - + } } @@ -750,23 +999,23 @@ void TextEdit::_consume_pair_symbol(CharType ch) { CharType ch_single_pair[2] = {_get_right_pair_symbol(ch), 0}; CharType ch_pair[3] = {ch, _get_right_pair_symbol(ch), 0}; - if(is_selection_active()) { + if(is_selection_active()) { int new_column,new_line; _begin_compex_operation(); _insert_text(get_selection_from_line(), get_selection_from_column(), - ch_single, - &new_line, &new_column); + ch_single, + &new_line, &new_column); int to_col_offset = 0; - if(get_selection_from_line() == get_selection_to_line()) + if(get_selection_from_line() == get_selection_to_line()) to_col_offset = 1; - _insert_text(get_selection_to_line(), - get_selection_to_column() + to_col_offset, - ch_single_pair, - &new_line,&new_column); + _insert_text(get_selection_to_line(), + get_selection_to_column() + to_col_offset, + ch_single_pair, + &new_line,&new_column); _end_compex_operation(); cursor_set_line(get_selection_to_line()); @@ -778,9 +1027,9 @@ void TextEdit::_consume_pair_symbol(CharType ch) { } if( (ch == '\'' || ch == '"') && - cursor_get_column() > 0 && - _is_text_char(text[cursor.line][cursor_get_column() - 1]) - ) { + cursor_get_column() > 0 && + _is_text_char(text[cursor.line][cursor_get_column() - 1]) + ) { insert_text_at_cursor(ch_single); cursor_set_column(cursor_position_to_move); return; @@ -792,9 +1041,9 @@ void TextEdit::_consume_pair_symbol(CharType ch) { cursor_set_column(cursor_position_to_move); return; } - if( _is_pair_right_symbol(ch) && - text[cursor.line][cursor_get_column()] == ch - ) { + if( _is_pair_right_symbol(ch) && + text[cursor.line][cursor_get_column()] == ch + ) { cursor_set_column(cursor_position_to_move); return; } @@ -830,88 +1079,90 @@ void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column } void TextEdit::backspace_at_cursor() { + if (readonly) + return; if (cursor.column==0 && cursor.line==0) return; - + int prev_line = cursor.column?cursor.line:cursor.line-1; int prev_column = cursor.column?(cursor.column-1):(text[cursor.line-1].length()); - if(auto_brace_completion_enabled && - cursor.column > 0 && - _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) { + if(auto_brace_completion_enabled && + cursor.column > 0 && + _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) { _consume_backspace_for_pair_symbol(prev_line, prev_column); } else { _remove_text(prev_line,prev_column,cursor.line,cursor.column); } - + cursor_set_line(prev_line); cursor_set_column(prev_column); - + } bool TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const { - + int row=p_mouse.y; row-=cache.style_normal->get_margin(MARGIN_TOP); row/=get_row_height(); - + if (row<0 || row>=get_visible_rows()) return false; - + row+=cursor.line_ofs; int col=0; - + if (row>=text.size()) { - + row=text.size()-1; col=text[row].size(); } else { - + col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w); col+=cursor.x_ofs; col=get_char_pos_for( col, get_line(row) ); } - + r_row=row; r_col=col; return true; } void TextEdit::_input_event(const InputEvent& p_input_event) { - + switch(p_input_event.type) { - + case InputEvent::MOUSE_BUTTON: { - + const InputEventMouseButton &mb=p_input_event.mouse_button; - + if (completion_active && completion_rect.has_point(Point2(mb.x,mb.y))) { - + if (!mb.pressed) return; - + if (mb.button_index==BUTTON_WHEEL_UP) { if (completion_index>0) { completion_index--; completion_current=completion_options[completion_index]; update(); } - + } if (mb.button_index==BUTTON_WHEEL_DOWN) { - + if (completion_index<completion_options.size()-1) { completion_index++; completion_current=completion_options[completion_index]; update(); } } - + if (mb.button_index==BUTTON_LEFT) { - + completion_index=CLAMP(completion_line_ofs+(mb.y-completion_rect.pos.y)/get_row_height(),0,completion_options.size()-1); - + completion_current=completion_options[completion_index]; update(); if (mb.doubleclick) @@ -920,8 +1171,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; } else { _cancel_completion(); + _cancel_code_hint(); } - + if (mb.pressed) { if (mb.button_index==BUTTON_WHEEL_UP) { v_scroll->set_val( v_scroll->get_val() -3 ); @@ -930,228 +1182,268 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { v_scroll->set_val( v_scroll->get_val() +3 ); } if (mb.button_index==BUTTON_LEFT) { - + int row,col; if (!_get_mouse_pos(Point2i(mb.x,mb.y), row,col)) return; - + int prev_col=cursor.column; int prev_line=cursor.line; + + + + cursor_set_line( row ); + cursor_set_column( col ); + + if (mb.mod.shift && (cursor.column!=prev_col || cursor.line!=prev_line)) { + if (!selection.active) { + selection.active=true; + selection.selecting_mode=Selection::MODE_POINTER; + selection.from_column=prev_col; + selection.from_line=prev_line; + selection.to_column=cursor.column; + selection.to_line=cursor.line; + if (selection.from_line>selection.to_line || (selection.from_line==selection.to_line && selection.from_column>selection.to_column)) { + SWAP(selection.from_column,selection.to_column); + SWAP(selection.from_line,selection.to_line); + selection.shiftclick_left=false; + } else { + selection.shiftclick_left=true; + } + selection.selecting_line=prev_line; + selection.selecting_column=prev_col; + update(); + } else { - cursor_set_line( row ); - cursor_set_column( col ); + if (cursor.line<selection.from_line || (cursor.line==selection.from_line && cursor.column<=selection.from_column)) { + selection.from_column=cursor.column; + selection.from_line=cursor.line; + } else if (cursor.line>selection.to_line || (cursor.line==selection.to_line && cursor.column>=selection.to_column)) { + selection.to_column=cursor.column; + selection.to_line=cursor.line; - if (mb.mod.shift && (cursor.column!=prev_col || cursor.line!=prev_line)) { + } else if (!selection.shiftclick_left) { - selection.active=true; - selection.selecting_mode=Selection::MODE_POINTER; - selection.from_column=prev_col; - selection.from_line=prev_line; - selection.to_column=cursor.column; - selection.to_line=cursor.line; - if (selection.from_column>selection.to_column) { - SWAP(selection.from_column,selection.to_column); - SWAP(selection.from_line,selection.to_line); + selection.from_column=cursor.column; + selection.from_line=cursor.line; + } else { + + selection.to_column=cursor.column; + selection.to_line=cursor.line; + } + + if (selection.from_line>selection.to_line || (selection.from_line==selection.to_line && selection.from_column>selection.to_column)) { + SWAP(selection.from_column,selection.to_column); + SWAP(selection.from_line,selection.to_line); + } + update(); } - selection.selecting_line=prev_line; - selection.selecting_column=prev_col; - update(); - } else { - //if sel active and dblick last time < something - //else + + + + + } else { + + //if sel active and dblick last time < something + + //else selection.active=false; selection.selecting_mode=Selection::MODE_POINTER; selection.selecting_line=row; selection.selecting_column=col; } - - + + if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600) { //tripleclick select line select(cursor.line,0,cursor.line,text[cursor.line].length()); last_dblclk=0; - + } else if (mb.doubleclick && text[cursor.line].length()) { - + //doubleclick select world String s = text[cursor.line]; int beg=CLAMP(cursor.column,0,s.length()); int end=beg; - + if (s[beg]>32 || beg==s.length()) { - + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this - + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { beg--; } while(end<s.length() && s[end+1]>32 && (symbol==_is_symbol(s[end+1]))) { end++; } - + if (end<s.length()) end+=1; - + select(cursor.line,beg,cursor.line,end); } - + last_dblclk = OS::get_singleton()->get_ticks_msec(); - + } - + update(); } } else { - + selection.selecting_mode=Selection::MODE_NONE; - // notify to show soft keyboard - notification(NOTIFICATION_FOCUS_ENTER); + // notify to show soft keyboard + notification(NOTIFICATION_FOCUS_ENTER); } - + } break; - case InputEvent::MOUSE_MOTION: { - - const InputEventMouseMotion &mm=p_input_event.mouse_motion; - - if (mm.button_mask&BUTTON_MASK_LEFT) { - + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_input_event.mouse_motion; + + if (mm.button_mask&BUTTON_MASK_LEFT) { + int row,col; if (!_get_mouse_pos(Point2i(mm.x,mm.y), row,col)) return; - - if (selection.selecting_mode==Selection::MODE_POINTER) { - + + if (selection.selecting_mode==Selection::MODE_POINTER) { + select(selection.selecting_line,selection.selecting_column,row,col); - + cursor_set_line( row ); cursor_set_column( col ); update(); - - } - - } - - } break; - + + } + + } + + } break; + case InputEvent::KEY: { - + InputEventKey k=p_input_event.key; - + if (!k.pressed) return; - + if (completion_active) { + if (readonly) + break; bool valid=true; - if (k.mod.command || k.mod.alt || k.mod.meta) + if (k.mod.command || k.mod.meta) valid=false; - + if (valid) { + + if (!k.mod.alt) { + if (k.scancode==KEY_UP) { + + if (completion_index>0) { + completion_index--; + completion_current=completion_options[completion_index]; + update(); + } + accept_event(); + return; + } + - if (k.scancode==KEY_UP) { + if (k.scancode==KEY_DOWN) { - if (completion_index>0) { - completion_index--; + if (completion_index<completion_options.size()-1) { + completion_index++; + completion_current=completion_options[completion_index]; + update(); + } + accept_event(); + return; + } + + if (k.scancode==KEY_PAGEUP) { + + completion_index-=get_constant("completion_lines"); + if (completion_index<0) + completion_index=0; completion_current=completion_options[completion_index]; update(); + accept_event(); + return; } - accept_event(); - return; - } - if (k.scancode==KEY_DOWN) { + if (k.scancode==KEY_PAGEDOWN) { - if (completion_index<completion_options.size()-1) { - completion_index++; + completion_index+=get_constant("completion_lines"); + if (completion_index>=completion_options.size()) + completion_index=completion_options.size()-1; completion_current=completion_options[completion_index]; update(); + accept_event(); + return; } - accept_event(); - return; - } - if (k.scancode==KEY_PAGEUP) { + if (k.scancode==KEY_HOME && completion_index>0) { - completion_index-=get_constant("completion_lines"); - if (completion_index<0) completion_index=0; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } - + completion_current=completion_options[completion_index]; + update(); + accept_event(); + return; + } - if (k.scancode==KEY_PAGEDOWN) { + if (k.scancode==KEY_END && completion_index<completion_options.size()-1) { - completion_index+=get_constant("completion_lines"); - if (completion_index>=completion_options.size()) completion_index=completion_options.size()-1; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } - - if (k.scancode==KEY_HOME) { - - completion_index=0; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } - - if (k.scancode==KEY_END) { - - completion_index=completion_options.size()-1; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } + completion_current=completion_options[completion_index]; + update(); + accept_event(); + return; + } - if (k.scancode==KEY_DOWN) { + if (k.scancode==KEY_DOWN) { - if (completion_index<completion_options.size()-1) { - completion_index++; - completion_current=completion_options[completion_index]; - update(); + if (completion_index<completion_options.size()-1) { + completion_index++; + completion_current=completion_options[completion_index]; + update(); + } + accept_event(); + return; } - accept_event(); - return; - } - if (k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { + if (k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { - _confirm_completion(); - accept_event(); - return; - } + _confirm_completion(); + accept_event(); + return; + } - if (k.scancode==KEY_BACKSPACE) { + if (k.scancode==KEY_BACKSPACE) { - backspace_at_cursor(); - _update_completion_candidates(); - accept_event(); - return; - } + backspace_at_cursor(); + _update_completion_candidates(); + accept_event(); + return; + } - if (k.scancode==KEY_SHIFT) { - accept_event(); - return; + if (k.scancode==KEY_SHIFT) { + accept_event(); + return; + } } - + if (k.unicode>32) { - + if (cursor.column<text[cursor.line].length() && text[cursor.line][cursor.column]==k.unicode) { //same char, move ahead cursor_set_column(cursor.column+1); @@ -1165,48 +1457,52 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { _insert_text_at_cursor(chr); } } - + _update_completion_candidates(); accept_event(); - + return; } } - + _cancel_completion(); + } - + /* TEST CONTROL FIRST!! */ - + // some remaps for duplicate functions.. if (k.mod.command && !k.mod.shift && !k.mod.alt && !k.mod.meta && k.scancode==KEY_INSERT) { - + k.scancode=KEY_C; } if (!k.mod.command && k.mod.shift && !k.mod.alt && !k.mod.meta && k.scancode==KEY_INSERT) { - + k.scancode=KEY_V; k.mod.command=true; - k.mod.shift=false; + k.mod.shift=false; } - + // stuff to do when selection is active.. - + if (selection.active) { + if (readonly) + break; + bool clear=false; bool unselect=false; bool dobreak=false; - + switch(k.scancode) { - + case KEY_TAB: { - + String txt = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); String prev_txt=txt; - + if (k.mod.shift) { - + for(int i=0;i<txt.length();i++) { if (((i>0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/)) && (txt[i]=='\t' || txt[i]==' ')) { txt.remove(i); @@ -1214,21 +1510,21 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } } } else { - + for(int i=0;i<txt.length();i++) { - + if (((i>0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/))) { txt=txt.insert(i,"\t"); //i--; } } } - + if (txt!=prev_txt) { - + int sel_line=selection.from_line; int sel_column=selection.from_column; - + cursor_set_line(selection.from_line); cursor_set_column(selection.from_column); _begin_compex_operation(); @@ -1242,10 +1538,10 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { selection.to_line=cursor.line; update(); } - + dobreak=true; accept_event(); - + } break; case KEY_X: case KEY_C: @@ -1256,7 +1552,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { case KEY_BACKSPACE: accept_event(); clear=true; dobreak=true; - break; + break; case KEY_LEFT: case KEY_RIGHT: case KEY_UP: @@ -1265,24 +1561,26 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { case KEY_PAGEDOWN: case KEY_HOME: case KEY_END: - if (k.mod.shift) // if selecting ignore + // ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys) + if (k.mod.command || k.mod.shift || k.mod.alt || k.mod.command) break; unselect=true; break; + default: if (k.unicode>=32 && !k.mod.command && !k.mod.alt && !k.mod.meta) clear=true; if (auto_brace_completion_enabled && _is_pair_left_symbol(k.unicode)) clear=false; } - + if (unselect) { selection.active=false; selection.selecting_mode=Selection::MODE_NONE; update(); } if (clear) { - + selection.active=false; update(); _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); @@ -1293,20 +1591,23 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (dobreak) break; } - + selection.selecting_test=false; - + bool scancode_handled=true; - + // special scancode test... switch (k.scancode) { - + case KEY_ENTER: case KEY_RETURN: { - String ins="\n"; + if (readonly) + break; + String ins="\n"; + //keep indentation for(int i=0;i<text[cursor.line].length();i++) { if (text[cursor.line][i]=='\t') @@ -1314,26 +1615,33 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { else break; } - + _insert_text_at_cursor(ins); _push_current_op(); - + + } break; + case KEY_ESCAPE: { + if (completion_hint!="") { + completion_hint=""; + update(); + + } } break; case KEY_TAB: { - + if (readonly) break; - + if (selection.active) { - - + + } else { if (k.mod.shift) { - + int cc = cursor.column; if (cc>0 && cc<=text[cursor.line].length() && text[cursor.line][cursor.column-1]=='\t') { //simple unindent - + backspace_at_cursor(); } } else { @@ -1341,173 +1649,187 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { _insert_text_at_cursor("\t"); } } - + } break; case KEY_BACKSPACE: { if (readonly) break; backspace_at_cursor(); - + } break; case KEY_LEFT: { - + if (k.mod.shift) _pre_shift_selection(); - + #ifdef APPLE_STYLE_KEYS if (k.mod.command) { cursor_set_column(0); } else if (k.mod.alt) { - + #else - if (k.mod.command) { + if (k.mod.alt) { + scancode_handled=false; + break; + } else if (k.mod.command) { #endif bool prev_char=false; int cc=cursor.column; while (cc>0) { - + bool ischar=_is_text_char(text[cursor.line][cc-1]); - + if (prev_char && !ischar) break; - + prev_char=ischar; cc--; - + } - + cursor_set_column(cc); - - } else if (cursor.column==0) { - + + } else if (cursor.column==0) { + if (cursor.line>0) { cursor_set_line(cursor.line-1); cursor_set_column(text[cursor.line].length()); } - } else { + } else { cursor_set_column(cursor_get_column()-1); } - + if (k.mod.shift) _post_shift_selection(); - + } break; case KEY_RIGHT: { - + if (k.mod.shift) _pre_shift_selection(); - + #ifdef APPLE_STYLE_KEYS if (k.mod.command) { cursor_set_column(text[cursor.line].length()); } else if (k.mod.alt) { #else - if (k.mod.command) { + if (k.mod.alt) { + scancode_handled=false; + break; + } else if (k.mod.command) { #endif bool prev_char=false; int cc=cursor.column; while (cc<text[cursor.line].length()) { - + bool ischar=_is_text_char(text[cursor.line][cc]); - + if (prev_char && !ischar) break; prev_char=ischar; cc++; } - + cursor_set_column(cc); - - } else if (cursor.column==text[cursor.line].length()) { - + + } else if (cursor.column==text[cursor.line].length()) { + if (cursor.line<text.size()-1) { cursor_set_line(cursor.line+1); cursor_set_column(0); } - } else { + } else { cursor_set_column(cursor_get_column()+1); } - + if (k.mod.shift) _post_shift_selection(); - + } break; case KEY_UP: { - + if (k.mod.shift) _pre_shift_selection(); - + if (k.mod.alt) { + scancode_handled=false; + break; + } #ifdef APPLE_STYLE_KEYS if (k.mod.command) cursor_set_line(0); else #endif cursor_set_line(cursor_get_line()-1); - + if (k.mod.shift) _post_shift_selection(); - + _cancel_code_hint(); + } break; case KEY_DOWN: { - + if (k.mod.shift) _pre_shift_selection(); - + if (k.mod.alt) { + scancode_handled=false; + break; + } #ifdef APPLE_STYLE_KEYS if (k.mod.command) cursor_set_line(text.size()-1); else #endif cursor_set_line(cursor_get_line()+1); - + if (k.mod.shift) _post_shift_selection(); - + _cancel_code_hint(); + } break; - + case KEY_DELETE: { - + if (readonly) break; int curline_len = text[cursor.line].length(); - + if (cursor.line==text.size()-1 && cursor.column==curline_len) break; //nothing to do - + int next_line = cursor.column<curline_len?cursor.line:cursor.line+1; int next_column = cursor.column<curline_len?(cursor.column+1):0; _remove_text(cursor.line,cursor.column,next_line,next_column); update(); } break; #ifdef APPLE_STYLE_KEYS - case KEY_HOME: { - - - if (k.mod.shift) - _pre_shift_selection(); - - cursor_set_line(0); - - if (k.mod.shift) - _post_shift_selection(); - - } break; - case KEY_END: { - - if (k.mod.shift) - _pre_shift_selection(); - - cursor_set_line(text.size()-1); - - if (k.mod.shift) - _post_shift_selection(); - - } break; - + case KEY_HOME: { + + + if (k.mod.shift) + _pre_shift_selection(); + + cursor_set_line(0); + + if (k.mod.shift) + _post_shift_selection(); + + } break; + case KEY_END: { + + if (k.mod.shift) + _pre_shift_selection(); + + cursor_set_line(text.size()-1); + + if (k.mod.shift) + _post_shift_selection(); + + } break; + #else case KEY_HOME: { - - + + if (k.mod.shift) _pre_shift_selection(); @@ -1527,54 +1849,54 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.command) cursor_set_line(0); - + if (k.mod.shift) _post_shift_selection(); - + } break; case KEY_END: { - + if (k.mod.shift) _pre_shift_selection(); - + if (k.mod.command) cursor_set_line(text.size()-1); cursor_set_column(text[cursor.line].length()); - + if (k.mod.shift) _post_shift_selection(); - + } break; #endif case KEY_PAGEUP: { - + if (k.mod.shift) _pre_shift_selection(); - + cursor_set_line(cursor_get_line()-get_visible_rows()); - + if (k.mod.shift) _post_shift_selection(); - + } break; case KEY_PAGEDOWN: { - + if (k.mod.shift) _pre_shift_selection(); - + cursor_set_line(cursor_get_line()+get_visible_rows()); - + if (k.mod.shift) _post_shift_selection(); - + } break; case KEY_A: { - + if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; } - + if (text.size()==1 && text[0].length()==0) break; selection.active=true; @@ -1584,186 +1906,169 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { selection.to_column=text[selection.to_line].size(); selection.selecting_mode=Selection::MODE_NONE; update(); - + } break; case KEY_X: { - + if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; } - - if (!selection.active){ - - String clipboard = text[cursor.line]; - OS::get_singleton()->set_clipboard(clipboard); - cursor_set_line(cursor.line); - cursor_set_column(0); - _remove_text(cursor.line,0,cursor.line,text[cursor.line].length()); - - backspace_at_cursor(); - update(); - cursor_set_line(cursor.line+1); - cut_copy_line = true; - - } - else - { - - String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - selection.active=false; - selection.selecting_mode=Selection::MODE_NONE; - update(); - cut_copy_line = false; - } - + + if (!selection.active){ + + String clipboard = text[cursor.line]; + OS::get_singleton()->set_clipboard(clipboard); + cursor_set_line(cursor.line); + cursor_set_column(0); + _remove_text(cursor.line,0,cursor.line,text[cursor.line].length()); + + backspace_at_cursor(); + update(); + cursor_set_line(cursor.line+1); + cut_copy_line = true; + + } + else + { + + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + OS::get_singleton()->set_clipboard(clipboard); + + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + selection.active=false; + selection.selecting_mode=Selection::MODE_NONE; + update(); + cut_copy_line = false; + } + } break; case KEY_C: { - + if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; + scancode_handled=false; + break; + } + + if (!selection.active){ + String clipboard = _base_get_text(cursor.line,0,cursor.line,text[cursor.line].length()); + OS::get_singleton()->set_clipboard(clipboard); + cut_copy_line = true; + } + else{ + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + OS::get_singleton()->set_clipboard(clipboard); + cut_copy_line = false; } - - if (!selection.active){ - String clipboard = _base_get_text(cursor.line,0,cursor.line,text[cursor.line].length()); - OS::get_singleton()->set_clipboard(clipboard); - cut_copy_line = true; - } - else{ - String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); - cut_copy_line = false; - } } break; case KEY_Z: { - - if (!k.mod.command) { - scancode_handled=false; - break; - } - - if (k.mod.shift) - redo(); - else - undo(); + + if (!k.mod.command) { + scancode_handled=false; + break; + } + + if (k.mod.shift) + redo(); + else + undo(); } break; case KEY_V: { - + if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; + scancode_handled=false; + break; } - + String clipboard = OS::get_singleton()->get_clipboard(); - + if (selection.active) { selection.active=false; _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); cursor_set_line(selection.from_line); cursor_set_column(selection.from_column); - + } - else if (cut_copy_line) - { - cursor_set_column(0); - String ins="\n"; - clipboard += ins; - } - + else if (cut_copy_line) + { + cursor_set_column(0); + String ins="\n"; + clipboard += ins; + } + _insert_text_at_cursor(clipboard); - + update(); } break; case KEY_SPACE: { +#ifdef OSX_ENABLED + if (completion_enabled && k.mod.meta) { //cmd-space is spotlight shortcut in OSX +#else if (completion_enabled && k.mod.command) { - +#endif + query_code_comple(); scancode_handled=true; } else { scancode_handled=false; } - + } break; - - case KEY_K:{ - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; - } - else { - if (selection.active) { - int ini = selection.from_line; - int end = selection.to_line; - for (int i=ini; i<= end; i++) - { - _insert_text(i,0,"#"); - } - } - else{ - _insert_text(cursor.line,0,"#"); - } - update(); - } - break;} - - case KEY_U:{ - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; - } - else { - if (selection.active) { - int ini = selection.from_line; - int end = selection.to_line; - for (int i=ini; i<= end; i++) - { - if (text[i][0] == '#') - _remove_text(i,0,i,1); - } - } - else{ - if (text[cursor.line][0] == '#') - _remove_text(cursor.line,0,cursor.line,1); - } - update(); - } - break;} - - default: { - - scancode_handled=false; - } break; - - } - - if (scancode_handled) - accept_event(); - - if (!scancode_handled && !k.mod.command && !k.mod.alt) { - - if (k.unicode>=32) { - - if (readonly) + + case KEY_U:{ + if (!k.mod.command || k.mod.shift) { + scancode_handled=false; break; - - accept_event(); - } else { - - break; - } + } + else { + if (selection.active) { + int ini = selection.from_line; + int end = selection.to_line; + for (int i=ini; i<= end; i++) + { + if (text[i][0] == '#') + _remove_text(i,0,i,1); + } + } + else{ + if (text[cursor.line][0] == '#') + _remove_text(cursor.line,0,cursor.line,1); + } + update(); + } + break;} + + default: { + + scancode_handled=false; + } break; + } - if (!scancode_handled && !k.mod.command && !k.mod.alt) { + if (scancode_handled) + accept_event(); + /* + if (!scancode_handled && !k.mod.command && !k.mod.alt) { + + if (k.unicode>=32) { + + if (readonly) + break; + accept_event(); + } else { + + break; + } + } +*/ + if (!scancode_handled && !k.mod.command) { //for german kbds + if (k.unicode>=32) { - + if (readonly) break; @@ -1777,30 +2082,30 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { accept_event(); } else { - + break; } } - + if (!selection.selecting_test) { - + selection.selecting_mode=Selection::MODE_NONE; } - + return; } break; - + } - + } void TextEdit::_pre_shift_selection() { - - + + if (!selection.active || selection.selecting_mode!=Selection::MODE_SHIFT) { - + selection.selecting_line=cursor.line; selection.selecting_column=cursor.column; selection.active=true; @@ -1809,145 +2114,141 @@ void TextEdit::_pre_shift_selection() { } void TextEdit::_post_shift_selection() { - - + + if (selection.active && selection.selecting_mode==Selection::MODE_SHIFT) { - + select(selection.selecting_line,selection.selecting_column,cursor.line,cursor.column); update(); } - - + + selection.selecting_test=true; } /**** TEXT EDIT CORE API ****/ void TextEdit::_base_insert_text(int p_line, int p_char,const String& p_text,int &r_end_line,int &r_end_column) { - + //save for undo... ERR_FAIL_INDEX(p_line,text.size()); ERR_FAIL_COND(p_char<0); - + /* STEP 1 add spaces if the char is greater than the end of the line */ while(p_char>text[p_line].length()) { - + text.set(p_line,text[p_line]+String::chr(' ')); } - + /* STEP 2 separate dest string in pre and post text */ - + String preinsert_text = text[p_line].substr(0,p_char); String postinsert_text = text[p_line].substr(p_char,text[p_line].size()); - + /* STEP 3 remove \r from source text and separate in substrings */ - + //buh bye \r and split Vector<String> substrings = p_text.replace("\r","").split("\n"); - - + + for(int i=0;i<substrings.size();i++) { //insert the substrings - + if (i==0) { - + text.set(p_line,preinsert_text+substrings[i]); } else { - + text.insert(p_line+i,substrings[i]); } - + if (i==substrings.size()-1){ - + text.set(p_line+i,text[p_line+i]+postinsert_text); } } - + r_end_line=p_line+substrings.size()-1; r_end_column=text[r_end_line].length()-postinsert_text.length(); - + if (!text_changed_dirty && !setting_text) { - - if (is_inside_scene()) + if (is_inside_tree()) MessageQueue::get_singleton()->push_call(this,"_text_changed_emit"); text_changed_dirty=true; } - + } String TextEdit::_base_get_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) const { - + ERR_FAIL_INDEX_V(p_from_line,text.size(),String()); ERR_FAIL_INDEX_V(p_from_column,text[p_from_line].length()+1,String()); ERR_FAIL_INDEX_V(p_to_line,text.size(),String()); ERR_FAIL_INDEX_V(p_to_column,text[p_to_line].length()+1,String()); ERR_FAIL_COND_V(p_to_line < p_from_line ,String()); // from > to ERR_FAIL_COND_V(p_to_line == p_from_line && p_to_column<p_from_column,String()); // from > to - + String ret; - + for(int i=p_from_line;i<=p_to_line;i++) { - + int begin = (i==p_from_line)?p_from_column:0; int end = (i==p_to_line)?p_to_column:text[i].length(); - + if (i>p_from_line) ret+="\n"; ret+=text[i].substr(begin,end-begin); } - + return ret; } void TextEdit::_base_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) { - + ERR_FAIL_INDEX(p_from_line,text.size()); ERR_FAIL_INDEX(p_from_column,text[p_from_line].length()+1); ERR_FAIL_INDEX(p_to_line,text.size()); ERR_FAIL_INDEX(p_to_column,text[p_to_line].length()+1); ERR_FAIL_COND(p_to_line < p_from_line ); // from > to ERR_FAIL_COND(p_to_line == p_from_line && p_to_column<p_from_column); // from > to - - + + String pre_text = text[p_from_line].substr(0,p_from_column); String post_text = text[p_to_line].substr(p_to_column,text[p_to_line].length()); - + for(int i=p_from_line;i<p_to_line;i++) { - + text.remove(p_from_line+1); } - + text.set(p_from_line,pre_text+post_text); - + if (!text_changed_dirty && !setting_text) { - - if (is_inside_scene()) + if (is_inside_tree()) MessageQueue::get_singleton()->push_call(this,"_text_changed_emit"); text_changed_dirty=true; } } - - void TextEdit::_insert_text(int p_line, int p_char,const String& p_text,int *r_end_line,int *r_end_column) { - + if (!setting_text) idle_detect->start(); - + if (undo_enabled) { _clear_redo(); } - + int retline,retchar; _base_insert_text(p_line,p_char,p_text,retline,retchar); if (r_end_line) *r_end_line=retline; if (r_end_column) *r_end_column=retchar; - + if (!undo_enabled) return; - + /* UNDO!! */ TextOperation op; op.type=TextOperation::TYPE_INSERT; @@ -1959,12 +2260,12 @@ void TextEdit::_insert_text(int p_line, int p_char,const String& p_text,int *r_e op.version=++version; op.chain_forward=false; op.chain_backward=false; - + //see if it shold just be set as current op if (current_op.type!=op.type) { _push_current_op(); current_op=op; - + return; //set as current op, return } //see if it can be merged @@ -1974,30 +2275,30 @@ void TextEdit::_insert_text(int p_line, int p_char,const String& p_text,int *r_e return; //set as current op, return } //merge current op - + current_op.text+=p_text; current_op.to_column=retchar; current_op.to_line=retline; current_op.version=op.version; - + } void TextEdit::_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) { - + if (!setting_text) idle_detect->start(); - + String text; if (undo_enabled) { _clear_redo(); text=_base_get_text(p_from_line,p_from_column,p_to_line,p_to_column); } - + _base_remove_text(p_from_line,p_from_column,p_to_line,p_to_column); - + if (!undo_enabled) return; - + /* UNDO!! */ TextOperation op; op.type=TextOperation::TYPE_REMOVE; @@ -2009,7 +2310,7 @@ void TextEdit::_remove_text(int p_from_line, int p_from_column,int p_to_line,int op.version=++version; op.chain_forward=false; op.chain_backward=false; - + //see if it shold just be set as current op if (current_op.type!=op.type) { _push_current_op(); @@ -2025,26 +2326,26 @@ void TextEdit::_remove_text(int p_from_line, int p_from_column,int p_to_line,int return; //update current op } if (current_op.from_line==p_from_line && current_op.from_column==p_from_column) { - + //current_op.text=text+current_op.text; //current_op.from_line=p_from_line; //current_op.from_column=p_from_column; //return; //update current op } - + _push_current_op(); current_op=op; - + } void TextEdit::_insert_text_at_cursor(const String& p_text) { - + int new_column,new_line; _insert_text(cursor.line,cursor.column,p_text,&new_line,&new_column); cursor_set_line(new_line); cursor_set_column(new_column); - + update(); } @@ -2052,145 +2353,143 @@ void TextEdit::_insert_text_at_cursor(const String& p_text) { int TextEdit::get_char_count() { - + int totalsize=0; - + for (int i=0;i<text.size();i++) { - + if (i>0) totalsize++; // incliude \n totalsize+=text[i].length(); } - + return totalsize; // omit last \n } Size2 TextEdit::get_minimum_size() { - + return cache.style_normal->get_minimum_size(); } int TextEdit::get_visible_rows() const { - + int total=cache.size.height; total-=cache.style_normal->get_minimum_size().height; total/=get_row_height(); return total; } void TextEdit::adjust_viewport_to_cursor() { - + if (cursor.line_ofs>cursor.line) cursor.line_ofs=cursor.line; - + int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w; if (v_scroll->is_visible()) visible_width-=v_scroll->get_combined_minimum_size().width; visible_width-=20; // give it a little more space - - + + //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line); - + int visible_rows = get_visible_rows(); if (h_scroll->is_visible()) visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); - + if (cursor.line>=(cursor.line_ofs+visible_rows)) cursor.line_ofs=cursor.line-visible_rows+1; if (cursor.line<cursor.line_ofs) cursor.line_ofs=cursor.line; - + int cursor_x = get_column_x_offset( cursor.column, text[cursor.line] ); - + if (cursor_x>(cursor.x_ofs+visible_width)) cursor.x_ofs=cursor_x-visible_width+1; - + if (cursor_x < cursor.x_ofs) cursor.x_ofs=cursor_x; - + update(); -/* - get_range()->set_max(text.size()); - - get_range()->set_page(get_visible_rows()); - - get_range()->set((int)cursor.line_ofs); + /* + get_range()->set_max(text.size()); + + get_range()->set_page(get_visible_rows()); + + get_range()->set((int)cursor.line_ofs); */ - - + + } void TextEdit::cursor_set_column(int p_col) { - + if (p_col<0) p_col=0; - + cursor.column=p_col; if (cursor.column > get_line( cursor.line ).length()) cursor.column=get_line( cursor.line ).length(); - + cursor.last_fit_x=get_column_x_offset(cursor.column,get_line(cursor.line)); - + adjust_viewport_to_cursor(); - + if (!cursor_changed_dirty) { - - if (is_inside_scene()) + if (is_inside_tree()) MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); cursor_changed_dirty=true; } - + } void TextEdit::cursor_set_line(int p_row) { - + if (setting_row) return; - + setting_row=true; if (p_row<0) p_row=0; - - + + if (p_row>=(int)text.size()) p_row=(int)text.size()-1; - + cursor.line=p_row; cursor.column=get_char_pos_for( cursor.last_fit_x, get_line( cursor.line) ); - - + + adjust_viewport_to_cursor(); - + setting_row=false; - - + + if (!cursor_changed_dirty) { - - if (is_inside_scene()) + if (is_inside_tree()) MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); cursor_changed_dirty=true; } - + } int TextEdit::cursor_get_column() const { - + return cursor.column; } int TextEdit::cursor_get_line() const { - + return cursor.line; } void TextEdit::_scroll_moved(double p_to_val) { - + if (updating_scrolls) return; - + if (h_scroll->is_visible()) cursor.x_ofs=h_scroll->get_val(); if (v_scroll->is_visible()) @@ -2203,87 +2502,87 @@ void TextEdit::_scroll_moved(double p_to_val) { int TextEdit::get_row_height() const { - + return cache.font->get_height()+cache.line_spacing; } int TextEdit::get_char_pos_for(int p_px,String p_str) const { - + int px=0; int c=0; - + int tab_w = cache.font->get_char_size(' ').width*tab_size; - + while (c<p_str.length()) { - + int w=0; - + if (p_str[c]=='\t') { - + int left = px%tab_w; if (left==0) w=tab_w; else w=tab_w-px%tab_w; // is right... - + } else { - + w=cache.font->get_char_size(p_str[c],p_str[c+1]).width; } - + if (p_px<(px+w/2)) break; px+=w; c++; } - + return c; } int TextEdit::get_column_x_offset(int p_char,String p_str) { - + int px=0; - + int tab_w = cache.font->get_char_size(' ').width*tab_size; - + for (int i=0;i<p_char;i++) { - + if (i>=p_str.length()) break; - + if (p_str[i]=='\t') { - + int left = px%tab_w; if (left==0) px+=tab_w; else px+=tab_w-px%tab_w; // is right... - + } else { px+=cache.font->get_char_size(p_str[i],p_str[i+1]).width; } } - + return px; - + } void TextEdit::insert_text_at_cursor(const String& p_text) { - + if (selection.active) { - + cursor_set_line(selection.from_line); cursor_set_column(selection.from_column); - + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); selection.active=false; selection.selecting_mode=Selection::MODE_NONE; - + } - + _insert_text_at_cursor(p_text); update(); - + } Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { @@ -2295,11 +2594,11 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { void TextEdit::set_text(String p_text){ - + setting_text=true; _clear(); _insert_text_at_cursor(p_text); - + cursor.column=0; cursor.line=0; cursor.x_ofs=0; @@ -2309,7 +2608,7 @@ void TextEdit::set_text(String p_text){ cursor_set_column(0); update(); setting_text=false; - + //get_range()->set(0); }; @@ -2317,29 +2616,53 @@ String TextEdit::get_text() { String longthing; int len = text.size(); for (int i=0;i<len;i++) { - - + + longthing+=text[i]; if (i!=len-1) longthing+="\n"; } - + return longthing; + +}; +String TextEdit::get_text_for_completion() { + + String longthing; + int len = text.size(); + for (int i=0;i<len;i++) { + + if (i==cursor.line) { + longthing+=text[i].substr(0,cursor.column); + longthing+=String::chr(0xFFFF); //not unicode, represents the cursor + longthing+=text[i].substr(cursor.column,text[i].size()); + } else { + + longthing+=text[i]; + } + + + if (i!=len-1) + longthing+="\n"; + } + + return longthing; + }; String TextEdit::get_line(int line) const { - + if (line<0 || line>=text.size()) return ""; - + return text[line]; - + }; void TextEdit::_clear() { - + clear_undo_history(); text.clear(); cursor.column=0; @@ -2352,31 +2675,31 @@ void TextEdit::_clear() { void TextEdit::clear() { - + setting_text=true; _clear(); setting_text=false; - + }; void TextEdit::set_readonly(bool p_readonly) { - - + + readonly=p_readonly; } void TextEdit::set_wrap(bool p_wrap) { - + wrap=p_wrap; } void TextEdit::set_max_chars(int p_max_chars) { - + max_chars=p_max_chars; } void TextEdit::_update_caches() { - + cache.style_normal=get_stylebox("normal"); cache.style_focus=get_stylebox("focus"); cache.font=get_font("font"); @@ -2387,16 +2710,17 @@ void TextEdit::_update_caches() { cache.mark_color=get_color("mark_color"); cache.current_line_color=get_color("current_line_color"); cache.breakpoint_color=get_color("breakpoint_color"); + cache.brace_mismatch_color=get_color("brace_mismatch_color"); cache.line_spacing=get_constant("line_spacing"); cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon=get_icon("tab"); text.set_font(cache.font); - + } void TextEdit::clear_colors() { - + keywords.clear(); color_regions.clear();; text.clear_caches(); @@ -2404,20 +2728,20 @@ void TextEdit::clear_colors() { } void TextEdit::set_custom_bg_color(const Color& p_color) { - + custom_bg_color=p_color; update(); } void TextEdit::add_keyword_color(const String& p_keyword,const Color& p_color) { - + keywords[p_keyword]=p_color; update(); - + } void TextEdit::add_color_region(const String& p_begin_key,const String& p_end_key,const Color &p_color,bool p_line_only) { - + color_regions.push_back(ColorRegion(p_begin_key,p_end_key,p_color,p_line_only)); text.clear_caches(); update(); @@ -2425,70 +2749,70 @@ void TextEdit::add_color_region(const String& p_begin_key,const String& p_end_ke } void TextEdit::set_symbol_color(const Color& p_color) { - + symbol_color=p_color; update(); } void TextEdit::set_syntax_coloring(bool p_enabled) { - + syntax_coloring=p_enabled; update(); } bool TextEdit::is_syntax_coloring_enabled() const { - + return syntax_coloring; } void TextEdit::cut() { - + if (!selection.active) return; - + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); OS::get_singleton()->set_clipboard(clipboard); - + cursor_set_line(selection.from_line); cursor_set_column(selection.from_column); - + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); selection.active=false; selection.selecting_mode=Selection::MODE_NONE; update(); - + } void TextEdit::copy() { - + if (!selection.active) return; - + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); OS::get_singleton()->set_clipboard(clipboard); - + } void TextEdit::paste() { - + if (selection.active) { - + cursor_set_line(selection.from_line); cursor_set_column(selection.from_column); - + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); selection.active=false; selection.selecting_mode=Selection::MODE_NONE; - + } - + String clipboard = OS::get_singleton()->get_clipboard(); _insert_text_at_cursor(clipboard); update(); - + } void TextEdit::select_all() { - + if (text.size()==1 && text[0].length()==0) return; selection.active=true; @@ -2498,95 +2822,95 @@ void TextEdit::select_all() { selection.to_column=text[selection.to_line].size(); selection.selecting_mode=Selection::MODE_NONE; update(); - + } void TextEdit::deselect() { - + selection.active=false; update(); } void TextEdit::select(int p_from_line,int p_from_column,int p_to_line,int p_to_column) { - + if (p_from_line>=text.size()) p_from_line=text.size()-1; if (p_from_column>=text[p_from_line].length()) p_from_column=text[p_from_line].length(); - + if (p_to_line>=text.size()) p_to_line=text.size()-1; if (p_to_column>=text[p_to_line].length()) p_to_column=text[p_to_line].length(); - + selection.from_line=p_from_line; selection.from_column=p_from_column; selection.to_line=p_to_line; selection.to_column=p_to_column; - + selection.active=true; - + if (selection.from_line==selection.to_line) { - + if (selection.from_column==selection.to_column) { - + selection.active=false; - + } else if (selection.from_column>selection.to_column) { - + SWAP( selection.from_column, selection.to_column ); } } else if (selection.from_line>selection.to_line) { - + SWAP( selection.from_line, selection.to_line ); SWAP( selection.from_column, selection.to_column ); } - - + + update(); } bool TextEdit::is_selection_active() const { - + return selection.active; } int TextEdit::get_selection_from_line() const { - + ERR_FAIL_COND_V(!selection.active,-1); return selection.from_line; - + } int TextEdit::get_selection_from_column() const { - + ERR_FAIL_COND_V(!selection.active,-1); return selection.from_column; - + } int TextEdit::get_selection_to_line() const { - + ERR_FAIL_COND_V(!selection.active,-1); return selection.to_line; - + } int TextEdit::get_selection_to_column() const { - + ERR_FAIL_COND_V(!selection.active,-1); return selection.to_column; - + } String TextEdit::get_selection_text() const { - + if (!selection.active) return ""; - + return _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - + } String TextEdit::get_word_under_cursor() const { - + int prev_cc = cursor.column; while(prev_cc >0) { bool is_char = _is_text_char(text[cursor.line][prev_cc-1]); @@ -2594,7 +2918,7 @@ String TextEdit::get_word_under_cursor() const { break; --prev_cc; } - + int next_cc = cursor.column; while(next_cc<text[cursor.line].length()) { bool is_char = _is_text_char(text[cursor.line][next_cc]); @@ -2608,7 +2932,7 @@ String TextEdit::get_word_under_cursor() const { } DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { - + int col,line; if (search(p_key,p_search_flags,p_from_line,p_from_column,col,line)) { DVector<int> result; @@ -2616,46 +2940,46 @@ DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, result.set(0,line); result.set(1,col); return result; - + } else { - + return DVector<int>(); } } bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_line, int p_from_column,int &r_line,int &r_column) const { - + if (p_key.length()==0) return false; ERR_FAIL_INDEX_V(p_from_line,text.size(),false); ERR_FAIL_INDEX_V(p_from_column,text[p_from_line].length()+1,false); - + //search through the whole documment, but start by current line - + int line=-1; int pos=-1; - + line=p_from_line; - + for(int i=0;i<text.size()+1;i++) { //backwards is broken... //int idx=(p_search_flags&SEARCH_BACKWARDS)?(text.size()-i):i; //do backwards seearch - - + + if (line<0) { line=text.size()-1; } if (line==text.size()) { line=0; } - + String text_line = text[line]; int from_column=0; if (line==p_from_line) { - + if (i==text.size()) { //wrapped - + if (p_search_flags&SEARCH_BACKWARDS) { text_line=text_line.substr(from_column,text_line.length()); from_column=text_line.length(); @@ -2663,13 +2987,13 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li text_line=text_line.substr(0,from_column); from_column=0; } - + } else { - + from_column=p_from_column; } - - + + } else { //text_line=text_line.substr(0,p_from_column); //wrap around for missing begining. if (p_search_flags&SEARCH_BACKWARDS) @@ -2677,17 +3001,17 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li else from_column=0; } - + pos=-1; - + if (!(p_search_flags&SEARCH_BACKWARDS)) { - + pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,from_column):text_line.findn(p_key,from_column); } else { - + pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.rfind(p_key,from_column):text_line.rfindn(p_key,from_column); } - + if (pos!=-1 && (p_search_flags&SEARCH_WHOLE_WORDS)) { //validate for whole words if (pos>0 && _is_text_char(text_line[pos-1])) @@ -2695,66 +3019,66 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li else if (_is_text_char(text_line[pos+p_key.length()])) pos=-1; } - + if (pos!=-1) break; - + if (p_search_flags&SEARCH_BACKWARDS) line--; else line++; - + } - + if (pos==-1) { r_line=-1; r_column=-1; return false; } - + r_line=line; r_column=pos; - - + + return true; } void TextEdit::_cursor_changed_emit() { - + emit_signal("cursor_changed"); cursor_changed_dirty=false; } void TextEdit::_text_changed_emit() { - + emit_signal("text_changed"); text_changed_dirty=false; } void TextEdit::set_line_as_marked(int p_line,bool p_marked) { - + ERR_FAIL_INDEX(p_line,text.size()); text.set_marked(p_line,p_marked); update(); } bool TextEdit::is_line_set_as_breakpoint(int p_line) const { - + ERR_FAIL_INDEX_V(p_line,text.size(),false); return text.is_breakpoint(p_line); - + } void TextEdit::set_line_as_breakpoint(int p_line,bool p_breakpoint) { - - + + ERR_FAIL_INDEX(p_line,text.size()); text.set_breakpoint(p_line,p_breakpoint); update(); } void TextEdit::get_breakpoints(List<int> *p_breakpoints) const { - + for(int i=0;i<text.size();i++) { if (text.is_breakpoint(i)) p_breakpoints->push_back(i); @@ -2762,39 +3086,39 @@ void TextEdit::get_breakpoints(List<int> *p_breakpoints) const { } int TextEdit::get_line_count() const { - + return text.size(); } void TextEdit::_do_text_op(const TextOperation& p_op, bool p_reverse) { - + ERR_FAIL_COND(p_op.type==TextOperation::TYPE_NONE); - + bool insert = p_op.type==TextOperation::TYPE_INSERT; if (p_reverse) insert=!insert; - + if (insert) { - + int check_line; int check_column; _base_insert_text(p_op.from_line,p_op.from_column,p_op.text,check_line,check_column); ERR_FAIL_COND( check_line != p_op.to_line ); // BUG ERR_FAIL_COND( check_column != p_op.to_column ); // BUG } else { - + _base_remove_text(p_op.from_line,p_op.from_column,p_op.to_line,p_op.to_column); } - + } void TextEdit::_clear_redo() { - + if (undo_stack_pos==NULL) return; //nothing to clear - + _push_current_op(); - + while (undo_stack_pos) { List<TextOperation>::Element *elem = undo_stack_pos; undo_stack_pos=undo_stack_pos->next(); @@ -2806,19 +3130,19 @@ void TextEdit::_clear_redo() { void TextEdit::undo() { _push_current_op(); - + if (undo_stack_pos==NULL) { - + if (!undo_stack.size()) return; //nothing to undo - + undo_stack_pos=undo_stack.back(); - + } else if (undo_stack_pos==undo_stack.front()) return; // at the bottom of the undo stack else undo_stack_pos=undo_stack_pos->prev(); - + _do_text_op( undo_stack_pos->get(),true); if(undo_stack_pos->get().chain_backward) { do { @@ -2826,19 +3150,19 @@ void TextEdit::undo() { _do_text_op(undo_stack_pos->get(), true); } while(!undo_stack_pos->get().chain_forward); } - + cursor_set_line(undo_stack_pos->get().from_line); cursor_set_column(undo_stack_pos->get().from_column); update(); } void TextEdit::redo() { - + _push_current_op(); - + if (undo_stack_pos==NULL) return; //nothing to do. - + _do_text_op(undo_stack_pos->get(), false); if(undo_stack_pos->get().chain_forward) { do { @@ -2853,12 +3177,12 @@ void TextEdit::redo() { } void TextEdit::clear_undo_history() { - + saved_version=0; current_op.type=TextOperation::TYPE_NONE; undo_stack_pos=NULL; undo_stack.clear(); - + } void TextEdit::_begin_compex_operation() { @@ -2897,12 +3221,12 @@ void TextEdit::_push_current_op() { } void TextEdit::set_draw_tabs(bool p_draw) { - + draw_tabs=p_draw; } bool TextEdit::is_drawing_tabs() const{ - + return draw_tabs; } @@ -2910,35 +3234,35 @@ uint32_t TextEdit::get_version() const { return current_op.version; } uint32_t TextEdit::get_saved_version() const { - + return saved_version; } void TextEdit::tag_saved_version() { - + saved_version=get_version(); } int TextEdit::get_v_scroll() const { - + return v_scroll->get_val(); } void TextEdit::set_v_scroll(int p_scroll) { - + v_scroll->set_val(p_scroll); cursor.line_ofs=p_scroll; } int TextEdit::get_h_scroll() const { - + return h_scroll->get_val(); } void TextEdit::set_h_scroll(int p_scroll) { - + h_scroll->set_val(p_scroll); } void TextEdit::set_completion(bool p_enabled,const Vector<String>& p_prefixes) { - + completion_prefixes.clear(); completion_enabled=p_enabled; for(int i=0;i<p_prefixes.size();i++) @@ -2946,7 +3270,7 @@ void TextEdit::set_completion(bool p_enabled,const Vector<String>& p_prefixes) { } void TextEdit::_confirm_completion() { - + String remaining=completion_current.substr(completion_base.length(),completion_current.length()-completion_base.length()); String l = text[cursor.line]; bool same=true; @@ -2958,44 +3282,89 @@ void TextEdit::_confirm_completion() { break; } } - + if (same) cursor_set_column(cursor.column+remaining.length()); - else + else { insert_text_at_cursor(remaining); - + if (remaining.ends_with("(") && auto_brace_completion_enabled) { + insert_text_at_cursor(")"); + cursor.column--; + } + } + _cancel_completion(); } -void TextEdit::_cancel_completion() { +void TextEdit::_cancel_code_hint() { + completion_hint=""; + update(); +} + +void TextEdit::_cancel_completion() { + if (!completion_active) return; - + completion_active=false; update(); + +} +static bool _is_completable(CharType c) { + + return !_is_symbol(c) || c=='"' || c=='\''; } -void TextEdit::_update_completion_candidates() { +void TextEdit::_update_completion_candidates() { + String l = text[cursor.line]; int cofs = CLAMP(cursor.column,0,l.length()); - + + String s; - while(cofs>0 && l[cofs-1]>32 && !_is_symbol(l[cofs-1])) { - s=String::chr(l[cofs-1])+s; - cofs--; + + //look for keywords first + + bool pre_keyword=false; + + if (cofs>0 && l[cofs-1]==' ') { + int kofs=cofs-1; + String kw; + while (kofs>=0 && l[kofs]==' ') + kofs--; + + while(kofs>=0 && l[kofs]>32 && _is_completable(l[kofs])) { + kw=String::chr(l[kofs])+kw; + kofs--; + } + + pre_keyword=keywords.has(kw); + print_line("KW "+kw+"? "+itos(pre_keyword)); + + } else { + + + while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { + s=String::chr(l[cofs-1])+s; + if (l[cofs-1]=='\'' || l[cofs-1]=='"') + break; + + cofs--; + } } + update(); - - if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { + + if (!pre_keyword && s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { //none to complete, cancel _cancel_completion(); return; } - + completion_options.clear(); completion_index=0; completion_base=s; @@ -3008,7 +3377,7 @@ void TextEdit::_update_completion_candidates() { if (max<ci_match) continue; for(int j=0;j<max;j++) { - + if (j>=completion_strings[i].length()) break; if (completion_current[j]!=completion_strings[i][j]) @@ -3019,181 +3388,180 @@ void TextEdit::_update_completion_candidates() { ci_match=m; completion_index=completion_options.size()-1; } - + } } - - - + + + if (completion_options.size()==0) { //no options to complete, cancel _cancel_completion(); return; - + } - + completion_current=completion_options[completion_index]; - + #if 0 // even there's only one option, user still get the chance to choose using it or not if (completion_options.size()==1) { //one option to complete, just complete it automagically _confirm_completion(); -// insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); + // insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); _cancel_completion(); return; - + } #endif if (completion_options.size()==1 && s==completion_options[0]) _cancel_completion(); - + completion_enabled=true; +} -} - void TextEdit::query_code_comple() { - + String l = text[cursor.line]; int ofs = CLAMP(cursor.column,0,l.length()); - String cs; - while(ofs>0 && l[ofs-1]>32) { - - if (_is_symbol(l[ofs-1])) { - String s; - while(ofs>0 && l[ofs-1]>32 && _is_symbol(l[ofs-1])) { - s=String::chr(l[ofs-1])+s; - ofs--; - } - if (completion_prefixes.has(s)) - cs=s+cs; - else - break; - } else { - - cs=String::chr(l[ofs-1])+cs; - ofs--; - } - - } - - if (cs!="") { - emit_signal("request_completion",cs,cursor.line); + + if (ofs>0 && (_is_completable(l[ofs-1]) || completion_prefixes.has(String::chr(l[ofs-1])))) + emit_signal("request_completion"); + +} - } +void TextEdit::set_code_hint(const String& p_hint) { + + completion_hint=p_hint; + completion_hint_offset=-0xFFFF; + update(); } void TextEdit::code_complete(const Vector<String> &p_strings) { - - + + completion_strings=p_strings; completion_active=true; completion_current=""; completion_index=0; _update_completion_candidates(); -// + // } String TextEdit::get_tooltip(const Point2& p_pos) const { - + if (!tooltip_obj) return Control::get_tooltip(p_pos); int row,col; if (!_get_mouse_pos(p_pos, row,col)) { return Control::get_tooltip(p_pos); } - + String s = text[row]; if (s.length()==0) return Control::get_tooltip(p_pos); int beg=CLAMP(col,0,s.length()); int end=beg; - - + + if (s[beg]>32 || beg==s.length()) { - + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this - + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { beg--; } while(end<s.length() && s[end+1]>32 && (symbol==_is_symbol(s[end+1]))) { end++; } - + if (end<s.length()) end+=1; - + String tt = tooltip_obj->call(tooltip_func,s.substr(beg,end-beg),tooltip_ud); - + return tt; - + } - + return Control::get_tooltip(p_pos); - + } void TextEdit::set_tooltip_request_func(Object *p_obj, const StringName& p_function,const Variant& p_udata) { - + tooltip_obj=p_obj; tooltip_func=p_function; tooltip_ud=p_udata; } +void TextEdit::set_line(int line, String new_text) +{ + if (line < 0 || line > text.size()) + return; + _remove_text(line, 0, line, text[line].length()); + _insert_text(line, 0, new_text); +} -void TextEdit::set_show_line_numbers(bool p_show) { +void TextEdit::insert_at(const String &p_text, int at) +{ + cursor_set_column(0); + cursor_set_line(at); + _insert_text(at, 0, p_text+"\n"); +} +void TextEdit::set_show_line_numbers(bool p_show) { + line_numbers=p_show; update(); } void TextEdit::_bind_methods() { - - + + ObjectTypeDB::bind_method(_MD("_input_event"),&TextEdit::_input_event); ObjectTypeDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); - + BIND_CONSTANT( SEARCH_MATCH_CASE ); BIND_CONSTANT( SEARCH_WHOLE_WORDS ); BIND_CONSTANT( SEARCH_BACKWARDS ); - -/* - ObjectTypeDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); - ObjectTypeDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); + + /* + ObjectTypeDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); + ObjectTypeDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); */ - + ObjectTypeDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); ObjectTypeDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); - + ObjectTypeDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); ObjectTypeDB::bind_method(_MD("get_text"),&TextEdit::get_text); ObjectTypeDB::bind_method(_MD("get_line"),&TextEdit::get_line); - + ObjectTypeDB::bind_method(_MD("cursor_set_column","column"),&TextEdit::cursor_set_column); ObjectTypeDB::bind_method(_MD("cursor_set_line","line"),&TextEdit::cursor_set_line); - + ObjectTypeDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); ObjectTypeDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); - - + + ObjectTypeDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); ObjectTypeDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); ObjectTypeDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); - + ObjectTypeDB::bind_method(_MD("cut"),&TextEdit::cut); ObjectTypeDB::bind_method(_MD("copy"),&TextEdit::copy); ObjectTypeDB::bind_method(_MD("paste"),&TextEdit::paste); ObjectTypeDB::bind_method(_MD("select_all"),&TextEdit::select_all); ObjectTypeDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); - + ObjectTypeDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); ObjectTypeDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); ObjectTypeDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); @@ -3202,30 +3570,30 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); ObjectTypeDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); ObjectTypeDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); - + ObjectTypeDB::bind_method(_MD("undo"),&TextEdit::undo); ObjectTypeDB::bind_method(_MD("redo"),&TextEdit::redo); ObjectTypeDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); ObjectTypeDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); ObjectTypeDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); - + ObjectTypeDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); ObjectTypeDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); - - + + ADD_SIGNAL(MethodInfo("cursor_changed")); ADD_SIGNAL(MethodInfo("text_changed")); - ADD_SIGNAL(MethodInfo("request_completion",PropertyInfo(Variant::STRING,"keyword"),PropertyInfo(Variant::INT,"line"))); - + ADD_SIGNAL(MethodInfo("request_completion")); + } TextEdit::TextEdit() { - + readonly=false; setting_row=false; draw_tabs=false; @@ -3238,39 +3606,39 @@ TextEdit::TextEdit() { tab_size=4; text.set_tab_size(tab_size); text.clear(); -// text.insert(1,"Mongolia.."); -// text.insert(2,"PAIS GENEROSO!!"); + // text.insert(1,"Mongolia.."); + // text.insert(2,"PAIS GENEROSO!!"); text.set_color_regions(&color_regions); - + h_scroll = memnew( HScrollBar ); v_scroll = memnew( VScrollBar ); - + add_child(h_scroll); add_child(v_scroll); - + updating_scrolls=false; selection.active=false; - + h_scroll->connect("value_changed", this,"_scroll_moved"); v_scroll->connect("value_changed", this,"_scroll_moved"); - + cursor_changed_dirty=false; text_changed_dirty=false; - + selection.selecting_mode=Selection::MODE_NONE; selection.selecting_line=0; selection.selecting_column=0; selection.selecting_test=false; selection.active=false; syntax_coloring=false; - + custom_bg_color=Color(0,0,0,0); idle_detect = memnew( Timer ); add_child(idle_detect); idle_detect->set_one_shot(true); idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3)); idle_detect->connect("timeout", this,"_push_current_op"); - + #if 0 syntax_coloring=true; keywords["void"]=Color(0.3,0.0,0.1); @@ -3280,24 +3648,24 @@ TextEdit::TextEdit() { keywords["extends"]=Color(0.3,0.0,0.1); keywords["constructor"]=Color(0.3,0.0,0.1); symbol_color=Color(0.1,0.0,0.3,1.0); - + color_regions.push_back(ColorRegion("/*","*/",Color(0.4,0.6,0,4))); color_regions.push_back(ColorRegion("//","",Color(0.6,0.6,0.4))); color_regions.push_back(ColorRegion("\"","\"",Color(0.4,0.7,0.7))); color_regions.push_back(ColorRegion("'","'",Color(0.4,0.8,0.8))); color_regions.push_back(ColorRegion("#","",Color(0.2,1.0,0.2))); - + #endif - + current_op.type=TextOperation::TYPE_NONE; undo_enabled=true; - undo_stack_pos=NULL; + undo_stack_pos=NULL; setting_text=false; last_dblclk=0; current_op.version=0; version=0; saved_version=0; - + completion_enabled=false; completion_active=false; completion_line_ofs=0; @@ -3305,9 +3673,10 @@ TextEdit::TextEdit() { line_numbers=false; next_operation_is_complex=false; auto_brace_completion_enabled=false; + brace_matching_enabled=false; + } -TextEdit::~TextEdit(){ +TextEdit::~TextEdit() +{ } - - diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 15c289a87e..1d57aef416 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -63,6 +63,7 @@ class TextEdit : public Control { int from_line,from_column; int to_line,to_column; + bool shiftclick_left; } selection; @@ -79,6 +80,7 @@ class TextEdit : public Control { Color mark_color; Color breakpoint_color; Color current_line_color; + Color brace_mismatch_color; int row_height; int line_spacing; @@ -138,7 +140,7 @@ class TextEdit : public Control { int size() const { return text.size(); } void clear(); void clear_caches(); - _FORCE_INLINE_ const String& operator[](int p_line) const { return text[p_line].data; } + _FORCE_INLINE_ const String& operator[](int p_line) const { return text[p_line].data; } Text() { tab_size=4; } }; @@ -185,6 +187,8 @@ class TextEdit : public Control { int completion_index; Rect2i completion_rect; int completion_line_ofs; + String completion_hint; + int completion_hint_offset; bool setting_text; @@ -208,6 +212,7 @@ class TextEdit : public Control { bool line_numbers; bool auto_brace_completion_enabled; + bool brace_matching_enabled; bool cut_copy_line; uint64_t last_dblclk; @@ -261,6 +266,7 @@ class TextEdit : public Control { void _clear(); void _cancel_completion(); + void _cancel_code_hint(); void _confirm_completion(); void _update_completion_candidates(); @@ -299,6 +305,7 @@ public: void set_text(String p_text); void insert_text_at_cursor(const String& p_text); + void insert_at(const String& p_text, int at); int get_line_count() const; void set_line_as_marked(int p_line,bool p_marked); void set_line_as_breakpoint(int p_line,bool p_breakpoint); @@ -306,12 +313,17 @@ public: void get_breakpoints(List<int> *p_breakpoints) const; String get_text(); String get_line(int line) const; + void set_line(int line, String new_text); void backspace_at_cursor(); inline void set_auto_brace_completion(bool p_enabled) { auto_brace_completion_enabled = p_enabled; } - + inline void set_brace_matching(bool p_enabled) { + brace_matching_enabled=p_enabled; + update(); + } + void cursor_set_column(int p_col); void cursor_set_line(int p_row); @@ -348,7 +360,7 @@ public: void undo(); void redo(); - void clear_undo_history(); + void clear_undo_history(); void set_draw_tabs(bool p_draw); @@ -374,10 +386,13 @@ public: void set_tooltip_request_func(Object *p_obj, const StringName& p_function, const Variant& p_udata); - void set_completion(bool p_enabled,const Vector<String>& p_prefixes); + void set_completion(bool p_enabled,const Vector<String>& p_prefixes); void code_complete(const Vector<String> &p_strings); + void set_code_hint(const String& p_hint); void query_code_comple(); + String get_text_for_completion(); + TextEdit(); ~TextEdit(); }; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 7954ac65df..1a7087b7ef 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -31,28 +31,37 @@ Size2 TextureButton::get_minimum_size() const { + Size2 rscale; if (normal.is_null()) { if (pressed.is_null()) { if (hover.is_null()) if (click_mask.is_null()) - return Size2(); + rscale= Size2(); else - return click_mask->get_size(); + rscale= click_mask->get_size(); else - return hover->get_size(); + rscale= hover->get_size(); } else - return pressed->get_size(); + rscale= pressed->get_size()*scale; } else - return normal->get_size(); + rscale= normal->get_size(); + + return rscale*scale; } bool TextureButton::has_point(const Point2& p_point) const { + if (scale[0] <= 0 || scale[1] <= 0) { + return false; + } + + Point2 ppos = p_point/scale; + if (click_mask.is_valid()) { - Point2i p =p_point; + Point2i p =ppos; if (p.x<0 || p.x>=click_mask->get_size().width || p.y<0 || p.y>=click_mask->get_size().height) return false; @@ -71,46 +80,57 @@ void TextureButton::_notification(int p_what) { DrawMode draw_mode = get_draw_mode(); // if (normal.is_null()) // break; + + Ref<Texture> texdraw; + switch (draw_mode) { case DRAW_NORMAL: { if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } break; case DRAW_PRESSED: { if (pressed.is_null()) { if (hover.is_null()) { if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } else - hover->draw(canvas_item,Point2()); + texdraw=hover; } else - pressed->draw(canvas_item,Point2()); + texdraw=pressed; } break; case DRAW_HOVER: { if (hover.is_null()) { if (pressed.is_valid() && is_pressed()) - pressed->draw(canvas_item,Point2()); + texdraw=pressed; else if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } else - hover->draw(canvas_item,Point2()); + texdraw=hover; } break; case DRAW_DISABLED: { if (disabled.is_null()) { if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } else - disabled->draw(canvas_item,Point2()); + texdraw=disabled; } break; } + + if (texdraw.is_valid()) { + Rect2 drect(Point2(),texdraw->get_size()*scale); + draw_texture_rect(texdraw,drect,false,modulate); + + } if (has_focus() && focused.is_valid()) { - focused->draw(canvas_item, Point2()); + Rect2 drect(Point2(),focused->get_size()*scale); + draw_texture_rect(focused,drect,false,modulate); + }; } break; @@ -125,6 +145,8 @@ void TextureButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture); ObjectTypeDB::bind_method(_MD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture); ObjectTypeDB::bind_method(_MD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask); + ObjectTypeDB::bind_method(_MD("set_scale","scale"),&TextureButton::set_scale); + ObjectTypeDB::bind_method(_MD("set_modulate","color"),&TextureButton::set_modulate); ObjectTypeDB::bind_method(_MD("get_normal_texture:Texture"),&TextureButton::get_normal_texture); ObjectTypeDB::bind_method(_MD("get_pressed_texture:Texture"),&TextureButton::get_pressed_texture); @@ -132,6 +154,8 @@ void TextureButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture); ObjectTypeDB::bind_method(_MD("get_focused_texture:Texture"),&TextureButton::get_focused_texture); ObjectTypeDB::bind_method(_MD("get_click_mask:BitMap"),&TextureButton::get_click_mask); + ObjectTypeDB::bind_method(_MD("get_scale"),&TextureButton::get_scale); + ObjectTypeDB::bind_method(_MD("get_modulate"),&TextureButton::get_modulate); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_pressed_texture"), _SCS("get_pressed_texture")); @@ -139,6 +163,8 @@ void TextureButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ; + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale")); + ADD_PROPERTY(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate")); } @@ -206,6 +232,29 @@ void TextureButton::set_focused_texture(const Ref<Texture>& p_focused) { focused = p_focused; }; +void TextureButton::set_scale(Size2 p_scale) { + + scale=p_scale; + minimum_size_changed(); + update(); +} + +Size2 TextureButton::get_scale() const{ + + return scale; +} + +void TextureButton::set_modulate(const Color& p_modulate) { + modulate=p_modulate; + update(); +} + +Color TextureButton::get_modulate() const { + return modulate; +} + TextureButton::TextureButton() { + scale=Size2(1.0, 1.0); + modulate=Color(1,1,1); } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index d186966cb1..94bc53b3ff 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -41,6 +41,8 @@ class TextureButton : public BaseButton { Ref<Texture> disabled; Ref<Texture> focused; Ref<BitMap> click_mask; + Size2 scale; + Color modulate; protected: @@ -66,6 +68,11 @@ public: Ref<Texture> get_focused_texture() const; Ref<BitMap> get_click_mask() const; + void set_scale(Size2 p_scale); + Size2 get_scale() const; + + void set_modulate(const Color& p_modulate); + Color get_modulate() const; TextureButton(); }; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index a39c61ecac..035dbb8cc4 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1499,7 +1499,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ case TreeItem::CELL_MODE_STRING: { //nothing in particular - if (select_mode==SELECT_MULTI && (get_scene()->get_last_event_id() == focus_in_id || !already_cursor)) { + if (select_mode==SELECT_MULTI && (get_tree()->get_last_event_id() == focus_in_id || !already_cursor)) { bring_up_editor=false; } @@ -1575,7 +1575,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ editor_text=String::num( p_item->cells[col].val, Math::decimals( p_item->cells[col].step ) ); bring_up_value_editor=false; - if (select_mode==SELECT_MULTI && get_scene()->get_last_event_id() == focus_in_id) + if (select_mode==SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id) bring_up_editor=false; } @@ -1693,6 +1693,13 @@ void Tree::text_editor_enter(String p_text) { case TreeItem::CELL_MODE_RANGE: { c.val=p_text.to_double(); + if (c.step>0) + c.val=Math::stepify(c.val,c.step); + if (c.val<c.min) + c.val=c.min; + else if (c.val>c.max) + c.val=c.max; + //popup_edited_item->edited_signal.call( popup_edited_item_col ); } break; default: { ERR_FAIL(); } @@ -2343,7 +2350,7 @@ void Tree::_notification(int p_what) { if (p_what==NOTIFICATION_FOCUS_ENTER) { - focus_in_id=get_scene()->get_last_event_id(); + focus_in_id=get_tree()->get_last_event_id(); } if (p_what==NOTIFICATION_MOUSE_EXIT) { @@ -2353,7 +2360,7 @@ void Tree::_notification(int p_what) { } } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { update_cache();; } @@ -2465,6 +2472,10 @@ void Tree::_notification(int p_what) { } } + if (p_what==NOTIFICATION_THEME_CHANGED) { + update_cache(); + } + } @@ -2811,7 +2822,7 @@ int Tree::get_item_offset(TreeItem *p_item) const { void Tree::ensure_cursor_is_visible() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; TreeItem *selected = get_selected(); diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 9a1c070529..050fd890f4 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -32,10 +32,10 @@ void VideoPlayer::_notification(int p_notification) { switch (p_notification) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { //set_idle_process(false); //don't annoy - if (stream.is_valid() && autoplay && !get_scene()->is_editor_hint()) + if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) play(); } break; @@ -45,20 +45,15 @@ void VideoPlayer::_notification(int p_notification) { return; if (paused) return; + if (!stream->is_playing()) + return; - stream->update(get_scene()->get_idle_process_time()); - while (stream->get_pending_frame_count()) { - - Image img = stream->pop_frame(); - if (texture->get_width() == 0) { - texture->create(img.get_width(),img.get_height(),img.get_format(),Texture::FLAG_VIDEO_SURFACE|Texture::FLAG_FILTER); - update(); - minimum_size_changed(); - } else { - - if (stream->get_pending_frame_count() == 0) - texture->set_data(img); - }; + stream->update(get_tree()->get_idle_process_time()); + int prev_width = texture->get_width(); + stream->pop_frame(texture); + if (prev_width == 0) { + update(); + minimum_size_changed(); }; } break; @@ -123,7 +118,7 @@ Ref<VideoStream> VideoPlayer::get_stream() const { void VideoPlayer::play() { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); if (stream.is_null()) return; stream->play(); @@ -132,7 +127,7 @@ void VideoPlayer::play() { void VideoPlayer::stop() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (stream.is_null()) return; @@ -197,7 +192,7 @@ String VideoPlayer::get_stream_name() const { return stream->get_name(); }; -float VideoPlayer::get_pos() const { +float VideoPlayer::get_stream_pos() const { if (stream.is_null()) return 0; @@ -236,7 +231,7 @@ void VideoPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_stream_name"),&VideoPlayer::get_stream_name); - ObjectTypeDB::bind_method(_MD("get_pos"),&VideoPlayer::get_pos); + ObjectTypeDB::bind_method(_MD("get_stream_pos"),&VideoPlayer::get_stream_pos); ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&VideoPlayer::set_autoplay); ObjectTypeDB::bind_method(_MD("has_autoplay"),&VideoPlayer::has_autoplay); @@ -257,9 +252,9 @@ void VideoPlayer::_bind_methods() { VideoPlayer::VideoPlayer() { volume=1; - loops=false; - paused=false; - autoplay=false; + loops = false; + paused = false; + autoplay = false; expand = true; loops = false; }; diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index db5f9a58a6..3eb629ced5 100644 --- a/scene/gui/video_player.h +++ b/scene/gui/video_player.h @@ -77,7 +77,7 @@ public: float get_volume_db() const; String get_stream_name() const; - float get_pos() const; + float get_stream_pos() const; void set_autoplay(bool p_vol); bool has_autoplay() const; diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index b0fcf9717b..16c2ec9706 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -131,14 +131,55 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina uint32_t flags=0; - if (bool(GLOBAL_DEF("image_loader/filter",true))) + + FileAccess *f2 = FileAccess::open(p_path+".flags",FileAccess::READ); + Map<String,bool> flags_found; + if (f2) { + + while(!f2->eof_reached()) { + String l2 = f2->get_line(); + int eqpos = l2.find("="); + if (eqpos!=-1) { + String flag=l2.substr(0,eqpos).strip_edges(); + String val=l2.substr(eqpos+1,l2.length()).strip_edges().to_lower(); + flags_found[flag]=(val=="true" || val=="1")?true:false; + } + } + memdelete(f2); + } + + + if (flags_found.has("filter")) { + if (flags_found["filter"]) + flags|=Texture::FLAG_FILTER; + } else if (bool(GLOBAL_DEF("image_loader/filter",true))) { flags|=Texture::FLAG_FILTER; - if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true))) + } + + + if (flags_found.has("gen_mipmaps")) { + if (flags_found["gen_mipmaps"]) + flags|=Texture::FLAG_MIPMAPS; + } else if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true))) { flags|=Texture::FLAG_MIPMAPS; - if (bool(GLOBAL_DEF("image_loader/repeat",false))) + } + + if (flags_found.has("repeat")) { + if (flags_found["repeat"]) + flags|=Texture::FLAG_REPEAT; + } else if (bool(GLOBAL_DEF("image_loader/repeat",true))) { flags|=Texture::FLAG_REPEAT; + } + if (flags_found.has("anisotropic")) { + if (flags_found["anisotropic"]) + flags|=Texture::FLAG_ANISOTROPIC_FILTER; + } + if (flags_found.has("tolinear")) { + if (flags_found["tolinear"]) + flags|=Texture::FLAG_CONVERT_TO_LINEAR; + } if (debug_load_times) begtime=OS::get_singleton()->get_ticks_usec(); diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 5006f55daf..ae842577a9 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -144,7 +144,7 @@ void CanvasLayer::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { Node *n = this; vp=NULL; @@ -169,7 +169,7 @@ void CanvasLayer::_notification(int p_what) { } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { VisualServer::get_singleton()->viewport_remove_canvas(viewport,canvas->get_canvas()); viewport=RID(); @@ -180,7 +180,7 @@ void CanvasLayer::_notification(int p_what) { Size2 CanvasLayer::get_viewport_size() const { - if (!is_inside_scene()) + if (!is_inside_tree()) return Size2(1,1); Rect2 r = vp->get_visible_rect(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index e511a057c5..fbdc87a7cc 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -64,7 +64,7 @@ void Node::_notification(int p_notification) { } } break; - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (data.pause_mode==PAUSE_MODE_INHERIT) { @@ -83,12 +83,12 @@ void Node::_notification(int p_notification) { if (data.unhandled_key_input) add_to_group("_vp_unhandled_key_input"+itos(get_viewport()->get_instance_ID())); - get_scene()->node_count++; + get_tree()->node_count++; } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { - get_scene()->node_count--; + get_tree()->node_count--; if (data.input) remove_from_group("_vp_input"+itos(get_viewport()->get_instance_ID())); if (data.unhandled_input) @@ -104,7 +104,7 @@ void Node::_notification(int p_notification) { Variant::CallError err; get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_ready,NULL,0); } - //emit_signal(SceneStringNames::get_singleton()->enter_scene); + //emit_signal(SceneStringNames::get_singleton()->enter_tree); } break; case NOTIFICATION_POSTINITIALIZE: { @@ -150,11 +150,11 @@ void Node::_propagate_ready() { } -void Node::_propagate_enter_scene() { - // this needs to happen to all childs before any ENTER_SCENE +void Node::_propagate_enter_tree() { + // this needs to happen to all childs before any enter_tree if (data.parent) { - data.scene=data.parent->data.scene; + data.tree=data.parent->data.tree; data.depth=data.parent->data.depth+1; } else { @@ -165,25 +165,25 @@ void Node::_propagate_enter_scene() { if (!data.viewport) data.viewport = data.parent->data.viewport; - data.inside_scene=true; + data.inside_tree=true; const StringName *K=NULL; while ((K=data.grouped.next(K))) { - data.scene->add_to_group(*K,this); + data.tree->add_to_group(*K,this); } - notification(NOTIFICATION_ENTER_SCENE); + notification(NOTIFICATION_ENTER_TREE); if (get_script_instance()) { Variant::CallError err; - get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_enter_scene,NULL,0); + get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_enter_tree,NULL,0); } - emit_signal(SceneStringNames::get_singleton()->enter_scene); + emit_signal(SceneStringNames::get_singleton()->enter_tree); data.blocked++; @@ -191,8 +191,8 @@ void Node::_propagate_enter_scene() { for (int i=0;i<data.children.size();i++) { - if (!data.children[i]->is_inside_scene()) // could have been added in ENTER_SCENE - data.children[i]->_propagate_enter_scene(); + if (!data.children[i]->is_inside_tree()) // could have been added in enter_tree + data.children[i]->_propagate_enter_tree(); } data.blocked--; @@ -201,7 +201,7 @@ void Node::_propagate_enter_scene() { -void Node::_propagate_exit_scene() { +void Node::_propagate_exit_tree() { //block while removing children @@ -209,7 +209,7 @@ void Node::_propagate_exit_scene() { for (int i=data.children.size()-1;i>=0;i--) { - data.children[i]->_propagate_exit_scene(); + data.children[i]->_propagate_exit_tree(); } data.blocked--; @@ -217,29 +217,29 @@ void Node::_propagate_exit_scene() { if (get_script_instance()) { Variant::CallError err; - get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_scene,NULL,0); + get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_exit_tree,NULL,0); } - emit_signal(SceneStringNames::get_singleton()->exit_scene); + emit_signal(SceneStringNames::get_singleton()->exit_tree); - notification(NOTIFICATION_EXIT_SCENE,true); - if (data.scene) - data.scene->node_removed(this); + notification(NOTIFICATION_EXIT_TREE,true); + if (data.tree) + data.tree->node_removed(this); // exit groups const StringName *K=NULL; while ((K=data.grouped.next(K))) { - data.scene->remove_from_group(*K,this); + data.tree->remove_from_group(*K,this); } data.viewport = NULL; - if (data.scene) - data.scene->tree_changed(); + if (data.tree) + data.tree->tree_changed(); - data.inside_scene=false; - data.scene=NULL; + data.inside_tree=false; + data.tree=NULL; data.depth=-1; } @@ -260,8 +260,8 @@ void Node::move_child(Node *p_child,int p_pos) { data.children.remove( p_child->data.pos ); data.children.insert( p_pos, p_child ); - if (data.scene) { - data.scene->tree_changed(); + if (data.tree) { + data.tree->tree_changed(); } data.blocked++; @@ -271,6 +271,7 @@ void Node::move_child(Node *p_child,int p_pos) { data.children[i]->data.pos=i; } // notification second + move_child_notify(p_child); for (int i=0;i<data.children.size();i++) { data.children[i]->notification( NOTIFICATION_MOVED_IN_PARENT ); @@ -310,6 +311,11 @@ void Node::remove_child_notify(Node *p_child) { // to be used when not wanted } +void Node::move_child_notify(Node *p_child) { + + // to be used when not wanted +} + void Node::set_fixed_process(bool p_process) { if (data.fixed_process==p_process) @@ -333,7 +339,7 @@ void Node::set_pause_mode(PauseMode p_mode) { bool prev_inherits=data.pause_mode==PAUSE_MODE_INHERIT; data.pause_mode=p_mode; - if (!is_inside_scene()) + if (!is_inside_tree()) return; //pointless if ((data.pause_mode==PAUSE_MODE_INHERIT) == prev_inherits) return; ///nothing changed @@ -372,10 +378,12 @@ void Node::_propagate_pause_owner(Node*p_owner) { bool Node::can_process() const { - ERR_FAIL_COND_V( !is_inside_scene(), false ); + ERR_FAIL_COND_V( !is_inside_tree(), false ); - if (get_scene()->is_paused()) { + if (get_tree()->is_paused()) { + if (data.pause_mode==PAUSE_MODE_STOP) + return false; if (data.pause_mode==PAUSE_MODE_PROCESS) return true; if (data.pause_mode==PAUSE_MODE_INHERIT) { @@ -385,6 +393,9 @@ bool Node::can_process() const { if (data.pause_owner->data.pause_mode==PAUSE_MODE_PROCESS) return true; + + if (data.pause_owner->data.pause_mode==PAUSE_MODE_STOP) + return false; } } @@ -395,8 +406,8 @@ bool Node::can_process() const { float Node::get_fixed_process_delta_time() const { - if (data.scene) - return data.scene->get_fixed_process_time(); + if (data.tree) + return data.tree->get_fixed_process_time(); else return 0; } @@ -419,8 +430,8 @@ void Node::set_process(bool p_idle_process) { float Node::get_process_delta_time() const { - if (data.scene) - return data.scene->get_idle_process_time(); + if (data.tree) + return data.tree->get_idle_process_time(); else return 0; } @@ -442,7 +453,7 @@ void Node::set_process_input(bool p_enable) { return; data.input=p_enable; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (p_enable) @@ -462,7 +473,7 @@ void Node::set_process_unhandled_input(bool p_enable) { if (p_enable==data.unhandled_input) return; data.unhandled_input=p_enable; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (p_enable) @@ -482,7 +493,7 @@ void Node::set_process_unhandled_key_input(bool p_enable) { if (p_enable==data.unhandled_key_input) return; data.unhandled_key_input=p_enable; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if (p_enable) @@ -520,10 +531,10 @@ void Node::set_name(const String& p_name) { data.parent->_validate_child_name(this); } - if (is_inside_scene()) { + if (is_inside_tree()) { emit_signal("renamed"); - get_scene()->tree_changed(); + get_tree()->tree_changed(); } } @@ -630,8 +641,8 @@ void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) { data.children.push_back( p_child ); p_child->data.parent=this; - if (data.scene) { - p_child->_set_scene(data.scene); + if (data.tree) { + p_child->_set_tree(data.tree); } /* Notify */ @@ -719,7 +730,7 @@ void Node::remove_child(Node *p_child) { //if (data.scene) { does not matter - p_child->_set_scene(NULL); + p_child->_set_tree(NULL); //} remove_child_notify(p_child); @@ -755,7 +766,7 @@ Node *Node::get_child(int p_index) const { Node *Node::_get_node(const NodePath& p_path) const { - ERR_FAIL_COND_V( !data.inside_scene && p_path.is_absolute(), NULL ); + ERR_FAIL_COND_V( !data.inside_tree && p_path.is_absolute(), NULL ); Node *current=NULL; Node *root=NULL; @@ -851,8 +862,8 @@ bool Node::is_a_parent_of(const Node *p_node) const { bool Node::is_greater_than(const Node *p_node) const { ERR_FAIL_NULL_V(p_node,false); - ERR_FAIL_COND_V( !data.inside_scene, false ); - ERR_FAIL_COND_V( !p_node->data.inside_scene, false ); + ERR_FAIL_COND_V( !data.inside_tree, false ); + ERR_FAIL_COND_V( !p_node->data.inside_tree, false ); ERR_FAIL_COND_V( data.depth<0, false); ERR_FAIL_COND_V( p_node->data.depth<0, false); @@ -1023,7 +1034,7 @@ NodePath Node::get_path_to(const Node *p_node) const { NodePath Node::get_path() const { - ERR_FAIL_COND_V(!is_inside_scene(),NodePath()); + ERR_FAIL_COND_V(!is_inside_tree(),NodePath()); const Node *n = this; Vector<StringName> path; @@ -1052,8 +1063,8 @@ void Node::add_to_group(const StringName& p_identifier,bool p_persistent) { GroupData gd; - if (data.scene) - data.scene->add_to_group(p_identifier,this); + if (data.tree) + data.tree->add_to_group(p_identifier,this); gd.persistent=p_persistent; @@ -1070,8 +1081,8 @@ void Node::remove_from_group(const StringName& p_identifier) { ERR_FAIL_COND(!g); - if (data.scene) - data.scene->remove_from_group(p_identifier,this); + if (data.tree) + data.tree->remove_from_group(p_identifier,this); data.grouped.erase(p_identifier); @@ -1131,7 +1142,7 @@ void Node::_propagate_reverse_notification(int p_notification) { void Node::_propagate_deferred_notification(int p_notification, bool p_reverse) { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); data.blocked++; @@ -1234,7 +1245,7 @@ void Node::generate_instance_state() { for( List<PropertyInfo>::Element *E=properties.front();E;E=E->next() ) { PropertyInfo &pi=E->get(); - if (!(pi.usage&PROPERTY_USAGE_EDITOR) || !(pi.usage&PROPERTY_USAGE_STORAGE)) + if ((pi.usage&PROPERTY_USAGE_NO_INSTANCE_STATE) || !(pi.usage&PROPERTY_USAGE_EDITOR) || !(pi.usage&PROPERTY_USAGE_STORAGE)) continue; data.instance_state[pi.name]=get(pi.name); @@ -1424,6 +1435,20 @@ Node *Node::duplicate_and_reown(const Map<Node*,Node*>& p_reown_map) const { node->set_name(get_name()); + List<PropertyInfo> plist; + + get_property_list(&plist); + + for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { + + if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) + continue; + String name = E->get().name; + node->set( name, get(name) ); + + } + + for(int i=0;i<get_child_count();i++) { get_child(i)->_duplicate_and_reown(node,p_reown_map); @@ -1610,29 +1635,29 @@ Node *Node::get_node_and_resource(const NodePath& p_path,RES& r_res) const { return node; } -void Node::_set_scene(SceneMainLoop *p_scene) { +void Node::_set_tree(SceneTree *p_tree) { - SceneMainLoop *tree_changed_a=NULL; - SceneMainLoop *tree_changed_b=NULL; + SceneTree *tree_changed_a=NULL; + SceneTree *tree_changed_b=NULL; // ERR_FAIL_COND(p_scene && data.parent && !data.parent->data.scene); //nobug if both are null - if (data.scene) { - _propagate_exit_scene(); + if (data.tree) { + _propagate_exit_tree(); - tree_changed_a=data.scene; + tree_changed_a=data.tree; } - data.scene=p_scene; + data.tree=p_tree; - if (data.scene) { + if (data.tree) { - _propagate_enter_scene(); + _propagate_enter_tree(); _propagate_ready(); //reverse_notification(NOTIFICATION_READY); - tree_changed_b=data.scene; + tree_changed_b=data.tree; } @@ -1650,7 +1675,7 @@ static void _Node_debug_sn(Object *p_obj) { if (!n) return; - if (n->is_inside_scene()) + if (n->is_inside_tree()) return; Node *p=n; @@ -1682,8 +1707,8 @@ void Node::print_stray_nodes() { void Node::queue_delete() { - ERR_FAIL_COND( !is_inside_scene() ); - get_scene()->queue_delete(this); + ERR_FAIL_COND( !is_inside_tree() ); + get_tree()->queue_delete(this); } Array Node::_get_children() const { @@ -1711,6 +1736,26 @@ NodePath Node::get_import_path() const { #endif +static void _add_nodes_to_options(const Node *p_base,const Node *p_node,List<String>*r_options) { + + if (p_node!=p_base && !p_node->get_owner()) + return; + String n = p_base->get_path_to(p_node); + r_options->push_back("\""+n+"\""); + for(int i=0;i<p_node->get_child_count();i++) { + _add_nodes_to_options(p_base,p_node->get_child(i),r_options); + } +} + +void Node::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String pf=p_function; + if ((pf=="has_node" || pf=="get_node") && p_idx==0) { + + _add_nodes_to_options(this,this,r_options); + } + Object::get_argument_options(p_function,p_idx,r_options); +} void Node::_bind_methods() { @@ -1728,7 +1773,7 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_node_and_resource","path"),&Node::has_node_and_resource); ObjectTypeDB::bind_method(_MD("get_node_and_resource","path"),&Node::_get_node_and_resource); - ObjectTypeDB::bind_method(_MD("is_inside_scene"),&Node::is_inside_scene); + ObjectTypeDB::bind_method(_MD("is_inside_tree"),&Node::is_inside_tree); ObjectTypeDB::bind_method(_MD("is_a_parent_of","node:Node"),&Node::is_a_parent_of); ObjectTypeDB::bind_method(_MD("is_greater_than","node:Node"),&Node::is_greater_than); ObjectTypeDB::bind_method(_MD("get_path"),&Node::get_path); @@ -1765,7 +1810,7 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("print_stray_nodes"),&Node::_print_stray_nodes); ObjectTypeDB::bind_method(_MD("get_position_in_parent"),&Node::get_position_in_parent); - ObjectTypeDB::bind_method(_MD("get_scene:SceneMainLoop"),&Node::get_scene); + ObjectTypeDB::bind_method(_MD("get_tree:SceneTree"),&Node::get_tree); ObjectTypeDB::bind_method(_MD("duplicate:Node"),&Node::duplicate); ObjectTypeDB::bind_method(_MD("replace_by","node:Node","keep_data"),&Node::replace_by,DEFVAL(false)); @@ -1780,8 +1825,8 @@ void Node::_bind_methods() { #endif - BIND_CONSTANT( NOTIFICATION_ENTER_SCENE ); - BIND_CONSTANT( NOTIFICATION_EXIT_SCENE ); + BIND_CONSTANT( NOTIFICATION_ENTER_TREE ); + BIND_CONSTANT( NOTIFICATION_EXIT_TREE ); BIND_CONSTANT( NOTIFICATION_MOVED_IN_PARENT ); //BIND_CONSTANT( NOTIFICATION_PARENT_DECONFIGURED ); BIND_CONSTANT( NOTIFICATION_READY ); @@ -1798,8 +1843,8 @@ void Node::_bind_methods() { BIND_CONSTANT( PAUSE_MODE_PROCESS ); ADD_SIGNAL( MethodInfo("renamed") ); - ADD_SIGNAL( MethodInfo("enter_scene") ); - ADD_SIGNAL( MethodInfo("exit_scene") ); + ADD_SIGNAL( MethodInfo("enter_tree") ); + ADD_SIGNAL( MethodInfo("exit_tree") ); // ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/process" ),_SCS("set_process"),_SCS("is_processing") ); // ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/fixed_process" ), _SCS("set_fixed_process"),_SCS("is_fixed_processing") ); @@ -1809,8 +1854,8 @@ void Node::_bind_methods() { BIND_VMETHOD( MethodInfo("_process",PropertyInfo(Variant::REAL,"delta")) ); BIND_VMETHOD( MethodInfo("_fixed_process",PropertyInfo(Variant::REAL,"delta")) ); - BIND_VMETHOD( MethodInfo("_enter_scene") ); - BIND_VMETHOD( MethodInfo("_exit_scene") ); + BIND_VMETHOD( MethodInfo("_enter_tree") ); + BIND_VMETHOD( MethodInfo("_exit_tree") ); BIND_VMETHOD( MethodInfo("_ready") ); BIND_VMETHOD( MethodInfo("_input",PropertyInfo(Variant::INPUT_EVENT,"event")) ); BIND_VMETHOD( MethodInfo("_unhandled_input",PropertyInfo(Variant::INPUT_EVENT,"event")) ); @@ -1827,10 +1872,10 @@ Node::Node() { data.depth=-1; data.blocked=0; data.parent=NULL; - data.scene=NULL; + data.tree=NULL; data.fixed_process=false; data.idle_process=false; - data.inside_scene=false; + data.inside_tree=false; data.owner=NULL; data.OW=NULL; diff --git a/scene/main/node.h b/scene/main/node.h index f1ecf497e0..47f49eb625 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -80,8 +80,8 @@ private: int depth; int blocked; // safeguard that throws an error when attempting to modify the tree in a harmful way while being traversed. StringName name; - SceneMainLoop *scene; - bool inside_scene; + SceneTree *tree; + bool inside_tree; #ifdef TOOLS_ENABLED NodePath import_path; //path used when imported, used by scene editors to keep tracking #endif @@ -118,9 +118,9 @@ private: void _propagate_reverse_notification(int p_notification); void _propagate_deferred_notification(int p_notification, bool p_reverse); - void _propagate_enter_scene(); + void _propagate_enter_tree(); void _propagate_ready(); - void _propagate_exit_scene(); + void _propagate_exit_tree(); void _propagate_validate_owner(); void _print_stray_nodes(); void _propagate_pause_owner(Node*p_owner); @@ -130,9 +130,9 @@ private: Array _get_children() const; Array _get_groups() const; -friend class SceneMainLoop; +friend class SceneTree; - void _set_scene(SceneMainLoop *p_scene); + void _set_tree(SceneTree *p_tree); protected: void _block() { data.blocked++; } @@ -142,6 +142,7 @@ protected: virtual void add_child_notify(Node *p_child); virtual void remove_child_notify(Node *p_child); + virtual void move_child_notify(Node *p_child); void remove_and_delete_child(Node *p_child); void _propagate_replace_owner(Node *p_owner,Node* p_by_owner); @@ -158,8 +159,8 @@ public: enum { // you can make your own, but don't use the same numbers as other notifications in other nodes - NOTIFICATION_ENTER_SCENE=10, - NOTIFICATION_EXIT_SCENE =11, + NOTIFICATION_ENTER_TREE=10, + NOTIFICATION_EXIT_TREE =11, NOTIFICATION_MOVED_IN_PARENT =12, NOTIFICATION_READY=13, //NOTIFICATION_PARENT_DECONFIGURED =15, - it's confusing, it's going away @@ -187,9 +188,9 @@ public: Node *get_node_and_resource(const NodePath& p_path,RES& r_res) const; Node *get_parent() const; - _FORCE_INLINE_ SceneMainLoop *get_scene() const { ERR_FAIL_COND_V( !data.scene, NULL ); return data.scene; } + _FORCE_INLINE_ SceneTree *get_tree() const { ERR_FAIL_COND_V( !data.tree, NULL ); return data.tree; } - _FORCE_INLINE_ bool is_inside_scene() const { return data.inside_scene; } + _FORCE_INLINE_ bool is_inside_tree() const { return data.inside_tree; } bool is_a_parent_of(const Node *p_node) const; bool is_greater_than(const Node *p_node) const; @@ -283,6 +284,7 @@ public: NodePath get_import_path() const; #endif + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; } diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index c51974167d..8e2dc93288 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -43,13 +43,13 @@ #include "viewport.h" -void SceneMainLoop::tree_changed() { +void SceneTree::tree_changed() { tree_version++; emit_signal(tree_changed_name); } -void SceneMainLoop::node_removed(Node *p_node) { +void SceneTree::node_removed(Node *p_node) { emit_signal(node_removed_name,p_node); if (call_lock>0) @@ -59,7 +59,7 @@ void SceneMainLoop::node_removed(Node *p_node) { } -void SceneMainLoop::add_to_group(const StringName& p_group, Node *p_node) { +void SceneTree::add_to_group(const StringName& p_group, Node *p_node) { Map<StringName,Group>::Element *E=group_map.find(p_group); if (!E) { @@ -74,7 +74,7 @@ void SceneMainLoop::add_to_group(const StringName& p_group, Node *p_node) { E->get().last_tree_version=0; } -void SceneMainLoop::remove_from_group(const StringName& p_group, Node *p_node) { +void SceneTree::remove_from_group(const StringName& p_group, Node *p_node) { Map<StringName,Group>::Element *E=group_map.find(p_group); ERR_FAIL_COND(!E); @@ -85,7 +85,7 @@ void SceneMainLoop::remove_from_group(const StringName& p_group, Node *p_node) { group_map.erase(E); } -void SceneMainLoop::_flush_transform_notifications() { +void SceneTree::_flush_transform_notifications() { SelfList<Node>* n = xform_change_list.first(); while(n) { @@ -98,7 +98,7 @@ void SceneMainLoop::_flush_transform_notifications() { } } -void SceneMainLoop::_flush_ugc() { +void SceneTree::_flush_ugc() { ugc_locked=true; @@ -118,7 +118,7 @@ void SceneMainLoop::_flush_ugc() { ugc_locked=false; } -void SceneMainLoop::_update_group_order(Group& g) { +void SceneTree::_update_group_order(Group& g) { if (g.last_tree_version==tree_version) return; @@ -134,7 +134,7 @@ void SceneMainLoop::_update_group_order(Group& g) { } -void SceneMainLoop::call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,VARIANT_ARG_DECLARE) { +void SceneTree::call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,VARIANT_ARG_DECLARE) { Map<StringName,Group>::Element *E=group_map.find(p_group); if (!E) @@ -216,7 +216,7 @@ void SceneMainLoop::call_group(uint32_t p_call_flags,const StringName& p_group,c call_skip.clear(); } -void SceneMainLoop::notify_group(uint32_t p_call_flags,const StringName& p_group,int p_notification) { +void SceneTree::notify_group(uint32_t p_call_flags,const StringName& p_group,int p_notification) { Map<StringName,Group>::Element *E=group_map.find(p_group); if (!E) @@ -266,7 +266,7 @@ void SceneMainLoop::notify_group(uint32_t p_call_flags,const StringName& p_group call_skip.clear(); } -void SceneMainLoop::set_group(uint32_t p_call_flags,const StringName& p_group,const String& p_name,const Variant& p_value) { +void SceneTree::set_group(uint32_t p_call_flags,const StringName& p_group,const String& p_name,const Variant& p_value) { Map<StringName,Group>::Element *E=group_map.find(p_group); if (!E) @@ -316,12 +316,12 @@ void SceneMainLoop::set_group(uint32_t p_call_flags,const StringName& p_group,co call_skip.clear(); } -void SceneMainLoop::set_input_as_handled() { +void SceneTree::set_input_as_handled() { input_handled=true; } -void SceneMainLoop::input_text( const String& p_text ) { +void SceneTree::input_text( const String& p_text ) { root_lock++; @@ -330,16 +330,20 @@ void SceneMainLoop::input_text( const String& p_text ) { } -void SceneMainLoop::input_event( const InputEvent& p_event ) { +void SceneTree::input_event( const InputEvent& p_event ) { + if (is_editor_hint() && (p_event.type==InputEvent::JOYSTICK_MOTION || p_event.type==InputEvent::JOYSTICK_BUTTON)) + return; //avoid joy input on editor + root_lock++; - last_id=p_event.ID; + //last_id=p_event.ID; input_handled=false; InputEvent ev = p_event; + ev.ID=++last_id; //this should work better #if 0 switch(ev.type) { @@ -393,7 +397,7 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) { #endif - MainLoop::input_event(p_event); + MainLoop::input_event(ev); #if 0 _call_input_pause("input","_input",ev); @@ -415,7 +419,7 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) { //transform for the rest #else - call_group(GROUP_CALL_REALTIME,"_viewports","_vp_input",p_event); //special one for GUI, as controls use their own process check + call_group(GROUP_CALL_REALTIME,"_viewports","_vp_input",ev); //special one for GUI, as controls use their own process check #endif if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote() && ev.type==InputEvent::KEY && ev.key.pressed && !ev.key.echo && ev.key.scancode==KEY_F8) { @@ -440,7 +444,7 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) { } #else - call_group(GROUP_CALL_REALTIME,"_viewports","_vp_unhandled_input",p_event); //special one for GUI, as controls use their own process check + call_group(GROUP_CALL_REALTIME,"_viewports","_vp_unhandled_input",ev); //special one for GUI, as controls use their own process check #endif input_handled=true; @@ -455,7 +459,7 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) { } -void SceneMainLoop::init() { +void SceneTree::init() { //_quit=false; accept_quit=true; @@ -466,12 +470,12 @@ void SceneMainLoop::init() { editor_hint=false; pause=false; - root->_set_scene(this); + root->_set_tree(this); MainLoop::init(); } -bool SceneMainLoop::iteration(float p_time) { +bool SceneTree::iteration(float p_time) { root_lock++; @@ -496,7 +500,7 @@ bool SceneMainLoop::iteration(float p_time) { return _quit; } -bool SceneMainLoop::idle(float p_time){ +bool SceneTree::idle(float p_time){ // print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage())); @@ -538,7 +542,7 @@ bool SceneMainLoop::idle(float p_time){ return _quit; } -void SceneMainLoop::finish() { +void SceneTree::finish() { _flush_delete_queue(); @@ -549,7 +553,7 @@ void SceneMainLoop::finish() { MainLoop::finish(); if (root) { - root->_set_scene(NULL); + root->_set_tree(NULL); memdelete(root); //delete root } @@ -564,12 +568,12 @@ void SceneMainLoop::finish() { } -void SceneMainLoop::quit() { +void SceneTree::quit() { _quit=true; } -void SceneMainLoop::_notification(int p_notification) { +void SceneTree::_notification(int p_notification) { @@ -602,22 +606,22 @@ void SceneMainLoop::_notification(int p_notification) { }; -void SceneMainLoop::set_auto_accept_quit(bool p_enable) { +void SceneTree::set_auto_accept_quit(bool p_enable) { accept_quit=p_enable; } -void SceneMainLoop::set_editor_hint(bool p_enabled) { +void SceneTree::set_editor_hint(bool p_enabled) { editor_hint=p_enabled; } -bool SceneMainLoop::is_editor_hint() const { +bool SceneTree::is_editor_hint() const { return editor_hint; } -void SceneMainLoop::set_pause(bool p_enabled) { +void SceneTree::set_pause(bool p_enabled) { if (p_enabled==pause) return; @@ -628,12 +632,12 @@ void SceneMainLoop::set_pause(bool p_enabled) { get_root()->propagate_notification(p_enabled ? Node::NOTIFICATION_PAUSED : Node::NOTIFICATION_UNPAUSED); } -bool SceneMainLoop::is_paused() const { +bool SceneTree::is_paused() const { return pause; } -void SceneMainLoop::_call_input_pause(const StringName& p_group,const StringName& p_method,const InputEvent& p_input) { +void SceneTree::_call_input_pause(const StringName& p_group,const StringName& p_method,const InputEvent& p_input) { Map<StringName,Group>::Element *E=group_map.find(p_group); if (!E) @@ -678,7 +682,7 @@ void SceneMainLoop::_call_input_pause(const StringName& p_group,const StringName call_skip.clear(); } -void SceneMainLoop::_notify_group_pause(const StringName& p_group,int p_notification) { +void SceneTree::_notify_group_pause(const StringName& p_group,int p_notification) { Map<StringName,Group>::Element *E=group_map.find(p_group); if (!E) @@ -728,13 +732,13 @@ void SceneMainLoop::_update_listener_2d() { } */ -uint32_t SceneMainLoop::get_last_event_id() const { +uint32_t SceneTree::get_last_event_id() const { return last_id; } -Variant SceneMainLoop::_call_group(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { +Variant SceneTree::_call_group(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { r_error.error=Variant::CallError::CALL_OK; @@ -759,13 +763,13 @@ Variant SceneMainLoop::_call_group(const Variant** p_args, int p_argcount, Varia } -int64_t SceneMainLoop::get_frame() const { +int64_t SceneTree::get_frame() const { return current_frame; } -Array SceneMainLoop::_get_nodes_in_group(const StringName& p_group) { +Array SceneTree::_get_nodes_in_group(const StringName& p_group) { Array ret; Map<StringName,Group>::Element *E=group_map.find(p_group); @@ -788,7 +792,7 @@ Array SceneMainLoop::_get_nodes_in_group(const StringName& p_group) { return ret; } -void SceneMainLoop::get_nodes_in_group(const StringName& p_group,List<Node*> *p_list) { +void SceneTree::get_nodes_in_group(const StringName& p_group,List<Node*> *p_list) { Map<StringName,Group>::Element *E=group_map.find(p_group); @@ -818,9 +822,9 @@ static void _fill_array(Node *p_node, Array& array, int p_level) { } } -void SceneMainLoop::_debugger_request_tree(void *self) { +void SceneTree::_debugger_request_tree(void *self) { - SceneMainLoop *sml = (SceneMainLoop *)self; + SceneTree *sml = (SceneTree *)self; Array arr; _fill_array(sml->root,arr,0); @@ -828,7 +832,7 @@ void SceneMainLoop::_debugger_request_tree(void *self) { } -void SceneMainLoop::_flush_delete_queue() { +void SceneTree::_flush_delete_queue() { _THREAD_SAFE_METHOD_ @@ -842,21 +846,22 @@ void SceneMainLoop::_flush_delete_queue() { } } -void SceneMainLoop::queue_delete(Object *p_object) { +void SceneTree::queue_delete(Object *p_object) { _THREAD_SAFE_METHOD_ ERR_FAIL_NULL(p_object); + p_object->_is_queued_for_deletion = true; delete_queue.push_back(p_object->get_instance_ID()); } -int SceneMainLoop::get_node_count() const { +int SceneTree::get_node_count() const { return node_count; } -void SceneMainLoop::_update_root_rect() { +void SceneTree::_update_root_rect() { if (stretch_mode==STRETCH_MODE_DISABLED) { @@ -959,7 +964,7 @@ void SceneMainLoop::_update_root_rect() { } -void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize) { +void SceneTree::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize) { stretch_mode=p_mode; stretch_aspect=p_aspect; @@ -969,50 +974,50 @@ void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect #ifdef TOOLS_ENABLED -void SceneMainLoop::set_edited_scene_root(Node *p_node) { +void SceneTree::set_edited_scene_root(Node *p_node) { edited_scene_root=p_node; } -Node *SceneMainLoop::get_edited_scene_root() const { +Node *SceneTree::get_edited_scene_root() const { return edited_scene_root; } #endif -void SceneMainLoop::_bind_methods() { +void SceneTree::_bind_methods() { //ObjectTypeDB::bind_method(_MD("call_group","call_flags","group","method","arg1","arg2"),&SceneMainLoop::_call_group,DEFVAL(Variant()),DEFVAL(Variant())); - ObjectTypeDB::bind_method(_MD("notify_group","call_flags","group","notification"),&SceneMainLoop::notify_group); - ObjectTypeDB::bind_method(_MD("set_group","call_flags","group","property","value"),&SceneMainLoop::set_group); + ObjectTypeDB::bind_method(_MD("notify_group","call_flags","group","notification"),&SceneTree::notify_group); + ObjectTypeDB::bind_method(_MD("set_group","call_flags","group","property","value"),&SceneTree::set_group); - ObjectTypeDB::bind_method(_MD("get_nodes_in_group"),&SceneMainLoop::_get_nodes_in_group); + ObjectTypeDB::bind_method(_MD("get_nodes_in_group"),&SceneTree::_get_nodes_in_group); - ObjectTypeDB::bind_method(_MD("get_root:Viewport"),&SceneMainLoop::get_root); + ObjectTypeDB::bind_method(_MD("get_root:Viewport"),&SceneTree::get_root); - ObjectTypeDB::bind_method(_MD("set_auto_accept_quit","enabled"),&SceneMainLoop::set_auto_accept_quit); + ObjectTypeDB::bind_method(_MD("set_auto_accept_quit","enabled"),&SceneTree::set_auto_accept_quit); - ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneMainLoop::set_editor_hint); - ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneMainLoop::is_editor_hint); + ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneTree::set_editor_hint); + ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneTree::is_editor_hint); #ifdef TOOLS_ENABLED - ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneMainLoop::set_edited_scene_root); - ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneMainLoop::get_edited_scene_root); + ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneTree::set_edited_scene_root); + ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneTree::get_edited_scene_root); #endif - ObjectTypeDB::bind_method(_MD("set_pause","enable"),&SceneMainLoop::set_pause); - ObjectTypeDB::bind_method(_MD("is_paused"),&SceneMainLoop::is_paused); - ObjectTypeDB::bind_method(_MD("set_input_as_handled"),&SceneMainLoop::set_input_as_handled); + ObjectTypeDB::bind_method(_MD("set_pause","enable"),&SceneTree::set_pause); + ObjectTypeDB::bind_method(_MD("is_paused"),&SceneTree::is_paused); + ObjectTypeDB::bind_method(_MD("set_input_as_handled"),&SceneTree::set_input_as_handled); - ObjectTypeDB::bind_method(_MD("get_node_count"),&SceneMainLoop::get_node_count); - ObjectTypeDB::bind_method(_MD("get_frame"),&SceneMainLoop::get_frame); - ObjectTypeDB::bind_method(_MD("quit"),&SceneMainLoop::quit); + ObjectTypeDB::bind_method(_MD("get_node_count"),&SceneTree::get_node_count); + ObjectTypeDB::bind_method(_MD("get_frame"),&SceneTree::get_frame); + ObjectTypeDB::bind_method(_MD("quit"),&SceneTree::quit); - ObjectTypeDB::bind_method(_MD("set_screen_stretch","mode","aspect","minsize"),&SceneMainLoop::set_screen_stretch); + ObjectTypeDB::bind_method(_MD("set_screen_stretch","mode","aspect","minsize"),&SceneTree::set_screen_stretch); - ObjectTypeDB::bind_method(_MD("queue_delete","obj"),&SceneMainLoop::queue_delete); + ObjectTypeDB::bind_method(_MD("queue_delete","obj"),&SceneTree::queue_delete); MethodInfo mi; @@ -1026,7 +1031,7 @@ void SceneMainLoop::_bind_methods() { defargs.push_back(Variant()); } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneMainLoop::_call_group,mi,defargs); + ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi,defargs); ADD_SIGNAL( MethodInfo("tree_changed") ); ADD_SIGNAL( MethodInfo("node_removed",PropertyInfo( Variant::OBJECT, "node") ) ); @@ -1047,14 +1052,14 @@ void SceneMainLoop::_bind_methods() { } -SceneMainLoop::SceneMainLoop() { +SceneTree::SceneTree() { _quit=false; initialized=false; tree_version=1; fixed_process_time=1; idle_process_time=1; - last_id=0; + last_id=1; root=NULL; current_frame=0; tree_changed_name="tree_changed"; @@ -1095,7 +1100,7 @@ SceneMainLoop::SceneMainLoop() { } -SceneMainLoop::~SceneMainLoop() { +SceneTree::~SceneTree() { } diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 63a6468a73..31a823ab1a 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -41,16 +41,16 @@ */ -class SceneMainLoop; +class SceneTree; class Node; class Viewport; -class SceneMainLoop : public MainLoop { +class SceneTree : public MainLoop { _THREAD_SAFE_CLASS_ - OBJ_TYPE( SceneMainLoop, MainLoop ); + OBJ_TYPE( SceneTree, MainLoop ); public: @@ -226,19 +226,22 @@ public: void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize); + //void change_scene(const String& p_path); + //Node *get_loaded_scene(); + #ifdef TOOLS_ENABLED void set_edited_scene_root(Node *p_node); Node *get_edited_scene_root() const; #endif - SceneMainLoop(); - ~SceneMainLoop(); + SceneTree(); + ~SceneTree(); }; -VARIANT_ENUM_CAST( SceneMainLoop::StretchMode ); -VARIANT_ENUM_CAST( SceneMainLoop::StretchAspect ); +VARIANT_ENUM_CAST( SceneTree::StretchMode ); +VARIANT_ENUM_CAST( SceneTree::StretchAspect ); diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 8e80f868c6..f718a09577 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -38,9 +38,10 @@ void Timer::_notification(int p_what) { if (autostart) { #ifdef TOOLS_ENABLED - if (get_scene()->is_editor_hint() && get_scene()->get_edited_scene_root() && (get_scene()->get_edited_scene_root()==this || get_scene()->get_edited_scene_root()->is_a_parent_of(this))) + if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root()==this || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) break; -#endif start(); +#endif + start(); } } break; case NOTIFICATION_PROCESS: { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 7e953e44c7..f0c71da153 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -29,6 +29,8 @@ #include "viewport.h" #include "os/os.h" #include "scene/3d/spatial.h" +#include "os/input.h" +#include "servers/physics_2d_server.h" //#include "scene/3d/camera.h" #include "servers/spatial_sound_server.h" @@ -38,7 +40,7 @@ #include "scene/3d/spatial_indexer.h" #include "scene/3d/collision_object.h" - +#include "scene/2d/collision_object_2d.h" int RenderTargetTexture::get_width() const { @@ -95,15 +97,17 @@ void Viewport::_update_stretch_transform() { if (size_override_stretch && size_override) { - print_line("sive override size "+size_override_size); - print_line("rect size "+rect.size); + //print_line("sive override size "+size_override_size); + //print_line("rect size "+rect.size); stretch_transform=Matrix32(); Size2 scale = rect.size/(size_override_size+size_override_margin*2); stretch_transform.scale(scale); stretch_transform.elements[2]=size_override_margin*scale; + } else { + stretch_transform=Matrix32(); } @@ -113,7 +117,7 @@ void Viewport::_update_stretch_transform() { void Viewport::_update_rect() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; Node *parent = get_parent(); @@ -135,7 +139,9 @@ void Viewport::_update_rect() { } vr.width=rect.size.width; vr.height=rect.size.height; + VisualServer::get_singleton()->viewport_set_rect(viewport,vr); + last_vp_rect=rect; if (canvas_item.is_valid()) { VisualServer::get_singleton()->canvas_item_set_custom_rect(canvas_item,true,rect); @@ -173,7 +179,7 @@ void Viewport::_parent_visibility_changed() { } -void Viewport::_vp_enter_scene() { +void Viewport::_vp_enter_tree() { Node *parent = get_parent(); //none? @@ -198,7 +204,7 @@ void Viewport::_vp_enter_scene() { } -void Viewport::_vp_exit_scene() { +void Viewport::_vp_exit_tree() { Node *parent = get_parent(); if (parent && parent->cast_to<Control>()) { @@ -229,19 +235,19 @@ void Viewport::_vp_exit_scene() { void Viewport::update_worlds() { - if (!is_inside_scene()) + if (!is_inside_tree()) return; Rect2 xformed_rect = (global_canvas_transform * canvas_transform).affine_inverse().xform(get_visible_rect()); find_world_2d()->_update_viewport(this,xformed_rect); find_world_2d()->_update(); - find_world()->_update(get_scene()->get_frame()); + find_world()->_update(get_tree()->get_frame()); } void Viewport::_test_new_mouseover(ObjectID new_collider) { - +#ifndef _3D_DISABLED if (new_collider!=physics_object_over) { if (physics_object_over) { @@ -269,7 +275,7 @@ void Viewport::_test_new_mouseover(ObjectID new_collider) { physics_object_over=new_collider; } - +#endif } @@ -278,11 +284,11 @@ void Viewport::_notification(int p_what) { switch( p_what ) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { if (!render_target) - _vp_enter_scene(); + _vp_enter_tree(); this->parent=NULL; Node *parent=get_parent(); @@ -332,7 +338,7 @@ void Viewport::_notification(int p_what) { } #endif } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { @@ -340,7 +346,7 @@ void Viewport::_notification(int p_what) { world_2d->_remove_viewport(this); if (!render_target) - _vp_exit_scene(); + _vp_exit_tree(); VisualServer::get_singleton()->viewport_set_scenario(viewport,RID()); SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); @@ -356,6 +362,7 @@ void Viewport::_notification(int p_what) { CollisionObject *last_object; ObjectID last_id=0; PhysicsDirectSpaceState::RayResult result; + Physics2DDirectSpaceState *ss2d=Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); bool motion_tested=false; @@ -388,6 +395,60 @@ void Viewport::_notification(int p_what) { } + if (ss2d) { + //send to 2D + + + uint64_t frame = get_tree()->get_frame(); + + Vector2 point = get_canvas_transform().affine_inverse().xform(pos); + Physics2DDirectSpaceState::ShapeResult res[64]; + int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF); + for(int i=0;i<rc;i++) { + + if (res[i].collider_id && res[i].collider) { + CollisionObject2D *co=res[i].collider->cast_to<CollisionObject2D>(); + if (co) { + + Map<ObjectID,uint64_t>::Element *E=physics_2d_mouseover.find(res[i].collider_id); + if (!E) { + E=physics_2d_mouseover.insert(res[i].collider_id,frame); + co->_mouse_enter(); + } else { + E->get()=frame; + } + + co->_input_event(this,ev,res[i].shape); + } + } + } + + List<Map<ObjectID,uint64_t>::Element*> to_erase; + + for (Map<ObjectID,uint64_t>::Element*E=physics_2d_mouseover.front();E;E=E->next()) { + if (E->get()!=frame) { + Object *o=ObjectDB::get_instance(E->key()); + if (o) { + + CollisionObject2D *co=o->cast_to<CollisionObject2D>(); + if (co) { + co->_mouse_exit(); + } + } + to_erase.push_back(E); + } + } + + while(to_erase.size()) { + physics_2d_mouseover.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + + } + + + +#ifndef _3D_DISABLED bool captured=false; if (physics_object_capture!=0) { @@ -495,8 +556,9 @@ void Viewport::_notification(int p_what) { _test_new_mouseover(new_collider); } - +#endif } + } } break; @@ -513,6 +575,7 @@ void Viewport::set_rect(const Rect2& p_rect) { if (rect==p_rect) return; rect=p_rect; + _update_rect(); _update_stretch_transform(); @@ -547,7 +610,7 @@ Rect2 Viewport::get_rect() const { void Viewport::_update_listener() { - if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) { + if (is_inside_tree() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) { SpatialSoundServer::get_singleton()->listener_set_space(listener,find_world()->get_sound_space()); } else { SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); @@ -558,7 +621,7 @@ void Viewport::_update_listener() { void Viewport::_update_listener_2d() { - if (is_inside_scene() && audio_listener && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) + if (is_inside_tree() && audio_listener && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space()); else SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID()); @@ -737,7 +800,7 @@ void Viewport::_propagate_enter_world(Node *p_node) { if (p_node!=this) { - if (!p_node->is_inside_scene()) //may not have entered scene yet + if (!p_node->is_inside_tree()) //may not have entered scene yet return; Spatial *s = p_node->cast_to<Spatial>(); @@ -766,7 +829,7 @@ void Viewport::_propagate_exit_world(Node *p_node) { if (p_node!=this) { - if (!p_node->is_inside_scene()) //may have exited scene already + if (!p_node->is_inside_tree()) //may have exited scene already return; Spatial *s = p_node->cast_to<Spatial>(); @@ -797,7 +860,7 @@ void Viewport::set_world(const Ref<World>& p_world) { if (world==p_world) return; - if (is_inside_scene()) + if (is_inside_tree()) _propagate_exit_world(this); #ifndef _3D_DISABLED @@ -807,7 +870,7 @@ void Viewport::set_world(const Ref<World>& p_world) { world=p_world; - if (is_inside_scene()) + if (is_inside_tree()) _propagate_enter_world(this); #ifndef _3D_DISABLED @@ -817,7 +880,7 @@ void Viewport::set_world(const Ref<World>& p_world) { //propagate exit - if (is_inside_scene()) { + if (is_inside_tree()) { VisualServer::get_singleton()->viewport_set_scenario(viewport,find_world()->get_scenario()); } @@ -905,12 +968,12 @@ void Viewport::set_as_render_target(bool p_enable){ render_target=p_enable; VS::get_singleton()->viewport_set_as_render_target(viewport,p_enable); - if (is_inside_scene()) { + if (is_inside_tree()) { if (p_enable) - _vp_exit_scene(); + _vp_exit_tree(); else - _vp_enter_scene(); + _vp_enter_tree(); } if (p_enable) { @@ -966,6 +1029,22 @@ bool Viewport::get_render_target_vflip() const{ return render_target_vflip; } +void Viewport::set_render_target_clear_on_new_frame(bool p_enable) { + + render_target_clear_on_new_frame=p_enable; + VisualServer::get_singleton()->viewport_set_render_target_clear_on_new_frame(viewport,p_enable); +} + +bool Viewport::get_render_target_clear_on_new_frame() const{ + + return render_target_clear_on_new_frame; +} + +void Viewport::render_target_clear() { + + //render_target_clear=true; + VisualServer::get_singleton()->viewport_render_target_clear(viewport); +} void Viewport::set_render_target_filter(bool p_enable) { @@ -999,8 +1078,9 @@ Matrix32 Viewport::_get_input_pre_xform() const { ERR_FAIL_COND_V(to_screen_rect.size.x==0,pre_xf); ERR_FAIL_COND_V(to_screen_rect.size.y==0,pre_xf); - pre_xf.scale(rect.size/to_screen_rect.size); + pre_xf.elements[2]=-to_screen_rect.pos; + pre_xf.scale(rect.size/to_screen_rect.size); } else { pre_xf.elements[2]=-rect.pos; @@ -1029,13 +1109,16 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); - Vector2 r = ai.xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 r = ai.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); ev.mouse_motion.x=l.x; ev.mouse_motion.y=l.y; ev.mouse_motion.global_x=g.x; ev.mouse_motion.global_y=g.y; ev.mouse_motion.relative_x=r.x; ev.mouse_motion.relative_y=r.y; + ev.mouse_motion.speed_x=s.x; + ev.mouse_motion.speed_y=s.y; } break; case InputEvent::SCREEN_TOUCH: { @@ -1050,8 +1133,8 @@ void Viewport::_make_input_local(InputEvent& ev) { Matrix32 ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); - Vector2 r = ai.xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); - Vector2 s = ai.xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); + Vector2 r = ai.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); + Vector2 s = ai.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); ev.screen_drag.x=t.x; ev.screen_drag.y=t.y; ev.screen_drag.relative_x=r.x; @@ -1061,6 +1144,7 @@ void Viewport::_make_input_local(InputEvent& ev) { } break; } + } @@ -1093,26 +1177,32 @@ void Viewport::_vp_unhandled_input(const InputEvent& p_ev) { } +void Viewport::warp_mouse(const Vector2& p_pos) { + + Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos); + Input::get_singleton()->warp_mouse_pos(gpos); +} + void Viewport::input(const InputEvent& p_event) { - ERR_FAIL_COND(!is_inside_scene()); - get_scene()->_call_input_pause(input_group,"_input",p_event); - get_scene()->call_group(SceneMainLoop::GROUP_CALL_REVERSE|SceneMainLoop::GROUP_CALL_REALTIME|SceneMainLoop::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check + ERR_FAIL_COND(!is_inside_tree()); + get_tree()->_call_input_pause(input_group,"_input",p_event); + get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check } void Viewport::unhandled_input(const InputEvent& p_event) { - ERR_FAIL_COND(!is_inside_scene()); + ERR_FAIL_COND(!is_inside_tree()); - get_scene()->_call_input_pause(unhandled_input_group,"_unhandled_input",p_event); + get_tree()->_call_input_pause(unhandled_input_group,"_unhandled_input",p_event); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev); - if (!get_scene()->input_handled && p_event.type==InputEvent::KEY) { - get_scene()->_call_input_pause(unhandled_key_input_group,"_unhandled_key_input",p_event); + if (!get_tree()->input_handled && p_event.type==InputEvent::KEY) { + get_tree()->_call_input_pause(unhandled_key_input_group,"_unhandled_key_input",p_event); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev); } - if (physics_object_picking && !get_scene()->input_handled) { + if (physics_object_picking && !get_tree()->input_handled) { if (p_event.type==InputEvent::MOUSE_BUTTON || p_event.type==InputEvent::MOUSE_MOTION || p_event.type==InputEvent::SCREEN_DRAG || p_event.type==InputEvent::SCREEN_TOUCH) { physics_picking_events.push_back(p_event); @@ -1127,7 +1217,7 @@ void Viewport::set_use_own_world(bool p_world) { return; - if (is_inside_scene()) + if (is_inside_tree()) _propagate_exit_world(this); #ifndef _3D_DISABLED @@ -1140,7 +1230,7 @@ void Viewport::set_use_own_world(bool p_world) { else own_world=Ref<World>( memnew( World )); - if (is_inside_scene()) + if (is_inside_tree()) _propagate_enter_world(this); #ifndef _3D_DISABLED @@ -1150,7 +1240,7 @@ void Viewport::set_use_own_world(bool p_world) { //propagate exit - if (is_inside_scene()) { + if (is_inside_tree()) { VisualServer::get_singleton()->viewport_set_scenario(viewport,find_world()->get_scenario()); } @@ -1185,6 +1275,21 @@ void Viewport::set_physics_object_picking(bool p_enable) { } + +Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { + + Matrix32 xf = get_final_transform(); + return xf.xform(p_viewport_coords); + + +} + +Vector2 Viewport::get_camera_rect_size() const { + + return last_vp_rect.size; +} + + bool Viewport::get_physics_object_picking() { @@ -1234,6 +1339,11 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_render_target_vflip","enable"), &Viewport::set_render_target_vflip); ObjectTypeDB::bind_method(_MD("get_render_target_vflip"), &Viewport::get_render_target_vflip); + + ObjectTypeDB::bind_method(_MD("set_render_target_clear_on_new_frame","enable"), &Viewport::set_render_target_clear_on_new_frame); + ObjectTypeDB::bind_method(_MD("get_render_target_clear_on_new_frame"), &Viewport::get_render_target_clear_on_new_frame); + + ObjectTypeDB::bind_method(_MD("render_target_clear"), &Viewport::render_target_clear); ObjectTypeDB::bind_method(_MD("set_render_target_filter","enable"), &Viewport::set_render_target_filter); ObjectTypeDB::bind_method(_MD("get_render_target_filter"), &Viewport::get_render_target_filter); @@ -1267,6 +1377,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d); ObjectTypeDB::bind_method(_MD("set_render_target_to_screen_rect"), &Viewport::set_render_target_to_screen_rect); + ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse); ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") ); @@ -1275,6 +1386,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_render_target_vflip"), _SCS("get_render_target_vflip") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/clear_on_new_frame"), _SCS("set_render_target_clear_on_new_frame"), _SCS("get_render_target_clear_on_new_frame") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/filter"), _SCS("set_render_target_filter"), _SCS("get_render_target_filter") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/gen_mipmaps"), _SCS("set_render_target_gen_mipmaps"), _SCS("get_render_target_gen_mipmaps") ); ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") ); @@ -1313,6 +1425,8 @@ Viewport::Viewport() { render_target_gen_mipmaps=false; render_target=false; render_target_vflip=false; + render_target_clear_on_new_frame=true; + //render_target_clear=true; render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) ); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5d68438f0d..14f4f68217 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -110,9 +110,11 @@ friend class RenderTargetTexture; Size2 size_override_size; Size2 size_override_margin; + Rect2 last_vp_rect; bool transparent_bg; bool render_target_vflip; + bool render_target_clear_on_new_frame; bool render_target_filter; bool render_target_gen_mipmaps; @@ -122,6 +124,7 @@ friend class RenderTargetTexture; ObjectID physics_object_over; Vector2 physics_last_mousepos; void _test_new_mouseover(ObjectID new_collider); + Map<ObjectID,uint64_t> physics_2d_mouseover; void _update_rect(); @@ -158,8 +161,8 @@ friend class RenderTargetTexture; _FORCE_INLINE_ Matrix32 _get_input_pre_xform() const; - void _vp_enter_scene(); - void _vp_exit_scene(); + void _vp_enter_tree(); + void _vp_exit_tree(); void _vp_input(const InputEvent& p_ev); void _vp_unhandled_input(const InputEvent& p_ev); @@ -219,6 +222,10 @@ public: void set_render_target_vflip(bool p_enable); bool get_render_target_vflip() const; + void set_render_target_clear_on_new_frame(bool p_enable); + bool get_render_target_clear_on_new_frame() const; + void render_target_clear(); + void set_render_target_filter(bool p_enable); bool get_render_target_filter() const; @@ -229,6 +236,10 @@ public: RenderTargetUpdateMode get_render_target_update_mode() const; Ref<RenderTargetTexture> get_render_target_texture() const; + + Vector2 get_camera_coords(const Vector2& p_viewport_coords) const; + Vector2 get_camera_rect_size() const; + void queue_screen_capture(); Image get_screen_capture() const; @@ -241,6 +252,8 @@ public: void set_render_target_to_screen_rect(const Rect2& p_rect); Rect2 get_render_target_to_screen_rect() const; + void warp_mouse(const Vector2& p_pos); + void set_physics_object_picking(bool p_enable); bool get_physics_object_picking(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index afa127caef..afadbf0170 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -39,7 +39,6 @@ #include "scene/main/viewport.h" #include "scene/gui/control.h" #include "scene/gui/texture_progress.h" -#include "scene/gui/empty_control.h" #include "scene/gui/button.h" #include "scene/gui/button_array.h" #include "scene/gui/button_group.h" @@ -54,6 +53,7 @@ #include "scene/gui/color_picker.h" #include "scene/gui/texture_frame.h" #include "scene/gui/menu_button.h" +#include "scene/gui/check_box.h" #include "scene/gui/check_button.h" #include "scene/gui/tab_container.h" #include "scene/gui/panel_container.h" @@ -75,14 +75,20 @@ #include "scene/gui/split_container.h" #include "scene/gui/video_player.h" #include "scene/gui/reference_frame.h" +#include "scene/gui/graph_node.h" +#include "scene/gui/graph_edit.h" +#include "scene/gui/tool_button.h" #include "scene/resources/video_stream.h" #include "scene/2d/particles_2d.h" #include "scene/2d/path_2d.h" +#include "scene/2d/light_2d.h" +#include "scene/2d/light_occluder_2d.h" #include "scene/2d/canvas_item.h" #include "scene/2d/sprite.h" #include "scene/2d/animated_sprite.h" #include "scene/2d/polygon_2d.h" +#include "scene/2d/back_buffer_copy.h" #include "scene/2d/visibility_notifier_2d.h" @@ -101,6 +107,8 @@ #include "scene/2d/screen_button.h" #include "scene/2d/remote_transform_2d.h" #include "scene/2d/y_sort.h" +#include "scene/2d/navigation2d.h" +#include "scene/2d/canvas_modulate.h" #include "scene/2d/position_2d.h" #include "scene/2d/tile_map.h" @@ -152,6 +160,8 @@ #include "scene/resources/mesh.h" #include "scene/resources/room.h" +#include "scene/resources/shader_graph.h" + #include "scene/resources/world.h" #include "scene/resources/world_2d.h" #include "scene/resources/volume.h" @@ -259,6 +269,7 @@ void register_scene_types() { ObjectTypeDB::register_virtual_type<RenderTargetTexture>(); ObjectTypeDB::register_type<Timer>(); ObjectTypeDB::register_type<CanvasLayer>(); + ObjectTypeDB::register_type<CanvasModulate>(); ObjectTypeDB::register_type<ResourcePreloader>(); /* REGISTER GUI */ @@ -268,7 +279,8 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type<Control>(); - ObjectTypeDB::register_type<EmptyControl>(); +// ObjectTypeDB::register_type<EmptyControl>(); + ObjectTypeDB::add_compatibility_type("EmptyControl","Control"); ObjectTypeDB::register_type<Button>(); ObjectTypeDB::register_type<Label>(); ObjectTypeDB::register_type<HScrollBar>(); @@ -279,7 +291,9 @@ void register_scene_types() { ObjectTypeDB::register_type<Popup>(); ObjectTypeDB::register_type<PopupPanel>(); ObjectTypeDB::register_type<MenuButton>(); + ObjectTypeDB::register_type<CheckBox>(); ObjectTypeDB::register_type<CheckButton>(); + ObjectTypeDB::register_type<ToolButton>(); ObjectTypeDB::register_type<Panel>(); ObjectTypeDB::register_type<Range>(); @@ -303,6 +317,8 @@ void register_scene_types() { ObjectTypeDB::register_virtual_type<SplitContainer>(); ObjectTypeDB::register_type<HSplitContainer>(); ObjectTypeDB::register_type<VSplitContainer>(); + ObjectTypeDB::register_type<GraphNode>(); + ObjectTypeDB::register_type<GraphEdit>(); OS::get_singleton()->yield(); //may take time to init @@ -394,8 +410,16 @@ void register_scene_types() { ObjectTypeDB::register_type<VisibilityNotifier>(); ObjectTypeDB::register_type<VisibilityEnabler>(); ObjectTypeDB::register_type<BakedLightInstance>(); + ObjectTypeDB::register_type<BakedLightSampler>(); ObjectTypeDB::register_type<WorldEnvironment>(); + ObjectTypeDB::register_virtual_type<Joint>(); + ObjectTypeDB::register_type<PinJoint>(); + ObjectTypeDB::register_type<HingeJoint>(); + ObjectTypeDB::register_type<SliderJoint>(); + ObjectTypeDB::register_type<ConeTwistJoint>(); + ObjectTypeDB::register_type<Generic6DOFJoint>(); + //scenariofx OS::get_singleton()->yield(); //may take time to init @@ -404,6 +428,7 @@ void register_scene_types() { ObjectTypeDB::register_type<SpatialStreamPlayer>(); ObjectTypeDB::register_type<SoundRoomParams>(); + #endif ObjectTypeDB::register_type<MeshLibrary>(); AcceptDialog::set_swap_ok_cancel( GLOBAL_DEF("display/swap_ok_cancel",bool(OS::get_singleton()->get_swap_ok_cancel())) ); @@ -421,12 +446,6 @@ void register_scene_types() { //ObjectTypeDB::register_type<PhysicsJointPin>(); - ObjectTypeDB::register_virtual_type<Joint>(); - ObjectTypeDB::register_type<PinJoint>(); - ObjectTypeDB::register_type<HingeJoint>(); - ObjectTypeDB::register_type<SliderJoint>(); - ObjectTypeDB::register_type<ConeTwistJoint>(); - ObjectTypeDB::register_type<Generic6DOFJoint>(); ObjectTypeDB::register_type<StreamPlayer>(); @@ -441,6 +460,7 @@ void register_scene_types() { //ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false); //ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false); + ObjectTypeDB::register_type<CanvasItemMaterial>(); ObjectTypeDB::register_virtual_type<CanvasItem>(); ObjectTypeDB::register_type<Node2D>(); ObjectTypeDB::register_type<Particles2D>(); @@ -462,7 +482,11 @@ void register_scene_types() { ObjectTypeDB::register_type<VisibilityNotifier2D>(); ObjectTypeDB::register_type<VisibilityEnabler2D>(); ObjectTypeDB::register_type<Polygon2D>(); + ObjectTypeDB::register_type<Light2D>(); + ObjectTypeDB::register_type<LightOccluder2D>(); + ObjectTypeDB::register_type<OccluderPolygon2D>(); ObjectTypeDB::register_type<YSort>(); + ObjectTypeDB::register_type<BackBufferCopy>(); ObjectTypeDB::set_type_enabled("CollisionShape2D",false); ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false); @@ -487,15 +511,22 @@ void register_scene_types() { /* REGISTER RESOURCES */ + ObjectTypeDB::register_virtual_type<Shader>(); + ObjectTypeDB::register_virtual_type<ShaderGraph>(); + ObjectTypeDB::register_type<CanvasItemShader>(); + ObjectTypeDB::register_type<CanvasItemShaderGraph>(); + #ifndef _3D_DISABLED ObjectTypeDB::register_type<Mesh>(); ObjectTypeDB::register_virtual_type<Material>(); ObjectTypeDB::register_type<FixedMaterial>(); - ObjectTypeDB::register_type<ParticleSystemMaterial>(); - ObjectTypeDB::register_type<UnshadedMaterial>(); ObjectTypeDB::register_type<ShaderMaterial>(); ObjectTypeDB::register_type<RoomBounds>(); - ObjectTypeDB::register_type<Shader>(); + ObjectTypeDB::register_type<MaterialShaderGraph>(); + ObjectTypeDB::register_type<MaterialShader>(); + ObjectTypeDB::add_compatibility_type("Shader","MaterialShader"); + ObjectTypeDB::add_compatibility_type("ParticleSystemMaterial","FixedMaterial"); + ObjectTypeDB::add_compatibility_type("UnshadedMaterial","FixedMaterial"); ObjectTypeDB::register_type<MultiMesh>(); ObjectTypeDB::register_type<MeshLibrary>(); @@ -559,11 +590,15 @@ void register_scene_types() { ObjectTypeDB::register_type<Path2D>(); ObjectTypeDB::register_type<PathFollow2D>(); + ObjectTypeDB::register_type<Navigation2D>(); + ObjectTypeDB::register_type<NavigationPolygon>(); + ObjectTypeDB::register_type<NavigationPolygonInstance>(); + OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type<PackedScene>(); - ObjectTypeDB::register_type<SceneMainLoop>(); + ObjectTypeDB::register_type<SceneTree>(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index e6359f920b..80993c7eaf 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1266,7 +1266,7 @@ T Animation::_interpolate( const Vector< TKey<T> >& p_keys, float p_time, Inter } } else { // no loop - + if (idx>=0) { if ((idx+1) < len) { @@ -1716,189 +1716,222 @@ void Animation::clear() { } -void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) { - ERR_FAIL_INDEX(p_idx,tracks.size()); - ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM); - TransformTrack *tt= static_cast<TransformTrack*>(tracks[p_idx]); - for(int i=1;i<tt->transforms.size()-1;i++) { - TKey<TransformKey> &t0 = tt->transforms[i-1]; - TKey<TransformKey> &t1 = tt->transforms[i]; - TKey<TransformKey> &t2 = tt->transforms[i+1]; +bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0,const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) { - real_t c = (t1.time-t0.time)/(t2.time-t0.time); - real_t t[3]={-1,-1,-1}; - { //translation + real_t c = (t1.time-t0.time)/(t2.time-t0.time); + real_t t[3]={-1,-1,-1}; - const Vector3 &v0=t0.value.loc; - const Vector3 &v1=t1.value.loc; - const Vector3 &v2=t2.value.loc; + { //translation - if (v0.distance_to(v2)<CMP_EPSILON) { - //0 and 2 are close, let's see if 1 is close - if (v0.distance_to(v1)>CMP_EPSILON) { - //not close, not optimizable - continue; - } + const Vector3 &v0=t0.value.loc; + const Vector3 &v1=t1.value.loc; + const Vector3 &v2=t2.value.loc; - } else { + if (v0.distance_to(v2)<CMP_EPSILON) { + //0 and 2 are close, let's see if 1 is close + if (v0.distance_to(v1)>CMP_EPSILON) { + //not close, not optimizable + return false; + } - Vector3 pd = (v2-v0); - float d0 = pd.dot(v0); - float d1 = pd.dot(v1); - float d2 = pd.dot(v2); - if (d1<d0 || d1>d2) { - continue; //beyond segment range - } + } else { - Vector3 s[2]={ v0, v2 }; - real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1); + Vector3 pd = (v2-v0); + float d0 = pd.dot(v0); + float d1 = pd.dot(v1); + float d2 = pd.dot(v2); + if (d1<d0 || d1>d2) { + return false; + } - if (d>pd.length()*p_alowed_linear_err) { - continue; //beyond allowed error for colinearity - } + Vector3 s[2]={ v0, v2 }; + real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1); - t[0] = (d1-d0)/(d2-d0); + if (d>pd.length()*p_alowed_linear_err) { + return false; //beyond allowed error for colinearity } - } - { //rotation + t[0] = (d1-d0)/(d2-d0); + } + } - const Quat &q0=t0.value.rot; - const Quat &q1=t1.value.rot; - const Quat &q2=t2.value.rot; + { //rotation - //localize both to rotation from q0 + const Quat &q0=t0.value.rot; + const Quat &q1=t1.value.rot; + const Quat &q2=t2.value.rot; - if ((q0-q2).length() < CMP_EPSILON) { + //localize both to rotation from q0 - if ((q0-q1).length() > CMP_EPSILON) - continue; + if ((q0-q2).length() < CMP_EPSILON) { - } else { + if ((q0-q1).length() > CMP_EPSILON) + return false; + } else { - Quat r02 = (q0.inverse() * q2).normalized(); - Quat r01 = (q0.inverse() * q1).normalized(); - Vector3 v02,v01; - real_t a02,a01; + Quat r02 = (q0.inverse() * q2).normalized(); + Quat r01 = (q0.inverse() * q1).normalized(); - r02.get_axis_and_angle(v02,a02); - r01.get_axis_and_angle(v01,a01); + Vector3 v02,v01; + real_t a02,a01; - if (Math::abs(a02)>p_max_optimizable_angle) - continue; + r02.get_axis_and_angle(v02,a02); + r01.get_axis_and_angle(v01,a01); - if (v01.dot(v02)<0) { - //make sure both rotations go the same way to compare - v02=-v02; - a02=-a02; - } + if (Math::abs(a02)>p_max_optimizable_angle) + return false; - real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized()))/Math_PI; - if (err_01>p_alowed_angular_err) { - //not rotating in the same axis - continue; - } + if (v01.dot(v02)<0) { + //make sure both rotations go the same way to compare + v02=-v02; + a02=-a02; + } - if (a01*a02 < 0 ) { - //not rotating in the same direction - continue; - } + real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized()))/Math_PI; + if (err_01>p_alowed_angular_err) { + //not rotating in the same axis + return false; + } - real_t tr = a01/a02; - if (tr<0 || tr>1) - continue; //rotating too much or too less + if (a01*a02 < 0 ) { + //not rotating in the same direction + return false; + } - t[1]=tr; + real_t tr = a01/a02; + if (tr<0 || tr>1) + return false; //rotating too much or too less - } + t[1]=tr; } - { //scale + } - const Vector3 &v0=t0.value.scale; - const Vector3 &v1=t1.value.scale; - const Vector3 &v2=t2.value.scale; + { //scale - if (v0.distance_to(v2)<CMP_EPSILON) { - //0 and 2 are close, let's see if 1 is close - if (v0.distance_to(v1)>CMP_EPSILON) { - //not close, not optimizable - continue; - } + const Vector3 &v0=t0.value.scale; + const Vector3 &v1=t1.value.scale; + const Vector3 &v2=t2.value.scale; - } else { + if (v0.distance_to(v2)<CMP_EPSILON) { + //0 and 2 are close, let's see if 1 is close + if (v0.distance_to(v1)>CMP_EPSILON) { + //not close, not optimizable + return false; + } - Vector3 pd = (v2-v0); - float d0 = pd.dot(v0); - float d1 = pd.dot(v1); - float d2 = pd.dot(v2); - if (d1<d0 || d1>d2) { - continue; //beyond segment range - } + } else { - Vector3 s[2]={ v0, v2 }; - real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1); + Vector3 pd = (v2-v0); + float d0 = pd.dot(v0); + float d1 = pd.dot(v1); + float d2 = pd.dot(v2); + if (d1<d0 || d1>d2) { + return false; //beyond segment range + } - if (d>pd.length()*p_alowed_linear_err) { - continue; //beyond allowed error for colinearity - } + Vector3 s[2]={ v0, v2 }; + real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1); - t[2] = (d1-d0)/(d2-d0); + if (d>pd.length()*p_alowed_linear_err) { + return false; //beyond allowed error for colinearity } + + t[2] = (d1-d0)/(d2-d0); } + } - bool erase=false; - if (t[0]==-1 && t[1]==-1 && t[2]==-1) { + bool erase=false; + if (t[0]==-1 && t[1]==-1 && t[2]==-1) { - erase=true; - } else { + erase=true; + } else { - erase=true; - real_t lt=-1; - for(int j=0;j<3;j++) { - //search for t on first, one must be it - if (t[j]!=-1) { - lt=t[j]; //official t - //validate rest - for(int k=j+1;k<3;k++) { - if (t[k]==-1) - continue; - - if (Math::abs(lt-t[k])>p_alowed_linear_err) { - erase=false; - break; - } + erase=true; + real_t lt=-1; + for(int j=0;j<3;j++) { + //search for t on first, one must be it + if (t[j]!=-1) { + lt=t[j]; //official t + //validate rest + for(int k=j+1;k<3;k++) { + if (t[k]==-1) + continue; + + if (Math::abs(lt-t[k])>p_alowed_linear_err) { + erase=false; + break; } - break; } + break; } + } - ERR_CONTINUE( lt==-1 ); + ERR_FAIL_COND_V( lt==-1,false ); - if (erase) { + if (erase) { - if (Math::abs(lt-c)>p_alowed_linear_err) { - //todo, evaluate changing the transition if this fails? - //this could be done as a second pass and would be - //able to optimize more - erase=false; - } else { + if (Math::abs(lt-c)>p_alowed_linear_err) { + //todo, evaluate changing the transition if this fails? + //this could be done as a second pass and would be + //able to optimize more + erase=false; + } else { - //print_line(itos(i)+"because of interp"); - } + //print_line(itos(i)+"because of interp"); } + } + + } + + + return erase; + + +} + +void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) { + + ERR_FAIL_INDEX(p_idx,tracks.size()); + ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM); + TransformTrack *tt= static_cast<TransformTrack*>(tracks[p_idx]); + bool prev_erased=false; + TKey<TransformKey> first_erased; + + for(int i=1;i<tt->transforms.size()-1;i++) { + + TKey<TransformKey> &t0 = tt->transforms[i-1]; + TKey<TransformKey> &t1 = tt->transforms[i]; + TKey<TransformKey> &t2 = tt->transforms[i+1]; + + bool erase = _transform_track_optimize_key(t0,t1,t2,p_alowed_linear_err,p_alowed_angular_err,p_max_optimizable_angle); + + + if (prev_erased && !_transform_track_optimize_key(t0,first_erased,t2,p_alowed_linear_err,p_alowed_angular_err,p_max_optimizable_angle)) { + //avoid error to go beyond first erased key + erase=false; } + if (erase) { + + if (!prev_erased) { + first_erased=t1; + prev_erased=true; + } + tt->transforms.remove(i); i--; + + } else { + prev_erased=false; } diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 0c0290295a..bf87789e39 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -204,6 +204,7 @@ private: return idxr; } + bool _transform_track_optimize_key(const TKey<TransformKey> &t0,const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle); void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125); protected: diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 8e694a6110..bc7bffa9d2 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -38,15 +38,18 @@ int AudioStreamResampled::get_channel_count() const { template<int C> -void AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { +uint32_t AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { + + uint32_t read=offset&MIX_FRAC_MASK; for (int i=0;i<p_todo;i++) { offset = (offset + p_increment)&(((1<<(rb_bits+MIX_FRAC_BITS))-1)); + read+=p_increment; uint32_t pos = offset >> MIX_FRAC_BITS; uint32_t frac = offset & MIX_FRAC_MASK; #ifndef FAST_AUDIO - ERR_FAIL_COND(pos>=rb_len); + ERR_FAIL_COND_V(pos>=rb_len,0); #endif uint32_t pos_next = (pos+1)&rb_mask; //printf("rb pos %i\n",pos); @@ -151,7 +154,7 @@ void AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increm } - rb_read_pos=offset>>MIX_FRAC_BITS; + return read>>MIX_FRAC_BITS;//rb_read_pos=offset>>MIX_FRAC_BITS; } @@ -173,10 +176,10 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { } else if (rb_read_pos<write_pos_cache) { - rb_todo=write_pos_cache-rb_read_pos-1; + rb_todo=write_pos_cache-rb_read_pos; //-1? } else { - rb_todo=(rb_len-rb_read_pos)+write_pos_cache-1; + rb_todo=(rb_len-rb_read_pos)+write_pos_cache; //-1? } int todo = MIN( ((int64_t(rb_todo)<<MIX_FRAC_BITS)/increment)+1, p_frames ); @@ -220,13 +223,22 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { #endif { + uint32_t read=0; switch(channels) { - case 1: _resample<1>(p_dest,todo,increment); break; - case 2: _resample<2>(p_dest,todo,increment); break; - case 4: _resample<4>(p_dest,todo,increment); break; - case 6: _resample<6>(p_dest,todo,increment); break; + case 1: read=_resample<1>(p_dest,todo,increment); break; + case 2: read=_resample<2>(p_dest,todo,increment); break; + case 4: read=_resample<4>(p_dest,todo,increment); break; + case 6: read=_resample<6>(p_dest,todo,increment); break; } + if (read>rb_todo) + read=rb_todo; + + rb_read_pos = (rb_read_pos+read)&rb_mask; + + + + } return true; diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h index f1e3629ac7..a1b95e81d5 100644 --- a/scene/resources/audio_stream_resampled.h +++ b/scene/resources/audio_stream_resampled.h @@ -57,7 +57,7 @@ class AudioStreamResampled : public AudioStream { template<int C> - void _resample(int32_t *p_dest,int p_todo,int32_t p_increment); + uint32_t _resample(int32_t *p_dest,int p_todo,int32_t p_increment); protected: @@ -97,7 +97,7 @@ protected: _FORCE_INLINE_ int16_t *get_write_buffer() { return read_buf; } _FORCE_INLINE_ void write(uint32_t p_frames) { - ERR_FAIL_COND(p_frames > rb_len); + ERR_FAIL_COND(p_frames >= rb_len); switch(channels) { case 1: { diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp index 647c8df5d4..226edec9ae 100644 --- a/scene/resources/baked_light.cpp +++ b/scene/resources/baked_light.cpp @@ -23,6 +23,27 @@ DVector<uint8_t> BakedLight::get_octree() const { return VS::get_singleton()->baked_light_get_octree(baked_light); } +void BakedLight::set_light(const DVector<uint8_t>& p_light) { + + VS::get_singleton()->baked_light_set_light(baked_light,p_light); +} + +DVector<uint8_t> BakedLight::get_light() const { + + return VS::get_singleton()->baked_light_get_light(baked_light); +} + + +void BakedLight::set_sampler_octree(const DVector<int>& p_sampler_octree) { + + VS::get_singleton()->baked_light_set_sampler_octree(baked_light,p_sampler_octree); +} + +DVector<int> BakedLight::get_sampler_octree() const { + + return VS::get_singleton()->baked_light_get_sampler_octree(baked_light); +} + @@ -199,6 +220,43 @@ float BakedLight::get_normal_damp() const { return normal_damp; } +void BakedLight::set_tint(float p_margin) { + tint=p_margin; +} + +float BakedLight::get_tint() const { + + return tint; +} + +void BakedLight::set_saturation(float p_margin) { + saturation=p_margin; +} + +float BakedLight::get_saturation() const { + + return saturation; +} + +void BakedLight::set_ao_radius(float p_ao_radius) { + ao_radius=p_ao_radius; +} + +float BakedLight::get_ao_radius() const { + return ao_radius; +} + +void BakedLight::set_ao_strength(float p_ao_strength) { + + ao_strength=p_ao_strength; +} + +float BakedLight::get_ao_strength() const { + + return ao_strength; +} + + void BakedLight::set_energy_multiplier(float p_multiplier){ energy_multiply=p_multiplier; @@ -329,6 +387,13 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_octree","octree"),&BakedLight::set_octree); ObjectTypeDB::bind_method(_MD("get_octree"),&BakedLight::get_octree); + ObjectTypeDB::bind_method(_MD("set_light","light"),&BakedLight::set_light); + ObjectTypeDB::bind_method(_MD("get_light"),&BakedLight::get_light); + + ObjectTypeDB::bind_method(_MD("set_sampler_octree","sampler_octree"),&BakedLight::set_sampler_octree); + ObjectTypeDB::bind_method(_MD("get_sampler_octree"),&BakedLight::get_sampler_octree); + + ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","gen_size"),&BakedLight::add_lightmap); ObjectTypeDB::bind_method(_MD("erase_lightmap","id"),&BakedLight::erase_lightmap); ObjectTypeDB::bind_method(_MD("clear_lightmaps"),&BakedLight::clear_lightmaps); @@ -357,6 +422,18 @@ void BakedLight::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_normal_damp","normal_damp"),&BakedLight::set_normal_damp); ObjectTypeDB::bind_method(_MD("get_normal_damp"),&BakedLight::get_normal_damp); + ObjectTypeDB::bind_method(_MD("set_tint","tint"),&BakedLight::set_tint); + ObjectTypeDB::bind_method(_MD("get_tint"),&BakedLight::get_tint); + + ObjectTypeDB::bind_method(_MD("set_saturation","saturation"),&BakedLight::set_saturation); + ObjectTypeDB::bind_method(_MD("get_saturation"),&BakedLight::get_saturation); + + ObjectTypeDB::bind_method(_MD("set_ao_radius","ao_radius"),&BakedLight::set_ao_radius); + ObjectTypeDB::bind_method(_MD("get_ao_radius"),&BakedLight::get_ao_radius); + + ObjectTypeDB::bind_method(_MD("set_ao_strength","ao_strength"),&BakedLight::set_ao_strength); + ObjectTypeDB::bind_method(_MD("get_ao_strength"),&BakedLight::get_ao_strength); + ObjectTypeDB::bind_method(_MD("set_format","format"),&BakedLight::set_format); ObjectTypeDB::bind_method(_MD("get_format"),&BakedLight::get_format); @@ -384,17 +461,24 @@ void BakedLight::_bind_methods(){ ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/plot_size",PROPERTY_HINT_RANGE,"1.0,16.0,0.01"),_SCS("set_plot_size"),_SCS("get_plot_size")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/energy_mult",PROPERTY_HINT_RANGE,"0.01,4096.0,0.01"),_SCS("set_energy_multiplier"),_SCS("get_energy_multiplier")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/gamma_adjust",PROPERTY_HINT_EXP_EASING),_SCS("set_gamma_adjust"),_SCS("get_gamma_adjust")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/saturation",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("set_saturation"),_SCS("get_saturation")); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/diffuse"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_DIFFUSE); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/specular"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_SPECULAR); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/translucent"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_TRANSLUCENT); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/conserve_energy"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_CONSERVE_ENERGY); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/linear_color"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_LINEAR_COLOR); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"lightmap/use_only_uv2"),_SCS("set_transfer_lightmaps_only_to_uv2"),_SCS("get_transfer_lightmaps_only_to_uv2")); ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_octree"),_SCS("get_octree")); + ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"light",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_light"),_SCS("get_light")); + ADD_PROPERTY( PropertyInfo(Variant::INT_ARRAY,"sampler_octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_sampler_octree"),_SCS("get_sampler_octree")); ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"lightmaps",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_lightmap_data"),_SCS("_get_lightmap_data")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/cell_margin",PROPERTY_HINT_RANGE,"0.01,0.8,0.01"),_SCS("set_cell_extra_margin"),_SCS("get_cell_extra_margin")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/edge_damp",PROPERTY_HINT_RANGE,"0.0,8.0,0.1"),_SCS("set_edge_damp"),_SCS("get_edge_damp")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/normal_damp",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_normal_damp"),_SCS("get_normal_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/light_tint",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_tint"),_SCS("get_tint")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_radius",PROPERTY_HINT_RANGE,"0.0,16.0,0.01"),_SCS("set_ao_radius"),_SCS("get_ao_radius")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/ao_strength",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_ao_strength"),_SCS("get_ao_strength")); BIND_CONSTANT( MODE_OCTREE ); BIND_CONSTANT( MODE_LIGHTMAPS ); @@ -415,18 +499,24 @@ BakedLight::BakedLight() { lattice_subdiv=4; plot_size=2.5; bounces=1; - energy_multiply=1.0; - gamma_adjust=1.0; + energy_multiply=2.0; + gamma_adjust=0.7; cell_extra_margin=0.05; edge_damp=0.0; normal_damp=0.0; + saturation=1; + tint=0.0; + ao_radius=2.5; + ao_strength=0.7; format=FORMAT_RGB; transfer_only_uv2=false; + flags[BAKE_DIFFUSE]=true; flags[BAKE_SPECULAR]=false; flags[BAKE_TRANSLUCENT]=true; flags[BAKE_CONSERVE_ENERGY]=false; + flags[BAKE_LINEAR_COLOR]=false; mode=MODE_OCTREE; baked_light=VS::get_singleton()->baked_light_create(); diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h index 57ed7d7aee..41e1e5f9e0 100644 --- a/scene/resources/baked_light.h +++ b/scene/resources/baked_light.h @@ -26,6 +26,7 @@ public: BAKE_SPECULAR, BAKE_TRANSLUCENT, BAKE_CONSERVE_ENERGY, + BAKE_LINEAR_COLOR, BAKE_MAX }; @@ -50,6 +51,10 @@ private: float cell_extra_margin; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; + float saturation; int bounces; bool transfer_only_uv2; Format format; @@ -99,6 +104,18 @@ public: void set_normal_damp(float p_margin); float get_normal_damp() const; + void set_tint(float p_margin); + float get_tint() const; + + void set_saturation(float p_saturation); + float get_saturation() const; + + void set_ao_radius(float p_ao_radius); + float get_ao_radius() const; + + void set_ao_strength(float p_ao_strength); + float get_ao_strength() const; + void set_bake_flag(BakeFlags p_flags,bool p_enable); bool get_bake_flag(BakeFlags p_flags) const; @@ -114,6 +131,14 @@ public: void set_octree(const DVector<uint8_t>& p_octree); DVector<uint8_t> get_octree() const; + void set_light(const DVector<uint8_t>& p_light); + DVector<uint8_t> get_light() const; + + void set_sampler_octree(const DVector<int>& p_sampler_octree); + DVector<int> get_sampler_octree() const; + + + void add_lightmap(const Ref<Texture> &p_texture,Size2 p_gen_size=Size2(256,256)); void set_lightmap_gen_size(int p_idx,const Size2& p_size); Size2 get_lightmap_gen_size(int p_idx) const; diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 056be87e72..d6a9db690b 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -54,9 +54,7 @@ void CircleShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CircleShape2D::set_radius); ObjectTypeDB::bind_method(_MD("get_radius"),&CircleShape2D::get_radius); - - - ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius"),_SCS("set_radius"),_SCS("get_radius") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.5"),_SCS("set_radius"),_SCS("get_radius") ); } diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index ae2c07ff56..7c2fa4d6f4 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -134,7 +134,7 @@ Vector2 Curve2D::interpolate(int p_index, float p_offset) const { Vector2 Curve2D::interpolatef(real_t p_findex) const { - if (p_findex>0) + if (p_findex<0) p_findex=0; else if (p_findex>=points.size()) p_findex=points.size(); @@ -485,7 +485,7 @@ Vector2 Curve2D::interpolate(int p_index, float p_offset) const { Vector2 Curve2D::interpolatef(real_t p_findex) const { - if (p_findex>0) + if (p_findex<0) p_findex=0; else if (p_findex>=points.size()) p_findex=points.size(); @@ -541,19 +541,12 @@ void Curve2D::_bake() const { Vector2 pos=points[0].pos; - int point=0; - float ofs=0; List<Vector2> pointlist; for(int i=0;i<points.size()-1;i++) { - float slen=points[i].pos.distance_to(points[i+1].pos); - float divs = slen / bake_interval; - if (divs>1) - divs=1; - - float step = divs*0.1; // 10 substeps ought to be enough? + float step = 0.1; // at least 10 substeps ought to be enough? float p = 0; while(p<1.0) { @@ -956,7 +949,7 @@ Vector3 Curve3D::interpolate(int p_index, float p_offset) const { Vector3 Curve3D::interpolatef(real_t p_findex) const { - if (p_findex>0) + if (p_findex<0) p_findex=0; else if (p_findex>=points.size()) p_findex=points.size(); @@ -1014,19 +1007,12 @@ void Curve3D::_bake() const { Vector3 pos=points[0].pos; - int point=0; - float ofs=0; List<Plane> pointlist; pointlist.push_back(Plane(pos,points[0].tilt)); for(int i=0;i<points.size()-1;i++) { - float slen=points[i].pos.distance_to(points[i+1].pos); - float divs = slen / bake_interval; - if (divs>1) - divs=1; - - float step = divs*0.1; // 10 substeps ought to be enough? + float step = 0.1; // at least 10 substeps ought to be enough? float p = 0; while(p<1.0) { diff --git a/scene/resources/default_theme/arrow_down.png b/scene/resources/default_theme/arrow_down.png Binary files differindex 1e5c04cb0e..bb4c9d6831 100644 --- a/scene/resources/default_theme/arrow_down.png +++ b/scene/resources/default_theme/arrow_down.png diff --git a/scene/resources/default_theme/arrow_right.png b/scene/resources/default_theme/arrow_right.png Binary files differindex 33e0c1965b..e39356dea8 100644 --- a/scene/resources/default_theme/arrow_right.png +++ b/scene/resources/default_theme/arrow_right.png diff --git a/scene/resources/default_theme/button_disabled.png b/scene/resources/default_theme/button_disabled.png Binary files differindex 8bcfa54cc6..e1d25c08fb 100644 --- a/scene/resources/default_theme/button_disabled.png +++ b/scene/resources/default_theme/button_disabled.png diff --git a/scene/resources/default_theme/button_hover.png b/scene/resources/default_theme/button_hover.png Binary files differindex aa3035fe4f..b01af258f0 100644 --- a/scene/resources/default_theme/button_hover.png +++ b/scene/resources/default_theme/button_hover.png diff --git a/scene/resources/default_theme/button_normal.png b/scene/resources/default_theme/button_normal.png Binary files differindex fbccf22636..d10df91b1d 100644 --- a/scene/resources/default_theme/button_normal.png +++ b/scene/resources/default_theme/button_normal.png diff --git a/scene/resources/default_theme/button_pressed.png b/scene/resources/default_theme/button_pressed.png Binary files differindex 882b583081..9d627936e6 100644 --- a/scene/resources/default_theme/button_pressed.png +++ b/scene/resources/default_theme/button_pressed.png diff --git a/scene/resources/default_theme/checked.png b/scene/resources/default_theme/checked.png Binary files differindex 171c61b6e5..a41b33cccf 100644 --- a/scene/resources/default_theme/checked.png +++ b/scene/resources/default_theme/checked.png diff --git a/scene/resources/default_theme/close_hl.png b/scene/resources/default_theme/close_hl.png Binary files differindex 835790e9e9..0f3be4a320 100644 --- a/scene/resources/default_theme/close_hl.png +++ b/scene/resources/default_theme/close_hl.png diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index d10bb37f60..7d5981522e 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -65,7 +65,7 @@ static Ref<Texture> make_icon(T p_src) { Ref<ImageTexture> texture( memnew( ImageTexture ) ); - texture->create_from_image( Image(p_src) ); + texture->create_from_image( Image(p_src),ImageTexture::FLAG_FILTER ); return texture; } @@ -168,8 +168,6 @@ void make_default_theme() { tex_cache = memnew( TexCacheMap ); - uint32_t last=OS::get_singleton()->get_ticks_msec(); - Ref<Theme> t( memnew( Theme ) ); //Ref<Font> default_font = make_font(_bi_font_normal_height,_bi_font_normal_ascent,_bi_font_normal_valign,_bi_font_normal_charcount,_bi_font_normal_characters,make_icon(font_normal_png)); @@ -177,166 +175,274 @@ void make_default_theme() { Ref<Font> source_font=make_font2(_builtin_source_font_height,_builtin_source_font_ascent,_builtin_source_font_charcount,&_builtin_source_font_charrects[0][0],_builtin_source_font_kerning_pair_count,&_builtin_source_font_kerning_pairs[0][0],_builtin_source_font_img_width,_builtin_source_font_img_height,_builtin_source_font_img_data); Ref<Font> large_font=make_font2(_builtin_large_font_height,_builtin_large_font_ascent,_builtin_large_font_charcount,&_builtin_large_font_charrects[0][0],_builtin_large_font_kerning_pair_count,&_builtin_large_font_kerning_pairs[0][0],_builtin_large_font_img_width,_builtin_large_font_img_height,_builtin_large_font_img_data); + // Font Colors + + Color control_font_color = Color::html("e0e0e0"); + Color control_font_color_low = Color::html("b0b0b0"); + Color control_font_color_hover = Color::html("f0f0f0"); + Color control_font_color_disabled = Color(0.9,0.9,0.9,0.2); + Color control_font_color_pressed = Color::html("ffffff"); + Color font_color_selection = Color::html("7d7d7d"); + + + // Panel + t->set_stylebox("panel","Panel", make_stylebox( panel_bg_png,0,0,0,0) ); - Color control_font_color = Color::html("cfc9d5"); - Color control_font_color_low = Color::html("bab4c1"); - Color control_font_color_hover = Color::html("ffffff"); - Color control_font_color_disabled = Color(0.9,0.9,0.9,0.6); - Color control_font_color_pressed = Color::html("bfb9c5"); - Color font_color_selection = Color::html("715e7d"); - Ref<Texture> empty_icon = memnew( ImageTexture ); - t->set_stylebox("normal","Button", make_stylebox( button_normal_png,5,5,5,5,8,3,8,4) ); - t->set_stylebox("pressed","Button", make_stylebox( button_pressed_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("hover","Button", make_stylebox( button_hover_png,5,5,5,5,3,0,3,0) ); - t->set_stylebox("disabled","Button", make_stylebox( button_disabled_png,5,5,5,5,3,3,3,3) ); - Ref<StyleBoxTexture> focus = make_stylebox( focus_png,6,6,6,6,3,3,3,3); + + // Focus + + Ref<StyleBoxTexture> focus = make_stylebox( focus_png,5,5,5,5); for(int i=0;i<4;i++) { focus->set_expand_margin_size(Margin(i),2); } + + + + // Button + + t->set_stylebox("normal","Button", make_stylebox( button_normal_png,4,4,4,4,8,4,8,4) ); + t->set_stylebox("pressed","Button", make_stylebox( button_pressed_png,4,4,4,4) ); + t->set_stylebox("hover","Button", make_stylebox( button_hover_png,4,4,4,4) ); + t->set_stylebox("disabled","Button", make_stylebox( button_disabled_png,4,4,4,4) ); t->set_stylebox("focus","Button", focus ); + t->set_font("font","Button", default_font ); + t->set_color("font_color","Button", control_font_color ); t->set_color("font_color_pressed","Button", control_font_color_pressed ); t->set_color("font_color_hover","Button", control_font_color_hover ); t->set_color("font_color_disabled","Button", control_font_color_disabled ); - t->set_constant("hseparation","Button", 2 ); + + t->set_constant("hseparation","Button", 2); - t->set_stylebox("normal","ColorPickerButton", make_stylebox( button_normal_png,7,7,7,7,8,3,8,3) ); - t->set_stylebox("pressed","ColorPickerButton", make_stylebox( button_pressed_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("hover","ColorPickerButton", make_stylebox( button_hover_png,4,4,4,4,3,3,3,3) ); - t->set_stylebox("disabled","ColorPickerButton", make_stylebox( button_disabled_png,4,4,4,4,3,3,3,3) ); - t->set_stylebox("focus","ColorPickerButton", make_stylebox( focus_png,5,5,5,5,3,3,3,3) ); + + // ColorPickerButton + + t->set_stylebox("normal","ColorPickerButton", make_stylebox( button_normal_png,4,4,4,4) ); + t->set_stylebox("pressed","ColorPickerButton", make_stylebox( button_pressed_png,4,4,4,4) ); + t->set_stylebox("hover","ColorPickerButton", make_stylebox( button_hover_png,4,4,4,4) ); + t->set_stylebox("disabled","ColorPickerButton", make_stylebox( button_disabled_png,4,4,4,4) ); + t->set_stylebox("focus","ColorPickerButton", focus ); + t->set_font("font","ColorPickerButton", default_font ); + t->set_color("font_color","ColorPickerButton", Color(1,1,1,1) ); t->set_color("font_color_pressed","ColorPickerButton", Color(0.8,0.8,0.8,1) ); t->set_color("font_color_hover","ColorPickerButton", Color(1,1,1,1) ); - t->set_color("font_color_disabled","ColorPickerButton", Color(0.9,0.9,0.9,0.6) ); + t->set_color("font_color_disabled","ColorPickerButton", Color(0.9,0.9,0.9,0.3) ); + t->set_constant("hseparation","ColorPickerButton", 2 ); - t->set_stylebox("normal","ToolButton", make_empty_stylebox(5,3,5,3) ); - t->set_stylebox("pressed","ToolButton", make_stylebox( button_pressed_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("hover","ToolButton", make_stylebox( button_normal_png,5,5,5,5,3,3,3,3) ); - //t->set_stylebox("disabled","ToolButton", make_stylebox( button_disabled_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("disabled","ToolButton", make_empty_stylebox(3,3,3,3) ); - t->set_stylebox("focus","ToolButton", make_stylebox( focus_png,5,5,5,5,3,3,3,3) ); + // ToolButton + + Ref<StyleBox> tb_empty = memnew( StyleBoxEmpty ); + tb_empty->set_default_margin(MARGIN_LEFT,8); + tb_empty->set_default_margin(MARGIN_RIGHT,8); + tb_empty->set_default_margin(MARGIN_TOP,4); + tb_empty->set_default_margin(MARGIN_BOTTOM,4); + + t->set_stylebox("normal","ToolButton", tb_empty); + t->set_stylebox("pressed","ToolButton", make_stylebox( button_pressed_png,4,4,4,4) ); + t->set_stylebox("hover","ToolButton", make_stylebox( button_normal_png,4,4,4,4) ); + t->set_stylebox("disabled","ToolButton", make_empty_stylebox(4,4,4,4) ); + t->set_stylebox("focus","ToolButton", focus ); + t->set_font("font","ToolButton", default_font ); + t->set_color("font_color","ToolButton", control_font_color ); t->set_color("font_color_pressed","ToolButton", control_font_color_pressed ); t->set_color("font_color_hover","ToolButton", control_font_color_hover ); - t->set_color("font_color_disabled","ToolButton", Color(0.9,0.95,1,0.6) ); - t->set_constant("hseparation","ToolButton", 2 ); + t->set_color("font_color_disabled","ToolButton", Color(0.9,0.95,1,0.3) ); + + t->set_constant("hseparation","ToolButton", 0 ); + + - t->set_stylebox("normal","OptionButton", make_stylebox( option_button_normal_png,4,4,20,5,8,3,20,4) ); - t->set_stylebox("pressed","OptionButton", make_stylebox( option_button_pressed_png,4,4,20,5,3,3,3,3) ); - t->set_stylebox("hover","OptionButton", make_stylebox( option_button_hover_png,4,4,20,5,3,3,3,3) ); - t->set_stylebox("disabled","OptionButton", make_stylebox( option_button_disabled_png,4,4,20,5,3,3,3,3) ); + // OptionButton + + t->set_stylebox("normal","OptionButton", make_stylebox( option_button_normal_png,5,5,21,5,8,4,8,4) ); + t->set_stylebox("pressed","OptionButton", make_stylebox( option_button_pressed_png,5,5,21,5) ); + t->set_stylebox("hover","OptionButton", make_stylebox( option_button_hover_png,5,5,21,5) ); + t->set_stylebox("disabled","OptionButton", make_stylebox( option_button_disabled_png,5,5,21,5) ); t->set_stylebox("focus","OptionButton", focus ); - t->set_constant("arrow_margin","OptionButton", 1 ); + t->set_icon("arrow","OptionButton", make_icon( option_arrow_png ) ); t->set_font("font","OptionButton", default_font ); + t->set_color("font_color","OptionButton", control_font_color ); t->set_color("font_color_pressed","OptionButton", control_font_color_pressed ); t->set_color("font_color_hover","OptionButton", control_font_color_hover ); t->set_color("font_color_disabled","OptionButton", control_font_color_disabled ); t->set_constant("hseparation","OptionButton", 2 ); + t->set_constant("arrow_margin","OptionButton", 2 ); - t->set_stylebox("normal","MenuButton", make_stylebox( button_normal_png,6,6,6,6,3,3,3,3) ); - t->set_stylebox("pressed","MenuButton", make_stylebox( tool_button_pressed_png ,6,6,6,6,3,3,3,3) ); - t->set_stylebox("hover","MenuButton", make_stylebox( button_normal_png,6,6,6,6,3,3,3,3) ); + + + // MenuButton + + t->set_stylebox("normal","MenuButton", make_stylebox( button_normal_png,4,4,4,4,8,4,8,4) ); + t->set_stylebox("pressed","MenuButton", make_stylebox( tool_button_pressed_png ,4,4,4,4) ); + t->set_stylebox("hover","MenuButton", make_stylebox( button_normal_png,4,4,4,4) ); t->set_stylebox("disabled","MenuButton", make_empty_stylebox(0,0,0,0) ); + t->set_font("font","MenuButton", default_font ); + t->set_color("font_color","MenuButton", control_font_color ); t->set_color("font_color_pressed","MenuButton", control_font_color_pressed ); t->set_color("font_color_hover","MenuButton", control_font_color_hover ); t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) ); - t->set_stylebox("focus","OptionButton", Ref<StyleBox>( memnew( StyleBoxEmpty )) ); - t->set_constant("hseparation","MenuButton", 2 ); + t->set_constant("hseparation","MenuButton", 0 ); + + // CheckBox + + Ref<StyleBox> cbx_empty = memnew( StyleBoxEmpty ); + cbx_empty->set_default_margin(MARGIN_LEFT,22); + cbx_empty->set_default_margin(MARGIN_RIGHT,4); + cbx_empty->set_default_margin(MARGIN_TOP,4); + cbx_empty->set_default_margin(MARGIN_BOTTOM,5); + Ref<StyleBox> cbx_focus = focus; + cbx_focus->set_default_margin(MARGIN_LEFT,4); + cbx_focus->set_default_margin(MARGIN_RIGHT,22); + cbx_focus->set_default_margin(MARGIN_TOP,4); + cbx_focus->set_default_margin(MARGIN_BOTTOM,5); + + t->set_stylebox("normal","CheckBox", cbx_empty ); + t->set_stylebox("pressed","CheckBox", cbx_empty ); + t->set_stylebox("disabled","CheckBox", cbx_empty ); + t->set_stylebox("hover","CheckBox", cbx_empty ); + t->set_stylebox("focus","CheckBox", cbx_focus ); + + t->set_icon("checked", "CheckBox", make_icon(checked_png)); + t->set_icon("unchecked", "CheckBox", make_icon(unchecked_png)); + t->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png)); + t->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png)); + + t->set_font("font","CheckBox", default_font ); + + t->set_color("font_color","CheckBox", control_font_color ); + t->set_color("font_color_pressed","CheckBox", control_font_color_pressed ); + t->set_color("font_color_hover","CheckBox", control_font_color_hover ); + t->set_color("font_color_disabled","CheckBox", control_font_color_disabled ); + + t->set_constant("hseparation","CheckBox",4); + t->set_constant("check_vadjust","CheckBox",0); + + + + // CheckButton Ref<StyleBox> cb_empty = memnew( StyleBoxEmpty ); + cb_empty->set_default_margin(MARGIN_LEFT,6); cb_empty->set_default_margin(MARGIN_RIGHT,70); cb_empty->set_default_margin(MARGIN_TOP,4); - cb_empty->set_default_margin(MARGIN_BOTTOM,4); + cb_empty->set_default_margin(MARGIN_BOTTOM,4); + t->set_stylebox("normal","CheckButton", cb_empty ); t->set_stylebox("pressed","CheckButton", cb_empty ); t->set_stylebox("disabled","CheckButton", cb_empty ); t->set_stylebox("hover","CheckButton", cb_empty ); - //t->set_stylebox("hover","CheckButton", make_stylebox( button_hover_png,5,5,5,5,3,3,3,3) ); + t->set_stylebox("focus","CheckButton", focus ); + + t->set_icon("on","CheckButton", make_icon(toggle_on_png) ); + t->set_icon("off","CheckButton", make_icon(toggle_off_png)); + t->set_font("font","CheckButton", default_font ); + t->set_color("font_color","CheckButton", control_font_color ); t->set_color("font_color_pressed","CheckButton", control_font_color_pressed ); t->set_color("font_color_hover","CheckButton", control_font_color_hover ); t->set_color("font_color_disabled","CheckButton", control_font_color_disabled ); - t->set_icon("on","CheckButton", make_icon(toggle_on_png) ); - t->set_icon("off","CheckButton", make_icon(toggle_off_png)); - t->set_stylebox("focus","CheckButton", focus ); + t->set_constant("hseparation","CheckButton",4); t->set_constant("check_vadjust","CheckButton",0); + + + // Label t->set_font("font","Label", default_font ); + t->set_color("font_color","Label", Color(1,1,1) ); t->set_color("font_color_shadow","Label", Color(0,0,0,0) ); + t->set_constant("shadow_offset_x","Label", 1 ); t->set_constant("shadow_offset_y","Label", 1 ); t->set_constant("shadow_as_outline","Label", 0 ); - t->set_stylebox("normal","LineEdit", make_stylebox( line_edit_png,4,4,4,4,3,4,3,4) ); - t->set_stylebox("focus","LineEdit", focus ); - t->set_stylebox("read_only","LineEdit", make_stylebox( line_edit_disabled_png,6,6,6,6,4,4,4,4) ); - Image n(line_edit_png); - Image nf(line_edit_focus_png); + // LineEdit + + t->set_stylebox("normal","LineEdit", make_stylebox( line_edit_png,5,5,5,5) ); + t->set_stylebox("focus","LineEdit", focus ); + t->set_stylebox("read_only","LineEdit", make_stylebox( line_edit_disabled_png,6,6,6,6) ); t->set_font("font","LineEdit", default_font ); + t->set_color("font_color","LineEdit", control_font_color ); t->set_color("font_color_selected","LineEdit", Color(0,0,0) ); t->set_color("cursor_color","LineEdit", control_font_color_hover ); t->set_color("selection_color","LineEdit", font_color_selection ); - t->set_constant("minimum_spaces","LineEdit", 8 ); - t->set_stylebox("bg","ProgressBar", make_stylebox( progress_bar_png,5,5,5,5,0,0,0,0) ); - t->set_stylebox("fg","ProgressBar", make_stylebox( progress_fill_png,5,5,5,5,2,2,2,2) ); + t->set_constant("minimum_spaces","LineEdit", 12 ); + + + + // ProgressBar + + t->set_stylebox("bg","ProgressBar", make_stylebox( progress_bar_png,4,4,4,4,0,0,0,0) ); + t->set_stylebox("fg","ProgressBar", make_stylebox( progress_fill_png,6,6,6,6,2,1,2,1) ); + t->set_font("font","ProgressBar", default_font ); - t->set_color("font_color","ProgressBar", control_font_color ); + + t->set_color("font_color","ProgressBar", control_font_color_hover ); t->set_color("font_color_shadow","ProgressBar", Color(0,0,0) ); - t->set_icon("tab","TextEdit", make_icon( tab_png) ); - t->set_stylebox("normal","TextEdit", make_stylebox( tree_bg_png,12,12,12,12,3,3,3,3) ); - t->set_stylebox("focus","TextEdit", focus ); - t->set_stylebox("completion","TextEdit", make_stylebox( tree_bg_png,4,4,4,5,3,3,3,3) ); - t->set_constant("completion_lines","TextEdit", 7 ); - t->set_constant("completion_max_width","TextEdit", 50 ); - t->set_constant("completion_scroll_width","TextEdit", 3 ); - t->set_color("completion_scroll_color","TextEdit", control_font_color_pressed ); - t->set_color("completion_existing","TextEdit", control_font_color ); + // TextEdit - //t->set_font("font","TextEdit", mono_font ); + t->set_stylebox("normal","TextEdit", make_stylebox( tree_bg_png,3,3,3,3) ); + t->set_stylebox("focus","TextEdit", focus ); + t->set_stylebox("completion","TextEdit", make_stylebox( tree_bg_png,3,3,3,3) ); + + t->set_icon("tab","TextEdit", make_icon( tab_png) ); t->set_font("font","TextEdit", default_font ); + + t->set_color("completion_scroll_color","TextEdit", control_font_color_pressed ); + t->set_color("completion_existing","TextEdit", control_font_color ); t->set_color("font_color","TextEdit", control_font_color ); t->set_color("font_color_selected","TextEdit", Color(0,0,0) ); t->set_color("selection_color","TextEdit", font_color_selection ); t->set_color("mark_color","TextEdit", Color(1.0,0.4,0.4,0.4) ); - t->set_color("breakpoint_color","TextEdit", Color(0.8,0.8,0.4,0.4) ); - t->set_color("current_line_color","TextEdit", Color(0.3,0.5,0.8,0.15) ); + t->set_color("breakpoint_color","TextEdit", Color(0.8,0.8,0.4,0.2) ); + t->set_color("current_line_color","TextEdit", Color(0.25,0.25,0.26,0.8) ); t->set_color("cursor_color","TextEdit", control_font_color ); t->set_color("symbol_color","TextEdit", control_font_color_hover ); - t->set_constant("line_spacing","TextEdit",1 ); + t->set_color("brace_mismatch_color","TextEdit", Color(1,0.2,0.2) ); + + t->set_constant("completion_lines","TextEdit", 7 ); + t->set_constant("completion_max_width","TextEdit", 50 ); + t->set_constant("completion_scroll_width","TextEdit", 3 ); + t->set_constant("line_spacing","TextEdit",4 ); + - t->set_stylebox("scroll","HScrollBar", make_stylebox( hscroll_bg_png,3,3,3,3,0,0,0,0) ); - t->set_stylebox("scroll_focus","HScrollBar", make_stylebox( hscroll_bg_png,3,3,3,3,0,0,0,0) ); - t->set_stylebox("grabber","HScrollBar", make_stylebox( hscroll_grabber_png,3,3,3,3,2,2,2,2) ); - t->set_stylebox("grabber_hilite","HScrollBar", make_stylebox( hscroll_grabber_hl_png,3,3,3,3,2,2,2,2) ); + Ref<Texture> empty_icon = memnew( ImageTexture ); + + // HScrollBar + + t->set_stylebox("scroll","HScrollBar", make_stylebox( scroll_bg_png,3,3,3,3,0,0,0,0) ); + t->set_stylebox("scroll_focus","HScrollBar", make_stylebox( scroll_bg_png,3,3,3,3,0,0,0,0) ); + t->set_stylebox("grabber","HScrollBar", make_stylebox( scroll_grabber_png,3,3,3,3,2,2,2,2) ); + t->set_stylebox("grabber_hilite","HScrollBar", make_stylebox( scroll_grabber_hl_png,3,3,3,3,2,2,2,2) ); t->set_icon("increment","HScrollBar",empty_icon); t->set_icon("increment_hilite","HScrollBar",empty_icon); @@ -344,129 +450,186 @@ void make_default_theme() { t->set_icon("decrement_hilite","HScrollBar",empty_icon); - t->set_stylebox("scroll","VScrollBar", make_stylebox( vscroll_bg_png,3,3,3,3,0,0,0,0) ); - t->set_stylebox("scroll_focus","VScrollBar", make_stylebox( vscroll_bg_png,3,3,3,3,0,0,0,0) ); - t->set_stylebox("grabber","VScrollBar", make_stylebox( vscroll_grabber_png,3,3,3,3,2,2,2,2) ); - t->set_stylebox("grabber_hilite","VScrollBar", make_stylebox( vscroll_grabber_hl_png,3,3,3,3,2,2,2,2) ); + + // VScrollBar + + t->set_stylebox("scroll","VScrollBar", make_stylebox( scroll_bg_png,3,3,3,3,0,0,0,0) ); + t->set_stylebox("scroll_focus","VScrollBar", make_stylebox( scroll_bg_png,3,3,3,3,0,0,0,0) ); + t->set_stylebox("grabber","VScrollBar", make_stylebox( scroll_grabber_png,3,3,3,3,2,2,2,2) ); + t->set_stylebox("grabber_hilite","VScrollBar", make_stylebox( scroll_grabber_hl_png,3,3,3,3,2,2,2,2) ); + t->set_icon("increment","VScrollBar",empty_icon); t->set_icon("increment_hilite","VScrollBar",empty_icon); t->set_icon("decrement","VScrollBar",empty_icon); t->set_icon("decrement_hilite","VScrollBar",empty_icon); - t->set_stylebox("slider","HSlider", make_stylebox( hslider_bg_png,5,5,5,5,1,1,1,1) ); - t->set_stylebox("focus","HSlider", make_stylebox( focus_png,3,3,3,3,1,1,1,1) ); - //t->set_stylebox("slider_focus","HSlider", make_stylebox( hslider_bg_focus_png,6,6,6,6,2,2,2,2) ); + + + // HSlider + + t->set_stylebox("slider","HSlider", make_stylebox( hslider_bg_png,4,4,4,4) ); + t->set_stylebox("grabber_hilite","HSlider", make_stylebox( hslider_grabber_hl_png,6,6,6,6) ); + t->set_stylebox("focus","HSlider", focus ); + t->set_icon("grabber","HSlider", make_icon( hslider_grabber_png ) ); t->set_icon("grabber_hilite","HSlider", make_icon( hslider_grabber_hl_png ) ); t->set_icon("tick","HSlider", make_icon( hslider_tick_png ) ); - t->set_stylebox("grabber_hilite","HSlider", make_stylebox( hslider_grabber_hl_png,6,6,6,6,2,2,2,2) ); - t->set_stylebox("slider","VSlider", make_stylebox( vslider_bg_png,5,5,5,5,1,1,1,1) ); - t->set_stylebox("focus","HSlider", make_stylebox( focus_png,3,3,3,3,1,1,1,1) ); - //t->set_stylebox("slider_focus","VSlider", make_stylebox( vslider_bg_focus_png,6,6,6,6,2,2,2,2) ); + + + + // VSlider + + t->set_stylebox("slider","VSlider", make_stylebox( vslider_bg_png,4,4,4,4) ); + t->set_stylebox("grabber_hilite","VSlider", make_stylebox( vslider_grabber_hl_png,6,6,6,6) ); + t->set_stylebox("focus","HSlider", focus ); + t->set_icon("grabber","VSlider", make_icon( vslider_grabber_png) ); t->set_icon("grabber_hilite","VSlider", make_icon( vslider_grabber_hl_png ) ); t->set_icon("tick","VSlider", make_icon( vslider_tick_png ) ); - t->set_stylebox("grabber_hilite","VSlider", make_stylebox( vslider_grabber_hl_png,6,6,6,6,2,2,2,2) ); + + + + // SpinBox t->set_icon("updown","SpinBox",make_icon(spinbox_updown_png)); - Ref<StyleBoxTexture> style_pp_win = make_stylebox( popup_window_png,6,28,6,7,8,8,8,8); + + // WindowDialog + + Ref<StyleBoxTexture> style_pp_win = make_stylebox( popup_window_png,6,28,6,7); for(int i=0;i<4;i++) style_pp_win->set_expand_margin_size((Margin)i,3); style_pp_win->set_expand_margin_size(MARGIN_TOP,26); + t->set_stylebox("panel","WindowDialog", style_pp_win ); - t->set_constant("titlebar_height","WindowDialog", 18 ); - t->set_constant("title_height","WindowDialog", 20 ); - t->set_font("title_font","WindowDialog", large_font ); - t->set_color("title_color","WindowDialog", Color(0,0,0) ); + t->set_icon("close","WindowDialog", make_icon( close_png ) ); t->set_icon("close_hilite","WindowDialog", make_icon( close_hl_png ) ); + + t->set_font("title_font","WindowDialog", large_font ); + + t->set_color("title_color","WindowDialog", Color(0,0,0) ); + t->set_constant("close_h_ofs","WindowDialog", 22 ); t->set_constant("close_v_ofs","WindowDialog", 20 ); + t->set_constant("titlebar_height","WindowDialog", 18 ); + t->set_constant("title_height","WindowDialog", 20 ); - Ref<StyleBoxTexture> style_pp = make_stylebox( popup_bg_png,6,19,6,7,8,8,8,8); - style_pp->set_expand_margin_size(MARGIN_LEFT,2); - style_pp->set_expand_margin_size(MARGIN_TOP,3); - style_pp->set_expand_margin_size(MARGIN_RIGHT,2); - style_pp->set_expand_margin_size(MARGIN_BOTTOM,3); + // Popup - t->set_stylebox("panel","PopupMenu", style_pp ); - t->set_stylebox("panel","PopupPanel", style_pp ); + Ref<StyleBoxTexture> style_pp = make_stylebox( popup_bg_png,4,4,4,4,8,8,8,8); Ref<StyleBoxTexture> selected = make_stylebox( selection_png,6,6,6,6); for(int i=0;i<4;i++) { selected->set_expand_margin_size(Margin(i),2); } - t->set_stylebox("panel_disabled","PopupMenu", make_stylebox( popup_bg_disabled_png,5,5,5,5) ); + t->set_stylebox("panel","PopupPanel", style_pp ); + + + + + // PopupMenu + + t->set_stylebox("panel","PopupMenu", make_stylebox( popup_bg_png,4,4,4,4,10,10,10,10) ); + t->set_stylebox("panel_disabled","PopupMenu", make_stylebox( popup_bg_disabled_png,4,4,4,4) ); t->set_stylebox("hover","PopupMenu", selected ); t->set_stylebox("separator","PopupMenu", make_stylebox( vseparator_png,3,3,3,3) ); - t->set_icon("checked","PopupMenu", make_icon(popup_checked_png) ); - t->set_icon("unchecked","PopupMenu", make_icon(popup_unchecked_png) ); + + t->set_icon("checked","PopupMenu", make_icon(checked_png) ); + t->set_icon("unchecked","PopupMenu", make_icon(unchecked_png) ); t->set_icon("submenu","PopupMenu", make_icon(submenu_png) ); + t->set_font("font","PopupMenu", default_font ); + t->set_color("font_color","PopupMenu", control_font_color ); t->set_color("font_color_accel","PopupMenu", Color(0.7,0.7,0.7,0.8) ); t->set_color("font_color_disabled","PopupMenu", Color(0.4,0.4,0.4,0.8) ); t->set_color("font_color_hover","PopupMenu", control_font_color ); - t->set_constant("hseparation","PopupMenu",2); - t->set_constant("vseparation","PopupMenu",1); - - t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5,3,3,3,3) ); + + t->set_constant("hseparation","PopupMenu",4); + t->set_constant("vseparation","PopupMenu",4); + + + // GraphNode + + Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5); + //graphsb->set_expand_margin_size(MARGIN_LEFT,10); + //graphsb->set_expand_margin_size(MARGIN_RIGHT,10); + t->set_stylebox("frame","GraphNode", graphsb ); + t->set_constant("separation","GraphNode", 1 ); + t->set_icon("port","GraphNode", make_icon( graph_port_png ) ); + t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) ); + t->set_font("title_font","GraphNode", default_font ); + t->set_color("title_color","GraphNode", Color(0,0,0,1)); + t->set_constant("title_offset","GraphNode", 18); + t->set_constant("close_offset","GraphNode", 18); + t->set_constant("port_offset","GraphNode", 3); + + + // Tree + + Ref<StyleBoxTexture> tree_selected = make_stylebox( selection_png,4,4,4,4,8,0,8,0); + Ref<StyleBoxTexture> tree_selected_oof = make_stylebox( selection_oof_png,4,4,4,4,8,0,8,0); + + t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5) ); t->set_stylebox("bg_focus","Tree", focus ); - Ref<StyleBoxTexture> tree_selected = make_stylebox( selection_png,4,4,4,4); - Ref<StyleBoxTexture> tree_selected_oof = make_stylebox( selection_oof_png,4,4,4,4); - for(int i=0;i<4;i++) { - tree_selected->set_expand_margin_size(Margin(i),2); - tree_selected_oof->set_expand_margin_size(Margin(i),2); - } t->set_stylebox("selected","Tree", tree_selected_oof ); t->set_stylebox("selected_focus","Tree", tree_selected ); - t->set_stylebox("completion_selected","TextEdit", tree_selected ); - - t->set_stylebox("cursor","Tree", focus ); t->set_stylebox("cursor_unfocused","Tree", focus ); - t->set_stylebox("button_pressed","Tree",make_stylebox( button_pressed_png,5,5,5,5,3,3,3,3)); + t->set_stylebox("button_pressed","Tree",make_stylebox( button_pressed_png,4,4,4,4)); + t->set_stylebox("title_button_normal","Tree", make_stylebox( tree_title_png,4,4,4,4) ); + t->set_stylebox("title_button_pressed","Tree", make_stylebox( tree_title_pressed_png,4,4,4,4) ); + t->set_stylebox("title_button_hover","Tree", make_stylebox( tree_title_png,4,4,4,4) ); + + t->set_icon("checked","Tree",make_icon(checked_png)); + t->set_icon("unchecked","Tree",make_icon(unchecked_png)); + t->set_icon("updown","Tree",make_icon(updown_png)); + t->set_icon("select_arrow","Tree",make_icon(dropdown_png)); + t->set_icon("arrow","Tree",make_icon(arrow_down_png)); + t->set_icon("arrow_collapsed","Tree",make_icon(arrow_right_png)); + + t->set_font("title_button_font","Tree", default_font ); t->set_font("font","Tree", default_font ); + + t->set_color("title_button_color","Tree", control_font_color ); t->set_color("font_color","Tree", control_font_color_low ); - t->set_color("font_color_selected","Tree", control_font_color ); + t->set_color("font_color_selected","Tree", control_font_color_pressed ); t->set_color("selection_color","Tree", Color(0.1,0.1,1,0.8) ); t->set_color("cursor_color","Tree", Color(0,0,0) ); t->set_color("guide_color","Tree", Color(0,0,0,0.1) ); - t->set_constant("hseparation","Tree",2); - t->set_constant("vseparation","Tree",1); - t->set_constant("guide_width","Tree",1); + + t->set_constant("hseparation","Tree",4); + t->set_constant("vseparation","Tree",2); + t->set_constant("guide_width","Tree",2); t->set_constant("item_margin","Tree",12); - t->set_constant("button_margin","Tree",2); + t->set_constant("button_margin","Tree",4); - t->set_stylebox("title_button_normal","Tree", make_stylebox( tree_title_png,4,4,4,4,3,3,3,3) ); - t->set_stylebox("title_button_pressed","Tree", make_stylebox( tree_title_pressed_png,4,4,4,4,3,3,3,3) ); - t->set_stylebox("title_button_hover","Tree", make_stylebox( tree_title_png,4,4,4,4,3,3,3,3) ); - t->set_color("title_button_color","Tree", control_font_color ); - t->set_font("title_button_font","Tree", default_font ); - t->set_icon("checked","Tree",make_icon(checked_png)); - t->set_icon("unchecked","Tree",make_icon(unchecked_png)); - t->set_icon("updown","Tree",make_icon(updown_png)); - t->set_icon("select_arrow","Tree",make_icon(dropdown_png)); - t->set_icon("arrow","Tree",make_icon(arrow_down_png)); - t->set_icon("arrow_collapsed","Tree",make_icon(arrow_right_png)); + // TextEdit + + t->set_stylebox("completion_selected","TextEdit", tree_selected ); + + - t->set_stylebox("tab_fg","TabContainer", make_stylebox( tab_current_png,5,5,5,5,8,3,8,3) ); - t->set_stylebox("tab_bg","TabContainer", make_stylebox( tab_behind_png,5,5,5,5,8,4,8,3) ); - Ref<StyleBoxTexture> tc_sb = make_stylebox( tab_container_bg_png,6,19,6,7); + // TabContainer + + Ref<StyleBoxTexture> tc_sb = make_stylebox( tab_container_bg_png,4,4,4,4); for(int i=0;i<4;i++) { - tc_sb->set_default_margin(Margin(i),7); + tc_sb->set_default_margin(Margin(i),4); tc_sb->set_expand_margin_size(Margin(i),2); } - //tc_sb->set_expand_margin_size(MARGIN_TOP,2); - //tc_sb->set_default_margin(MARGIN_TOP,6); + tc_sb->set_expand_margin_size(MARGIN_TOP,2); + tc_sb->set_default_margin(MARGIN_TOP,8); + + t->set_stylebox("tab_fg","TabContainer", make_stylebox( tab_current_png,4,4,4,4,16,4,16,4) ); + t->set_stylebox("tab_bg","TabContainer", make_stylebox( tab_behind_png,4,4,4,4,16,6,16,4) ); t->set_stylebox("panel","TabContainer", tc_sb ); t->set_icon("increment","TabContainer",make_icon( scroll_button_right_png)); @@ -475,116 +638,178 @@ void make_default_theme() { t->set_icon("decrement_hilite","TabContainer",make_icon( scroll_button_left_hl_png)); t->set_font("font","TabContainer", default_font ); + t->set_color("font_color_fg","TabContainer", control_font_color_hover ); - t->set_color("font_color_bg","TabContainer", control_font_color ); - t->set_constant("side_margin","TabContainer", 5 ); + t->set_color("font_color_bg","TabContainer", control_font_color_low ); + + t->set_constant("side_margin","TabContainer", 8 ); t->set_constant("top_margin","TabContainer", 24); - t->set_constant("label_valign_fg","TabContainer", 4); - t->set_constant("label_valign_bg","TabContainer", 5); - t->set_constant("hseparation","TabContainer", 2); + t->set_constant("label_valign_fg","TabContainer", 0); + t->set_constant("label_valign_bg","TabContainer", 2); + t->set_constant("hseparation","TabContainer", 4); + + + + // Tabs + + t->set_stylebox("tab_fg","Tabs", make_stylebox( tab_current_png,4,4,4,4,16,4,16,4) ); + t->set_stylebox("tab_bg","Tabs", make_stylebox( tab_behind_png,4,4,4,4,16,6,16,4) ); + t->set_stylebox("panel","Tabs", make_stylebox( tab_container_bg_png,4,4,4,4) ); - t->set_stylebox("tab_fg","Tabs", make_stylebox( tab_current_png,5,5,5,5,8,3,8,3) ); - t->set_stylebox("tab_bg","Tabs", make_stylebox( tab_behind_png,5,5,5,5,8,4,8,3) ); - t->set_stylebox("panel","Tabs", make_stylebox( tab_container_bg_png,3,3,3,3) ); t->set_font("font","Tabs", default_font ); + t->set_color("font_color_fg","Tabs", control_font_color_hover ); - t->set_color("font_color_bg","Tabs", control_font_color ); + t->set_color("font_color_bg","Tabs", control_font_color_low ); + t->set_constant("top_margin","Tabs", 24); - t->set_constant("label_valign_fg","Tabs", 4); - t->set_constant("label_valign_bg","Tabs", 5); - t->set_constant("hseparation","Tabs", 2); + t->set_constant("label_valign_fg","Tabs", 0); + t->set_constant("label_valign_bg","Tabs", 2); + t->set_constant("hseparation","Tabs", 4); + + + + // Separators t->set_stylebox("separator","HSeparator", make_stylebox( vseparator_png,3,3,3,3) ); - t->set_constant("separation","HSeparator", 7); t->set_stylebox("separator","VSeparator", make_stylebox( hseparator_png,3,3,3,3) ); - t->set_constant("separation","VSeparator", 7); t->set_icon("close","Icons", make_icon(icon_close_png)); t->set_font("source","Fonts", source_font); t->set_font("normal","Fonts", default_font ); t->set_font("large","Fonts", large_font ); + t->set_constant("separation","HSeparator", 4); + t->set_constant("separation","VSeparator", 4); - t->set_constant("margin","Dialogs",10); + // Dialogs + + t->set_constant("margin","Dialogs",8); t->set_constant("button_margin","Dialogs",32); + + + + // FileDialog t->set_icon("folder","FileDialog",make_icon(icon_folder_png)); + t->set_color("files_disabled","FileDialog",Color(0,0,0,0.7)); + + + // colorPicker + t->set_constant("value_height","ColorPicker", 23 ); t->set_constant("value_width","ColorPicker", 50); t->set_constant("color_width","ColorPicker", 100); - t->set_constant("label_width","ColorPicker", 15); + t->set_constant("label_width","ColorPicker", 20); t->set_constant("hseparator","ColorPicker", 4); - Ref<StyleBoxTexture> style_tt = make_stylebox( tooltip_bg_png,9,9,9,9,8,8,8,8); + + + // TooltipPanel + + Ref<StyleBoxTexture> style_tt = make_stylebox( tooltip_bg_png,4,4,4,4); for(int i=0;i<4;i++) style_tt->set_expand_margin_size((Margin)i,4); + t->set_stylebox("panel","TooltipPanel", style_tt ); + t->set_font("font","TooltipLabel", default_font ); + t->set_color("font_color","TooltipLabel", Color(0,0,0) ); t->set_color("font_color_shadow","TooltipLabel", Color(0,0,0,0.1) ); + t->set_constant("shadow_offset_x","TooltipLabel", 1 ); t->set_constant("shadow_offset_y","TooltipLabel", 1 ); + + + // RichTextLabel + + t->set_stylebox("focus","RichTextLabel", focus ); + t->set_font("default_font","RichTextLabel", default_font ); + t->set_color("default_color","RichTextLabel", control_font_color ); t->set_color("font_color_selected","RichTextLabel", font_color_selection ); t->set_color("selection_color","RichTextLabel", Color(0.1,0.1,1,0.8) ); + t->set_constant("line_separation","RichTextLabel", 1 ); - t->set_stylebox("focus","RichTextLabel", focus ); + + // Containers + + t->set_stylebox("bg","VSplitContainer", make_stylebox( vsplit_bg_png,1,1,1,1) ); + t->set_stylebox("bg","HSplitContainer", make_stylebox( hsplit_bg_png,1,1,1,1) ); + + t->set_icon("grabber","VSplitContainer",make_icon(vsplitter_png)); + t->set_icon("grabber","HSplitContainer",make_icon(hsplitter_png)); + t->set_constant("separation","HBoxContainer",4); t->set_constant("separation","VBoxContainer",4); - t->set_constant("margin","MarginContainer",15); - + t->set_constant("margin","MarginContainer",8); t->set_constant("separation","GridContainer",4); - - t->set_constant("separation","HSplitContainer",8); - t->set_constant("separation","VSplitContainer",8); + t->set_constant("separation","HSplitContainer",12); + t->set_constant("separation","VSplitContainer",12); t->set_constant("autohide","HSplitContainer",1); t->set_constant("autohide","VSplitContainer",1); - t->set_icon("grabber","VSplitContainer",make_icon(vsplitter_png)); - t->set_icon("grabber","HSplitContainer",make_icon(hsplitter_png)); - t->set_stylebox("bg","VSplitContainer", make_stylebox( vsplit_bg_png,1,1,1,1,1,1,1,1) ); - t->set_stylebox("bg","HSplitContainer", make_stylebox( hsplit_bg_png,1,1,1,1,1,1,1,1) ); - t->set_stylebox("normal","HButtonArray", make_stylebox( button_normal_png,2,2,2,2,3,3,3,3) ); - t->set_stylebox("selected","HButtonArray", make_stylebox( button_pressed_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("hover","HButtonArray", make_stylebox( button_hover_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("focus","HButtonArray", make_stylebox( focus_png,5,5,5,5,3,3,3,3) ); + + // HButtonArray + + t->set_stylebox("normal","HButtonArray", make_stylebox( button_normal_png,4,4,4,4,0,4,22,4) ); + t->set_stylebox("selected","HButtonArray", make_stylebox( button_pressed_png,4,4,4,4,0,4,22,4) ); + t->set_stylebox("hover","HButtonArray", make_stylebox( button_hover_png,4,4,4,4) ); + t->set_font("font","HButtonArray", default_font); t->set_font("font_selected","HButtonArray", default_font); - t->set_color("font_color","HButtonArray", Color(1,1,1,1) ); - t->set_color("font_color_selected","HButtonArray", Color(0.7,0.7,0.7,1) ); - t->set_constant("icon_separator","HButtonArray", 2 ); - t->set_constant("button_separator","HButtonArray", 3 ); - - t->set_stylebox("normal","VButtonArray", make_stylebox( button_normal_png,2,2,2,2,3,3,3,3) ); - t->set_stylebox("selected","VButtonArray", make_stylebox( button_pressed_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("hover","VButtonArray", make_stylebox( button_hover_png,5,5,5,5,3,3,3,3) ); - t->set_stylebox("focus","VButtonArray", make_stylebox( focus_png,5,5,5,5,3,3,3,3) ); + + t->set_color("font_color","HButtonArray", control_font_color_low ); + t->set_color("font_color_selected","HButtonArray", control_font_color_hover ); + + t->set_constant("icon_separator","HButtonArray", 4 ); + t->set_constant("button_separator","HButtonArray", 8 ); + + t->set_stylebox("focus","HButtonArray", focus ); + + + // VButtonArray + + t->set_stylebox("normal","VButtonArray", make_stylebox( button_normal_png,4,4,4,4,0,4,22,4) ); + t->set_stylebox("selected","VButtonArray", make_stylebox( button_pressed_png,4,4,4,4,0,4,22,4) ); + t->set_stylebox("hover","VButtonArray", make_stylebox( button_hover_png,4,4,4,4) ); + t->set_font("font","VButtonArray", default_font); t->set_font("font_selected","VButtonArray", default_font); - t->set_color("font_color","VButtonArray", Color(1,1,1,1) ); - t->set_color("font_color_selected","VButtonArray", Color(0.7,0.7,0.7,1) ); - t->set_constant("icon_separator","VButtonArray", 2 ); - t->set_constant("button_separator","VButtonArray", 3 ); - t->set_stylebox("border","ReferenceFrame", make_stylebox( reference_border_png,5,5,5,5,3,3,3,3) ); + t->set_color("font_color","VButtonArray", control_font_color_low ); + t->set_color("font_color_selected","VButtonArray", control_font_color_hover ); + + t->set_constant("icon_separator","VButtonArray", 4); + t->set_constant("button_separator","VButtonArray", 8); + + t->set_stylebox("focus","VButtonArray", focus ); + + + // ReferenceFrame Ref<StyleBoxTexture> ttnc = make_stylebox( full_panel_bg_png,8,8,8,8); ttnc->set_draw_center(false); + + t->set_stylebox("border","ReferenceFrame", make_stylebox( reference_border_png,4,4,4,4) ); t->set_stylebox("panelnc","Panel", ttnc ); t->set_stylebox("panelf","Panel", tc_sb ); - t->set_stylebox("panel","PanelContainer", tc_sb ); t->set_icon( "logo","Icons", make_icon(logo_png) ); + + + // Theme + Theme::set_default( t ); Theme::set_default_icon( make_icon(error_icon_png) ); Theme::set_default_style( make_stylebox( error_icon_png,2,2,2,2) ); @@ -611,8 +836,8 @@ void make_default_theme() { style->set_texture(texture); for(int i=0;i<4;i++) { - style->set_margin_size( Margin(),2); - style->set_default_margin( Margin(),2); + style->set_margin_size( Margin(),8); + style->set_default_margin( Margin(),8); } Ref<Font> f = make_default_font(); diff --git a/scene/resources/default_theme/dropdown.png b/scene/resources/default_theme/dropdown.png Binary files differindex 5279e72d24..72fc5d73a3 100644 --- a/scene/resources/default_theme/dropdown.png +++ b/scene/resources/default_theme/dropdown.png diff --git a/scene/resources/default_theme/focus.png b/scene/resources/default_theme/focus.png Binary files differindex 0daf85718f..1656fea188 100644 --- a/scene/resources/default_theme/focus.png +++ b/scene/resources/default_theme/focus.png diff --git a/scene/resources/default_theme/full_panel_bg.png b/scene/resources/default_theme/full_panel_bg.png Binary files differindex b43469a8aa..771e50e2af 100644 --- a/scene/resources/default_theme/full_panel_bg.png +++ b/scene/resources/default_theme/full_panel_bg.png diff --git a/scene/resources/default_theme/graph_node.png b/scene/resources/default_theme/graph_node.png Binary files differnew file mode 100644 index 0000000000..3adccf2c3b --- /dev/null +++ b/scene/resources/default_theme/graph_node.png diff --git a/scene/resources/default_theme/graph_node_close.png b/scene/resources/default_theme/graph_node_close.png Binary files differnew file mode 100644 index 0000000000..ea5b510418 --- /dev/null +++ b/scene/resources/default_theme/graph_node_close.png diff --git a/scene/resources/default_theme/graph_port.png b/scene/resources/default_theme/graph_port.png Binary files differnew file mode 100644 index 0000000000..92f425f977 --- /dev/null +++ b/scene/resources/default_theme/graph_port.png diff --git a/scene/resources/default_theme/hscroll_bg.png b/scene/resources/default_theme/hscroll_bg.png Binary files differdeleted file mode 100644 index 9d6381f0c9..0000000000 --- a/scene/resources/default_theme/hscroll_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/hscroll_bg_focus.png b/scene/resources/default_theme/hscroll_bg_focus.png Binary files differdeleted file mode 100644 index e81a867b87..0000000000 --- a/scene/resources/default_theme/hscroll_bg_focus.png +++ /dev/null diff --git a/scene/resources/default_theme/hscroll_grabber.png b/scene/resources/default_theme/hscroll_grabber.png Binary files differdeleted file mode 100644 index 9015038911..0000000000 --- a/scene/resources/default_theme/hscroll_grabber.png +++ /dev/null diff --git a/scene/resources/default_theme/hscroll_grabber_hl.png b/scene/resources/default_theme/hscroll_grabber_hl.png Binary files differdeleted file mode 100644 index 11c895e9e3..0000000000 --- a/scene/resources/default_theme/hscroll_grabber_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/hslider_bg.png b/scene/resources/default_theme/hslider_bg.png Binary files differindex 2d6c336e18..963e4c8456 100644 --- a/scene/resources/default_theme/hslider_bg.png +++ b/scene/resources/default_theme/hslider_bg.png diff --git a/scene/resources/default_theme/hslider_grabber.png b/scene/resources/default_theme/hslider_grabber.png Binary files differindex 626709dd32..b72ec4d8f4 100644 --- a/scene/resources/default_theme/hslider_grabber.png +++ b/scene/resources/default_theme/hslider_grabber.png diff --git a/scene/resources/default_theme/hslider_grabber_hl.png b/scene/resources/default_theme/hslider_grabber_hl.png Binary files differindex 30b06089c5..0dc5f2b615 100644 --- a/scene/resources/default_theme/hslider_grabber_hl.png +++ b/scene/resources/default_theme/hslider_grabber_hl.png diff --git a/scene/resources/default_theme/hslider_tick.png b/scene/resources/default_theme/hslider_tick.png Binary files differindex 3ba740355e..e8e18b5402 100644 --- a/scene/resources/default_theme/hslider_tick.png +++ b/scene/resources/default_theme/hslider_tick.png diff --git a/scene/resources/default_theme/hsplit_bg.png b/scene/resources/default_theme/hsplit_bg.png Binary files differindex 6147aac10d..34033289d0 100644 --- a/scene/resources/default_theme/hsplit_bg.png +++ b/scene/resources/default_theme/hsplit_bg.png diff --git a/scene/resources/default_theme/hsplitter.png b/scene/resources/default_theme/hsplitter.png Binary files differindex cfd9ab7d93..4173dc02e7 100644 --- a/scene/resources/default_theme/hsplitter.png +++ b/scene/resources/default_theme/hsplitter.png diff --git a/scene/resources/default_theme/icon_folder.png b/scene/resources/default_theme/icon_folder.png Binary files differindex 9ec797a8a5..0abf60253a 100644 --- a/scene/resources/default_theme/icon_folder.png +++ b/scene/resources/default_theme/icon_folder.png diff --git a/scene/resources/default_theme/icon_play.png b/scene/resources/default_theme/icon_play.png Binary files differindex f04a5cd789..40bbce5f0d 100644 --- a/scene/resources/default_theme/icon_play.png +++ b/scene/resources/default_theme/icon_play.png diff --git a/scene/resources/default_theme/icon_stop.png b/scene/resources/default_theme/icon_stop.png Binary files differindex 5ae2851d57..b0fd5caa83 100644 --- a/scene/resources/default_theme/icon_stop.png +++ b/scene/resources/default_theme/icon_stop.png diff --git a/scene/resources/default_theme/line_edit.png b/scene/resources/default_theme/line_edit.png Binary files differindex 3d8b748dff..d0ce0b9d70 100644 --- a/scene/resources/default_theme/line_edit.png +++ b/scene/resources/default_theme/line_edit.png diff --git a/scene/resources/default_theme/line_edit_disabled.png b/scene/resources/default_theme/line_edit_disabled.png Binary files differindex 4507c36857..edb6a7d5fc 100644 --- a/scene/resources/default_theme/line_edit_disabled.png +++ b/scene/resources/default_theme/line_edit_disabled.png diff --git a/scene/resources/default_theme/option_arrow.png b/scene/resources/default_theme/option_arrow.png Binary files differindex 4c04cbc6ad..b0ab74421a 100644 --- a/scene/resources/default_theme/option_arrow.png +++ b/scene/resources/default_theme/option_arrow.png diff --git a/scene/resources/default_theme/option_button_disabled.png b/scene/resources/default_theme/option_button_disabled.png Binary files differindex 6cb7c6f858..6250e34ff8 100644 --- a/scene/resources/default_theme/option_button_disabled.png +++ b/scene/resources/default_theme/option_button_disabled.png diff --git a/scene/resources/default_theme/option_button_hover.png b/scene/resources/default_theme/option_button_hover.png Binary files differindex da0216e813..8962e8aef9 100644 --- a/scene/resources/default_theme/option_button_hover.png +++ b/scene/resources/default_theme/option_button_hover.png diff --git a/scene/resources/default_theme/option_button_normal.png b/scene/resources/default_theme/option_button_normal.png Binary files differindex fb61d0b50f..dd47afcd41 100644 --- a/scene/resources/default_theme/option_button_normal.png +++ b/scene/resources/default_theme/option_button_normal.png diff --git a/scene/resources/default_theme/option_button_pressed.png b/scene/resources/default_theme/option_button_pressed.png Binary files differindex 116e6e2a3e..916da52f07 100644 --- a/scene/resources/default_theme/option_button_pressed.png +++ b/scene/resources/default_theme/option_button_pressed.png diff --git a/scene/resources/default_theme/panel_bg.png b/scene/resources/default_theme/panel_bg.png Binary files differindex 255269ee68..df08179aac 100644 --- a/scene/resources/default_theme/panel_bg.png +++ b/scene/resources/default_theme/panel_bg.png diff --git a/scene/resources/default_theme/popup_bg.png b/scene/resources/default_theme/popup_bg.png Binary files differindex 655b3eadf4..3afd0b13dd 100644 --- a/scene/resources/default_theme/popup_bg.png +++ b/scene/resources/default_theme/popup_bg.png diff --git a/scene/resources/default_theme/popup_checked.png b/scene/resources/default_theme/popup_checked.png Binary files differindex 7cd2cd45b0..d313db6820 100644 --- a/scene/resources/default_theme/popup_checked.png +++ b/scene/resources/default_theme/popup_checked.png diff --git a/scene/resources/default_theme/popup_window.png b/scene/resources/default_theme/popup_window.png Binary files differindex de903216d1..88fbb3bc83 100644 --- a/scene/resources/default_theme/popup_window.png +++ b/scene/resources/default_theme/popup_window.png diff --git a/scene/resources/default_theme/progress_bar.png b/scene/resources/default_theme/progress_bar.png Binary files differindex 5d290ce0fb..3016c52216 100644 --- a/scene/resources/default_theme/progress_bar.png +++ b/scene/resources/default_theme/progress_bar.png diff --git a/scene/resources/default_theme/progress_fill.png b/scene/resources/default_theme/progress_fill.png Binary files differindex d446407f08..ee7c3315e4 100644 --- a/scene/resources/default_theme/progress_fill.png +++ b/scene/resources/default_theme/progress_fill.png diff --git a/scene/resources/default_theme/radio_checked.png b/scene/resources/default_theme/radio_checked.png Binary files differnew file mode 100644 index 0000000000..ada8dde3c1 --- /dev/null +++ b/scene/resources/default_theme/radio_checked.png diff --git a/scene/resources/default_theme/radio_unchecked.png b/scene/resources/default_theme/radio_unchecked.png Binary files differnew file mode 100644 index 0000000000..018af99afd --- /dev/null +++ b/scene/resources/default_theme/radio_unchecked.png diff --git a/scene/resources/default_theme/scroll_bg.png b/scene/resources/default_theme/scroll_bg.png Binary files differnew file mode 100644 index 0000000000..53797886cd --- /dev/null +++ b/scene/resources/default_theme/scroll_bg.png diff --git a/scene/resources/default_theme/scroll_button_down.png b/scene/resources/default_theme/scroll_button_down.png Binary files differindex 87de51d5ef..88b218f581 100644 --- a/scene/resources/default_theme/scroll_button_down.png +++ b/scene/resources/default_theme/scroll_button_down.png diff --git a/scene/resources/default_theme/scroll_button_down_hl.png b/scene/resources/default_theme/scroll_button_down_hl.png Binary files differindex cfece0d5d0..90b1a48ac8 100644 --- a/scene/resources/default_theme/scroll_button_down_hl.png +++ b/scene/resources/default_theme/scroll_button_down_hl.png diff --git a/scene/resources/default_theme/scroll_button_left.png b/scene/resources/default_theme/scroll_button_left.png Binary files differindex 57bdb29ea1..8e60a96476 100644 --- a/scene/resources/default_theme/scroll_button_left.png +++ b/scene/resources/default_theme/scroll_button_left.png diff --git a/scene/resources/default_theme/scroll_button_left_hl.png b/scene/resources/default_theme/scroll_button_left_hl.png Binary files differindex a5f497178a..1114a92381 100644 --- a/scene/resources/default_theme/scroll_button_left_hl.png +++ b/scene/resources/default_theme/scroll_button_left_hl.png diff --git a/scene/resources/default_theme/scroll_button_right.png b/scene/resources/default_theme/scroll_button_right.png Binary files differindex 7fc0748305..ee79c0aa56 100644 --- a/scene/resources/default_theme/scroll_button_right.png +++ b/scene/resources/default_theme/scroll_button_right.png diff --git a/scene/resources/default_theme/scroll_button_right_hl.png b/scene/resources/default_theme/scroll_button_right_hl.png Binary files differindex 9e643262b3..b83e24a954 100644 --- a/scene/resources/default_theme/scroll_button_right_hl.png +++ b/scene/resources/default_theme/scroll_button_right_hl.png diff --git a/scene/resources/default_theme/scroll_button_up.png b/scene/resources/default_theme/scroll_button_up.png Binary files differindex 3487213eba..251106b487 100644 --- a/scene/resources/default_theme/scroll_button_up.png +++ b/scene/resources/default_theme/scroll_button_up.png diff --git a/scene/resources/default_theme/scroll_button_up_hl.png b/scene/resources/default_theme/scroll_button_up_hl.png Binary files differindex e263754f50..059b4b0f2b 100644 --- a/scene/resources/default_theme/scroll_button_up_hl.png +++ b/scene/resources/default_theme/scroll_button_up_hl.png diff --git a/scene/resources/default_theme/scroll_grabber.png b/scene/resources/default_theme/scroll_grabber.png Binary files differnew file mode 100644 index 0000000000..16beda1514 --- /dev/null +++ b/scene/resources/default_theme/scroll_grabber.png diff --git a/scene/resources/default_theme/scroll_grabber_hl.png b/scene/resources/default_theme/scroll_grabber_hl.png Binary files differnew file mode 100644 index 0000000000..acfb7c835b --- /dev/null +++ b/scene/resources/default_theme/scroll_grabber_hl.png diff --git a/scene/resources/default_theme/selection.png b/scene/resources/default_theme/selection.png Binary files differindex 08e242c28c..074c7a4d80 100644 --- a/scene/resources/default_theme/selection.png +++ b/scene/resources/default_theme/selection.png diff --git a/scene/resources/default_theme/selection_oof.png b/scene/resources/default_theme/selection_oof.png Binary files differindex c6e5ee285b..17ec977bd6 100644 --- a/scene/resources/default_theme/selection_oof.png +++ b/scene/resources/default_theme/selection_oof.png diff --git a/scene/resources/default_theme/submenu.png b/scene/resources/default_theme/submenu.png Binary files differindex 286300e25b..034912eb7a 100644 --- a/scene/resources/default_theme/submenu.png +++ b/scene/resources/default_theme/submenu.png diff --git a/scene/resources/default_theme/tab_behind.png b/scene/resources/default_theme/tab_behind.png Binary files differindex 953c76eabb..4997d9e441 100644 --- a/scene/resources/default_theme/tab_behind.png +++ b/scene/resources/default_theme/tab_behind.png diff --git a/scene/resources/default_theme/tab_container_bg.png b/scene/resources/default_theme/tab_container_bg.png Binary files differindex bfe117af39..5cfe85cfef 100644 --- a/scene/resources/default_theme/tab_container_bg.png +++ b/scene/resources/default_theme/tab_container_bg.png diff --git a/scene/resources/default_theme/tab_current.png b/scene/resources/default_theme/tab_current.png Binary files differindex 08f4faf829..f3cdd96fbf 100644 --- a/scene/resources/default_theme/tab_current.png +++ b/scene/resources/default_theme/tab_current.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 9cef0265ee..78e210239d 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -5,12 +5,12 @@ static const unsigned char arrow_down_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x98,0x0,0x74,0x0,0xf2,0x18,0x7e,0x84,0x12,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x16,0x10,0x34,0x34,0x9c,0xae,0x6b,0x51,0x0,0x0,0x0,0x91,0x49,0x44,0x41,0x54,0x28,0xcf,0xb5,0x91,0xbd,0x9,0xc3,0x40,0xc,0x85,0xbf,0x5c,0x76,0xf1,0x95,0x1e,0x20,0x99,0xe7,0x46,0x50,0x77,0x95,0xba,0x1b,0x41,0xf3,0x24,0x7b,0x18,0x63,0xbc,0x80,0x21,0xe0,0xca,0x69,0x64,0x38,0x12,0xc7,0x89,0x8b,0x3c,0x10,0xe8,0xe7,0x7b,0xcd,0x13,0xfc,0x5d,0x2a,0x76,0x88,0x3d,0x79,0x73,0x1,0x6e,0x5f,0xf8,0x6b,0x2e,0xe9,0x1e,0x7c,0x58,0x80,0x69,0x7,0x9e,0x9c,0x61,0x35,0x74,0xc0,0x79,0x5d,0xbe,0x68,0xf1,0x5b,0x7,0x10,0x54,0x8c,0x5c,0xd2,0x8,0x44,0x60,0xde,0x30,0xcc,0x40,0xcc,0x25,0x8d,0x2a,0x46,0xc8,0x25,0xe1,0xa6,0x1,0x68,0x81,0xbe,0x82,0x7b,0xa0,0xcd,0x25,0xd,0xce,0xbc,0xa7,0xa5,0x62,0x8d,0x8a,0x3d,0xbc,0x9a,0xdd,0x24,0x2b,0x53,0x54,0xb1,0xf8,0x53,0xec,0x35,0x70,0xe4,0x47,0x1f,0xf5,0x4,0x90,0xda,0x3c,0x12,0x9e,0x52,0xc6,0x4e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x1c,0xa,0x30,0xc,0x28,0x58,0xa2,0xa7,0x0,0x0,0x0,0x7c,0x49,0x44,0x41,0x54,0x28,0x91,0xa5,0xd1,0xcb,0xa,0x83,0x30,0x10,0x46,0xe1,0xaf,0x97,0x77,0xe9,0xb2,0x74,0xed,0xda,0xf7,0x5f,0x57,0x8,0x88,0x88,0x2f,0xe0,0xa2,0xb8,0x4a,0x37,0x51,0x52,0x49,0x2b,0xa1,0x3f,0xc,0x84,0x33,0x73,0x86,0x90,0x9c,0x42,0x8,0x6a,0x72,0xae,0x9a,0xfe,0x47,0x68,0x10,0xf,0xaa,0xc9,0x85,0x88,0xf9,0xc7,0xe2,0x39,0xcd,0x6c,0x42,0x8f,0xcb,0xa,0x77,0x89,0xa9,0xd7,0xe7,0xc2,0x84,0x1b,0x96,0x82,0xb0,0xa4,0xde,0x94,0xb,0x30,0xe2,0x8e,0x21,0x63,0x43,0x62,0xe3,0xa,0xf6,0xaf,0xd4,0xa1,0xc5,0x2b,0x55,0x9b,0xd8,0x96,0x6b,0xe1,0xa,0x1d,0x1e,0xd9,0xf9,0x23,0x25,0x1,0x9e,0x5f,0x78,0xfd,0xc7,0xbd,0x1,0x73,0x20,0x21,0xa9,0x4,0x80,0xe0,0x11,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char arrow_right_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x98,0x0,0x74,0x0,0xf2,0x18,0x7e,0x84,0x12,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x16,0x10,0x35,0x5,0xd4,0x6b,0x5a,0x2a,0x0,0x0,0x0,0xa0,0x49,0x44,0x41,0x54,0x28,0xcf,0x95,0x92,0xbd,0xd,0xc2,0x40,0xc,0x46,0x1f,0x81,0x2,0xa,0x36,0xa0,0x86,0x16,0x6a,0x68,0x59,0xc5,0x23,0xa4,0x73,0x75,0x9d,0x47,0xc8,0x24,0x48,0xb4,0x2c,0x11,0x68,0x10,0x42,0x59,0x80,0x2,0x51,0x1d,0x4d,0x22,0x5,0x73,0x47,0xc4,0xd7,0x59,0xf2,0xf3,0xe7,0x3f,0x68,0x15,0xca,0x8a,0xbe,0x7c,0xdc,0x69,0xe4,0x92,0xb6,0x40,0x4,0xae,0x6a,0xd2,0x84,0xb2,0x42,0x4d,0x3e,0x80,0xc2,0x15,0x38,0x1,0x7,0xe0,0x12,0xca,0x6a,0xa1,0x26,0x5f,0x4e,0x45,0xc2,0x75,0xe,0xcc,0x5a,0x68,0xe9,0xa1,0x2,0xb2,0xad,0x4e,0x81,0xa3,0x87,0xfc,0xc,0x31,0x1,0x3f,0x81,0x8d,0x9a,0xd4,0xbf,0x1c,0xb2,0x1a,0x2,0x6e,0xc0,0x5a,0x4d,0xea,0xae,0xa5,0x49,0x26,0x31,0x2,0x2f,0x60,0xaf,0x26,0xe7,0xfe,0x7a,0x53,0xc0,0x3,0x18,0x3,0x2b,0x35,0xb9,0xfb,0x5b,0x78,0x60,0x37,0x74,0x38,0xfe,0x7d,0x8d,0x37,0xf2,0x54,0x41,0xdd,0x92,0x6e,0x8a,0x2e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x1c,0xa,0x2e,0x1a,0x8,0xcd,0x28,0x29,0x0,0x0,0x0,0x7b,0x49,0x44,0x41,0x54,0x28,0x91,0x95,0xd1,0xb1,0xe,0x1,0x51,0x10,0x46,0xe1,0x6f,0x51,0x50,0x78,0x5,0x25,0xad,0x9e,0xd6,0x53,0x6f,0x4b,0xaf,0x45,0x6e,0x22,0x22,0x5e,0x40,0xa5,0x5a,0x8d,0x2b,0x32,0x76,0xb9,0x7b,0xba,0x99,0xc9,0x99,0x4c,0xfe,0xa9,0x52,0x4a,0xfa,0x30,0xa,0xf5,0xa,0xd,0xce,0xb8,0x95,0x8,0x5b,0xdc,0x31,0xc4,0x2,0xd7,0x28,0xc,0x5a,0x96,0x4c,0x31,0xc1,0x9,0xf3,0x12,0x1,0x2a,0x8c,0x51,0x47,0xa9,0x4b,0xc8,0xcc,0xb0,0x7f,0x9d,0x57,0x24,0x7c,0xf1,0x4f,0xb8,0x60,0x89,0x43,0x6e,0xc4,0x94,0x32,0xd,0x1e,0xd8,0xe0,0xf8,0x39,0x68,0x13,0x7e,0xc6,0x1a,0x85,0xb5,0x9e,0x8f,0xdb,0x75,0x9c,0xf8,0xe6,0x9,0x8,0x62,0x16,0x5f,0x9a,0xba,0xfd,0xff,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -25,27 +25,27 @@ static const unsigned char base_green_png[]={ static const unsigned char button_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x3e,0x0,0x34,0x0,0x44,0xb5,0x81,0x75,0x5d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0xd,0x2e,0x9b,0xe9,0x5,0xa7,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xec,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xd0,0xb1,0x6a,0xc2,0x50,0x0,0x85,0xe1,0xff,0x26,0x91,0x28,0x41,0x8a,0xb5,0x6,0xa3,0x90,0x21,0x6b,0x69,0xc1,0xa1,0x5d,0x3a,0xb9,0x38,0x76,0x28,0x94,0x2e,0x3e,0x96,0x8f,0xe0,0x22,0x85,0xe2,0xec,0xe2,0xe4,0x62,0x7,0xa1,0xd0,0xb5,0x43,0x21,0x55,0x4c,0x62,0xb4,0x41,0x6a,0x12,0xaa,0x2e,0xba,0xdf,0xe0,0xd2,0xa1,0xff,0xfe,0x9d,0xe1,0x8,0x0,0xdb,0x72,0x6e,0x81,0x16,0x70,0x8d,0x5c,0x6f,0xc0,0xe0,0x73,0xfa,0x31,0x16,0xb6,0xe5,0xdc,0x5b,0x95,0x7a,0xbb,0x71,0x79,0x43,0xad,0x52,0x97,0xd2,0x5f,0x9e,0xcb,0xe4,0xfd,0x95,0xa9,0xe7,0x76,0x85,0x6d,0x39,0x9d,0x87,0xd6,0x93,0xf9,0x13,0x6f,0x8,0xc2,0x85,0xd4,0x40,0xb9,0x74,0x4e,0x41,0xcf,0xf3,0x32,0xe8,0xcd,0x35,0xc0,0x5c,0x45,0x2b,0xa2,0xf5,0x1a,0xd9,0x82,0x70,0x41,0xd1,0x30,0x0,0x4c,0x5,0xc8,0x84,0x8f,0x1d,0x8d,0xc2,0x89,0xfd,0xf,0xfc,0x95,0x1,0x7f,0x19,0xf9,0x99,0xe1,0xc1,0xf8,0xea,0x59,0xb1,0x94,0x4b,0xd2,0xf8,0x4a,0xd3,0x54,0xa,0xba,0x21,0x85,0xc3,0x6f,0x8f,0x99,0xe7,0x92,0xa4,0x49,0x5f,0x0,0xdc,0x35,0x9a,0x8f,0xf3,0x60,0xd6,0x8c,0xd3,0xf8,0x42,0x66,0x40,0xcf,0xe9,0xbe,0x59,0xae,0xe,0x47,0x93,0xe1,0xb3,0x0,0xd8,0x6d,0x77,0x2a,0x90,0xcf,0xf0,0xc9,0x16,0xd8,0x8,0x45,0xfc,0xee,0x1,0x19,0x87,0x50,0x44,0x2,0xd,0x4,0xc3,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x13,0x3b,0x32,0x53,0xec,0x41,0x80,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xb5,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x93,0x3d,0xe,0x82,0x40,0x10,0x85,0xbf,0x95,0x1d,0x8b,0x85,0x84,0xe8,0x11,0xd8,0x4e,0x8f,0x60,0x8c,0x67,0x37,0x84,0x78,0x2,0xed,0xd6,0x23,0xd8,0x28,0x5b,0x38,0x31,0x58,0x8,0x96,0xb0,0x9,0x8d,0x85,0xd3,0xbd,0xcc,0xbc,0x9f,0x62,0x9e,0x1,0x2c,0xb0,0x4,0x4,0x30,0xa4,0x4d,0x7,0x28,0xf0,0x1c,0xc8,0x6b,0xa0,0x0,0xb2,0x44,0x81,0x17,0xf0,0x0,0x6e,0xb6,0x77,0x2e,0xf6,0xbb,0xc3,0xca,0x57,0x7e,0x23,0x22,0xa3,0x29,0x54,0xb5,0xb,0xd7,0x70,0xa9,0x9b,0x23,0xc0,0xdd,0xf6,0xb1,0x33,0x5f,0xf9,0x6d,0x8c,0x91,0x36,0xc6,0x51,0xeb,0xdc,0x39,0xe3,0x2b,0xbf,0xad,0x9b,0xe3,0x9,0x30,0x8b,0x61,0x21,0x22,0x93,0x64,0x80,0x36,0x46,0x44,0xe4,0x8b,0x17,0x23,0xb7,0x49,0xf3,0x17,0xf8,0x29,0x1,0x55,0x25,0x77,0x6e,0x92,0x90,0x3b,0x87,0xaa,0x7e,0xb1,0xe5,0x53,0x8c,0x57,0xb8,0x86,0xb3,0xaf,0xfc,0xa6,0x2c,0xcb,0xa4,0x57,0xe6,0xd3,0x87,0xce,0x0,0x8e,0x19,0x65,0x32,0xcc,0xac,0xf3,0x1b,0xb6,0xa2,0x3d,0xf4,0x28,0x24,0x4e,0x1c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char button_hover_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4e,0x0,0x41,0x0,0x56,0xed,0xd0,0x4e,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0xb,0x2f,0xba,0xb4,0x92,0xb7,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x7b,0x49,0x44,0x41,0x54,0x38,0xcb,0x95,0x92,0xbd,0x2f,0x44,0x41,0x14,0xc5,0x7f,0x77,0xbc,0xcd,0x5a,0x1f,0x11,0x11,0x62,0x49,0x56,0x96,0x52,0x45,0xa2,0x53,0x9,0x7a,0x1a,0xbd,0xce,0x1f,0x40,0x2b,0x3a,0xf1,0xf,0xe8,0xf4,0x1a,0x7a,0x12,0x95,0x4e,0x42,0xa5,0x44,0x6c,0xb2,0x88,0x8d,0x42,0x7c,0xbe,0x8f,0x99,0xab,0xd8,0xd9,0xf7,0x56,0x88,0x3c,0x37,0x99,0xc9,0xe4,0xdc,0x73,0xcf,0x9c,0x7b,0x67,0x44,0x55,0x19,0x1b,0x99,0x58,0x2,0xd6,0x80,0x5,0xf2,0xc5,0x31,0xb0,0x7b,0x7b,0x77,0x75,0x28,0x95,0xf2,0xf8,0x7a,0x79,0x70,0x74,0x67,0x6a,0x72,0x86,0x91,0xc1,0xd1,0x5c,0xd5,0x77,0x8d,0x3a,0x17,0x97,0x67,0xdc,0x37,0xea,0x1b,0x52,0x29,0x8f,0x5f,0x2f,0x2f,0xae,0x54,0x3f,0xc2,0x4f,0xde,0x3f,0xde,0x72,0x9,0x74,0x95,0xba,0x29,0x15,0x3b,0x39,0x38,0xda,0xbf,0x9,0x80,0xea,0xf3,0xcb,0x33,0x71,0x12,0x93,0x37,0xde,0xde,0x5f,0x89,0xa2,0x10,0xa0,0x6a,0x80,0x7f,0x15,0xb7,0xa2,0x55,0x13,0x0,0xa8,0x75,0x20,0x3e,0xa3,0xa0,0xfe,0x28,0x1e,0x53,0xf,0x48,0xba,0x91,0x92,0x2,0x0,0xab,0x16,0x54,0x9a,0xa0,0xb4,0x5d,0xa3,0xbf,0x5c,0xed,0x5a,0x1c,0xcd,0x4,0x12,0x67,0x1,0x83,0xc1,0x81,0x1a,0xcf,0xcb,0xce,0x88,0xc3,0x60,0x52,0x5,0xa7,0xc6,0x2b,0x79,0x1,0x67,0x6d,0xab,0xa4,0x99,0x48,0x2d,0xbb,0xd4,0x88,0xa3,0xad,0x4d,0xdc,0x77,0x7,0xd6,0x29,0xa2,0x9e,0x2c,0x20,0x2a,0x80,0x66,0xb3,0xf0,0xbb,0x8a,0x22,0x1e,0x54,0x3f,0xa0,0xa6,0x80,0xb5,0x18,0x1c,0x4e,0xf0,0xb6,0x5d,0x6a,0x38,0x73,0xd0,0x96,0xd3,0x8c,0xd1,0x6c,0xc1,0x25,0xde,0x2c,0xa0,0x69,0x23,0x3f,0x26,0x8e,0x6f,0xa3,0x8d,0x41,0x0,0xd4,0xa2,0x24,0xac,0x4,0xa6,0xf0,0x73,0xe2,0xbf,0xbd,0x82,0xc7,0x12,0x17,0x3,0xd4,0x3a,0xfa,0x7a,0xfb,0x3b,0xa3,0x38,0x9c,0xef,0x2a,0x75,0x63,0x8c,0x78,0xc6,0xdf,0x2b,0xb1,0x31,0xf,0x8d,0x3a,0x51,0x1c,0x6d,0x8b,0xaa,0x32,0x3b,0x3d,0xb7,0xf9,0xf8,0xf4,0xb0,0x1a,0xc6,0x61,0x25,0xcf,0x2f,0x2c,0x16,0x8a,0xb5,0xa1,0x81,0xe1,0xbd,0xd3,0xf3,0x93,0x2d,0x51,0x55,0x50,0xa,0x40,0xf,0xd0,0x91,0xf3,0x27,0x5b,0xe0,0x15,0x21,0xfe,0x2,0x54,0x16,0xb4,0xfe,0xee,0xb0,0x9,0x99,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x13,0x3b,0xf,0xb,0x84,0xd,0x91,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0xb1,0x4e,0xc3,0x40,0x10,0x84,0xe1,0xef,0xc2,0x4a,0x9c,0x90,0xb,0x6a,0x9f,0xe0,0x9,0x2,0xbc,0x58,0xc2,0xcb,0xc0,0x8b,0x85,0xa4,0xa6,0x41,0x4e,0x4d,0x41,0x71,0x91,0xe,0x99,0x2,0xd7,0x76,0xa4,0x34,0x14,0x6c,0xb9,0xda,0xf9,0x47,0x2b,0xcd,0x24,0xdc,0xe0,0x16,0x1d,0xae,0x90,0xcc,0xcf,0x88,0x6f,0x7c,0xe1,0x33,0x26,0xf1,0x23,0xee,0x90,0xcf,0x4,0x54,0x7c,0xe0,0x2d,0x26,0xe7,0xfb,0x87,0xf5,0xd3,0xba,0xf4,0x65,0x13,0x11,0xb3,0x80,0xd6,0xda,0x38,0x1c,0x87,0xd7,0xfd,0x61,0x97,0xf0,0x1e,0x8,0x5c,0x97,0xbe,0x6c,0x6b,0xad,0x6a,0xad,0xb3,0xf6,0x39,0xe7,0x54,0xfa,0xb2,0xdd,0x1f,0x76,0xcf,0x88,0xd5,0xb4,0x4f,0x11,0xb1,0x28,0x86,0x5a,0xab,0x88,0x60,0x7a,0x75,0x35,0x7f,0xbe,0x3c,0xff,0x80,0xbf,0x4,0x18,0x5b,0x6b,0x72,0xce,0x8b,0x82,0x9c,0xb3,0xd6,0x1a,0xbf,0x91,0x16,0x68,0x38,0xd,0xc7,0xe1,0xa5,0xf4,0x65,0xd3,0x75,0xdd,0x59,0x51,0xc6,0x9,0x2d,0xa1,0x77,0x41,0x99,0x92,0xb,0xeb,0xfc,0x3,0xd0,0xc5,0x44,0x36,0x1d,0x79,0x84,0xde,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char button_normal_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4e,0x0,0x41,0x0,0x56,0xed,0xd0,0x4e,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0xb,0x19,0x75,0xe,0x7,0x2e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x77,0x49,0x44,0x41,0x54,0x38,0xcb,0x95,0x92,0x3d,0x4f,0x54,0x41,0x14,0x86,0x9f,0xb3,0x7b,0x5d,0x2f,0xa8,0xc4,0xaf,0x5,0x51,0x24,0xd9,0x82,0x46,0xb,0x12,0x1a,0xb,0x5a,0xc,0x95,0x5,0x7f,0xc1,0xce,0x1f,0x0,0xad,0xb1,0x33,0xfe,0x1,0x3b,0xff,0x82,0x85,0x95,0xb1,0xb6,0xb0,0x31,0xb1,0x80,0xc6,0x44,0x92,0x35,0x1a,0x40,0x4,0x34,0x7c,0x2c,0xf7,0xce,0xcc,0x4b,0x71,0x67,0x71,0x76,0x85,0xe4,0x72,0x92,0xb9,0x99,0xbc,0x73,0xde,0x8f,0x39,0x77,0x4c,0x12,0x77,0xc7,0xef,0x2f,0x1,0xcf,0x80,0xc7,0xd4,0xab,0xf,0xc0,0xeb,0x9f,0x5b,0xdf,0xdf,0xda,0x64,0x7b,0x6a,0xb9,0x7d,0x63,0xe2,0xd5,0xc3,0x99,0x59,0xee,0xdc,0xba,0x57,0x8b,0xbd,0xf1,0xfb,0x7,0xab,0x5f,0xbf,0xf0,0x6b,0x77,0x73,0xc5,0x26,0xdb,0x53,0xdf,0x16,0xe7,0x9f,0x74,0x7a,0x45,0x8f,0xa3,0xde,0x61,0x2d,0x81,0x91,0x7c,0x94,0xbc,0x95,0xf3,0xfe,0xe3,0xbb,0xf5,0xc,0xe8,0xfc,0x3d,0xf8,0x83,0x73,0x8e,0xba,0x75,0x78,0x74,0x40,0x51,0x1e,0x3,0x74,0x1a,0xc0,0x85,0xc8,0xfd,0xea,0x73,0x32,0x0,0x85,0x0,0x16,0x4f,0x4,0x8a,0x5b,0x8b,0x98,0x22,0x60,0xa7,0x1f,0x4e,0x9b,0x32,0x0,0x2f,0xf,0xb2,0xa,0xb4,0xc4,0x46,0x67,0x58,0x87,0x7e,0x8f,0x12,0x81,0x50,0xa1,0x86,0x2a,0x21,0x40,0xc9,0x1e,0x13,0x96,0x58,0x4b,0x36,0x28,0x10,0x82,0x1f,0xb4,0x4e,0x23,0xa7,0x41,0xd2,0x74,0x83,0x9,0x84,0x29,0x54,0xb0,0x81,0x45,0x7,0xd,0xf0,0xc,0x99,0xb0,0x8,0x2a,0xe,0xa8,0x4a,0xe0,0x3d,0x86,0xaa,0xc4,0x91,0x3c,0x3c,0xa,0x91,0x9c,0xe9,0x5f,0x47,0x25,0x20,0x3f,0xd4,0xc9,0x39,0x77,0x18,0xbe,0x46,0x25,0xd0,0x2d,0x5d,0x31,0xdd,0x6c,0x64,0xff,0x4f,0xfc,0xac,0xbf,0x10,0x31,0x1f,0x1c,0x40,0xb7,0x79,0xed,0xca,0x58,0x5e,0xba,0x62,0x21,0xbf,0x3c,0x82,0x35,0x2c,0x89,0x71,0xfe,0xf2,0xde,0xb1,0xbd,0xbb,0x49,0xe9,0xca,0x97,0x26,0x89,0xb9,0x7,0x8f,0x9e,0xef,0xec,0x6d,0x3f,0x2d,0x5c,0x31,0x5d,0xe7,0x15,0xb6,0xb2,0x56,0xf7,0xe6,0xf5,0xdb,0x6f,0x3e,0xaf,0x7d,0x7a,0x61,0x92,0x50,0xd0,0x25,0xe0,0x2a,0xd0,0xac,0xf9,0x92,0x3d,0xb0,0x6f,0xd,0x2b,0x4f,0x0,0xb1,0x79,0xab,0x16,0x83,0x7a,0xfa,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xe,0x27,0x37,0x5e,0x6d,0x4f,0x26,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xb5,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0x31,0x4e,0xc3,0x40,0x14,0x45,0xd1,0x33,0x61,0x24,0x10,0xa2,0x60,0x3a,0x32,0x23,0x58,0x41,0x80,0x8d,0x25,0x6c,0x6,0x36,0x16,0x92,0x9a,0x26,0x72,0x5a,0x53,0x50,0x38,0x52,0xd0,0x50,0x60,0x44,0x67,0x5b,0x4a,0x43,0xc1,0xab,0xdf,0xbd,0xbf,0x79,0x3f,0xe0,0x12,0xd7,0xb8,0xc2,0x19,0x82,0xe1,0x54,0x7c,0xe2,0x3,0xef,0xb1,0x87,0x1f,0x70,0x8b,0x8b,0x89,0x82,0xe,0x3b,0xbc,0xc6,0xfe,0xf2,0xdd,0xfd,0xe2,0x71,0x51,0x72,0x59,0xaa,0x23,0x82,0xa0,0x36,0xfb,0xe6,0x65,0xb3,0x5d,0x7,0xbc,0x45,0x44,0x9c,0x97,0x5c,0x56,0x5d,0xd7,0x69,0xdb,0x76,0x90,0x4f,0x29,0x85,0x92,0xcb,0x6a,0xb3,0x5d,0x3f,0x21,0xce,0x7e,0xbd,0x46,0x61,0xfa,0x4e,0xed,0x19,0xcc,0x6,0xdb,0x13,0xf2,0x2f,0xf8,0x4b,0x82,0x2a,0x90,0x52,0x1a,0x5,0x52,0x4a,0x3f,0x63,0xaf,0x7c,0xaf,0xf0,0x88,0x43,0xb3,0x6f,0x9e,0x4b,0x2e,0xcb,0xf9,0xcd,0x7c,0xd2,0x94,0x71,0xc0,0x31,0x20,0x3b,0xe1,0x99,0x82,0x13,0xdf,0xf9,0xb,0x7f,0x70,0x3b,0x69,0x4a,0x9d,0x12,0xc4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char button_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x3e,0x0,0x34,0x0,0x44,0xb5,0x81,0x75,0x5d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0xd,0xa,0xa7,0xea,0xe1,0x76,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x53,0x49,0x44,0x41,0x54,0x38,0xcb,0x95,0x93,0x4d,0x4a,0xc4,0x40,0x10,0x85,0xbf,0x72,0x12,0x93,0x19,0xfc,0x43,0x4,0x51,0x41,0x1c,0xf4,0xa,0xae,0xdd,0xe8,0x1,0xbc,0x82,0xbb,0x39,0x80,0x6e,0xc5,0x9d,0x78,0x1,0x77,0x5e,0xc1,0x3,0xcc,0xca,0xb5,0x57,0x10,0x84,0x1,0x11,0x51,0x5c,0x89,0x26,0x23,0xa9,0xe7,0xa2,0x3b,0x71,0x46,0x66,0x11,0x6b,0xd1,0x5d,0xa4,0xaa,0x5e,0xbf,0xf7,0xba,0x63,0x92,0xe8,0x6f,0xed,0x1d,0x3,0x3,0xe0,0x88,0x76,0x31,0x4,0xae,0x1f,0x9f,0x1e,0x6e,0x6d,0x67,0x73,0xf7,0x34,0x9b,0xcf,0xaf,0xba,0x59,0x8f,0x2c,0xcf,0x5a,0x4d,0x97,0x45,0xc9,0x57,0xf9,0x49,0x39,0x2e,0xce,0x12,0x60,0xb0,0xb4,0xb0,0x4c,0x37,0xef,0x61,0x66,0xad,0x0,0xb2,0x34,0x27,0x4d,0x53,0x5e,0xdf,0x8b,0x41,0x2,0xf4,0xbb,0x79,0xf,0x0,0x49,0xb4,0x8d,0x38,0xd3,0x4f,0x66,0xd,0xa,0x30,0x84,0x8,0x8c,0xea,0x7c,0x16,0xbf,0x4,0xa0,0x72,0xf,0x45,0xb,0x60,0x66,0x86,0x4,0x98,0x47,0x66,0x6,0x26,0x3c,0xd6,0x50,0x38,0xa4,0x1,0x70,0x55,0x1,0xc0,0x6b,0x90,0xc8,0x24,0xee,0x56,0xd3,0x2,0x54,0xf7,0x4c,0x2,0xc8,0xbd,0xf9,0xc0,0xa4,0x1a,0x9b,0x6,0x62,0x46,0x4f,0x60,0xe0,0x1e,0x7,0x4,0xb2,0xc6,0x3,0xec,0x17,0xa1,0xf1,0x20,0xf6,0x4c,0x7b,0xd0,0x48,0x30,0x64,0x8e,0x9,0xdc,0xc,0x53,0xf4,0x80,0x90,0xbb,0x81,0x85,0xe5,0x8f,0x4,0x39,0x8a,0xc6,0x58,0x64,0x80,0xbc,0xb9,0x5,0x88,0xb9,0xc0,0x9,0x7,0xd4,0xa5,0x20,0xa1,0xf2,0x46,0x73,0x9b,0x97,0xa0,0x3f,0x1e,0x8c,0x2a,0xaf,0xb6,0xeb,0xeb,0x69,0x1b,0xf1,0xed,0x8c,0x3a,0x2b,0x8b,0xab,0xb9,0x4c,0x87,0x9d,0xb9,0x84,0xff,0x44,0xf9,0x5d,0xe0,0x95,0x5f,0x9a,0x24,0xe,0xf6,0x8f,0xce,0x5f,0xde,0x9e,0x4f,0xca,0x71,0xb1,0xdd,0xea,0x5f,0x98,0xcf,0x47,0xeb,0x6b,0x1b,0x37,0x77,0xf7,0xc3,0xb,0x53,0x70,0x2f,0x5,0x16,0x80,0x4e,0x4b,0x2,0x15,0xf0,0x81,0xf1,0xfd,0x3,0xe7,0x4,0xa3,0xf4,0x4f,0x7,0x6b,0x83,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xc2,0x0,0xc2,0x0,0xcc,0x6a,0x6f,0xcc,0x71,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x7,0x31,0xd,0x7f,0xbc,0x67,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc7,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0xc1,0x4a,0xc3,0x50,0x14,0x4,0xd0,0xf3,0x6a,0x1e,0x26,0x22,0xc1,0xb5,0x90,0xe4,0x7,0x44,0xd1,0xef,0x6a,0xfd,0x19,0xfd,0xae,0x96,0xfa,0x1,0x42,0xdb,0x7d,0x75,0x21,0xbc,0x96,0x57,0x89,0xb,0xb3,0x4e,0xb,0xdd,0xb8,0x70,0x96,0x97,0x3b,0x33,0xf7,0xc2,0x4c,0xc0,0x15,0x6e,0x70,0x8d,0xb,0x4,0xe3,0xe8,0xf1,0x8d,0x2f,0x7c,0x16,0x3,0xf9,0x1e,0xd,0xca,0x13,0x5,0x76,0xd8,0xe0,0xad,0x18,0x9c,0xdb,0xc7,0x87,0xa7,0xbb,0xb6,0xe9,0xa6,0x31,0xc6,0x51,0x81,0x9c,0x73,0xbf,0xde,0xac,0x5e,0x17,0xcb,0x79,0xc0,0x7b,0x81,0x2,0x97,0x6d,0xd3,0xcd,0x52,0x4a,0xb6,0x1f,0xdb,0x51,0xfb,0xaa,0xac,0x42,0xdb,0x74,0xb3,0xc5,0x72,0xfe,0x8c,0x62,0x32,0xcc,0x43,0x8c,0x51,0xda,0xa5,0x23,0xd7,0x93,0x76,0x49,0x8c,0x91,0xe1,0xd5,0xc9,0xf8,0xfa,0x71,0xfc,0xb,0xfc,0x25,0x81,0x3e,0xe7,0xac,0x2a,0xab,0xa3,0x84,0xaa,0xac,0xe4,0x9c,0xf9,0x8d,0xb4,0x2,0x7,0xec,0xd7,0x9b,0xd5,0x4b,0xdb,0x74,0xd3,0xba,0xae,0x4f,0x8a,0x32,0xf6,0x38,0x4,0xdc,0x3a,0xa3,0x4c,0xc1,0x99,0x75,0xfe,0x1,0x94,0xfc,0x44,0x1b,0xd0,0x15,0xb1,0x70,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char checked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x34,0x0,0x2e,0x0,0x39,0xc0,0x34,0x46,0xdb,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x7,0x16,0x4c,0x4b,0x43,0x36,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xd0,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x93,0xbf,0x6b,0x53,0x51,0x14,0xc7,0x3f,0xaf,0x7d,0xa4,0x31,0x49,0x93,0x26,0x69,0x5e,0x5e,0x4c,0x8a,0x15,0x41,0x84,0x80,0xb5,0xb5,0x2a,0x82,0xa2,0xa8,0x4b,0xc1,0x45,0xc1,0x5d,0xba,0x94,0xe,0x5,0x11,0x4,0x45,0x94,0x3a,0x29,0xe,0xae,0x1d,0x4,0xd1,0xc1,0x3f,0x40,0x7,0xd1,0x49,0x8c,0x14,0x5c,0x8a,0x38,0x38,0x44,0xc8,0x62,0x69,0x4d,0x43,0xa5,0xc5,0xa,0x49,0xee,0xbb,0x3f,0x1c,0x34,0x8f,0xbc,0xf4,0x5,0x44,0xf,0x1c,0xb8,0xf7,0x7e,0xcf,0xf9,0x9c,0xc3,0xe1,0x1e,0xcb,0x71,0x1c,0xfe,0xc7,0xec,0xde,0x87,0x46,0xa3,0xf1,0xd7,0xc9,0x8e,0xe3,0x4,0x1,0x83,0x26,0x72,0xb5,0x90,0x2b,0xcd,0x3,0xc7,0x7b,0x83,0xc7,0x8b,0x7,0xb8,0xbe,0x70,0xe3,0x47,0x3c,0x11,0xab,0x65,0xf3,0xe9,0x63,0x27,0xce,0x4e,0xaa,0x40,0x7,0x83,0x26,0x72,0xd7,0x1d,0xdd,0x7b,0xef,0xf0,0xc1,0x29,0x32,0xa9,0xdc,0xae,0x6a,0xe7,0x67,0xce,0xa0,0x94,0x4a,0xce,0x5d,0x9b,0x9d,0xf4,0x3c,0xef,0xe,0xb0,0x8,0x30,0xd0,0x15,0x33,0x7f,0xe4,0xd0,0x34,0xcd,0x76,0x93,0xda,0x6a,0x35,0xe0,0x7b,0xa2,0x31,0x32,0xce,0x8,0xf,0x1f,0x3d,0xe0,0xd4,0xd4,0x39,0x2c,0xcb,0x9a,0xb,0x9b,0x81,0xbb,0xbd,0xb3,0x85,0x52,0x6a,0x57,0xf5,0xa3,0x27,0x27,0xa8,0xbc,0xfa,0x80,0x3d,0x60,0xd3,0x6a,0x37,0x1,0xdc,0x8e,0xd6,0xdd,0x1,0x6d,0xd1,0x42,0x2a,0x8f,0x42,0xae,0xc8,0xcc,0x85,0x8b,0xa4,0x93,0x19,0x4a,0xf9,0x7d,0x94,0xf6,0x17,0x78,0x5d,0x79,0x49,0x3c,0x96,0xa0,0x2d,0x5a,0x1,0x78,0x0,0x60,0x8c,0xc1,0x18,0x43,0xed,0xeb,0x17,0x8a,0xe3,0x2e,0x97,0xaf,0x5c,0xa2,0x5c,0x2e,0xf3,0x79,0xa5,0x8a,0xa7,0x3c,0x5f,0xef,0xb,0x90,0x52,0x22,0xa5,0xc4,0xa0,0xb9,0xbd,0x78,0x93,0x74,0x36,0xc5,0xf4,0xe9,0x9,0x2a,0xef,0xdf,0x11,0x1b,0x8a,0xfb,0x7a,0x5f,0x80,0x36,0xa,0x6d,0x7e,0xcf,0x20,0x11,0x1f,0xe6,0xd9,0xe3,0xe7,0x88,0x96,0xe0,0x53,0x75,0xc5,0xd7,0x3a,0x7a,0xe8,0x47,0xd2,0x5a,0xfb,0xe7,0x68,0x24,0xca,0xf2,0xc7,0xb7,0xc,0x3d,0x8d,0x92,0x8c,0xa7,0x2,0x5a,0xbf,0xe,0xd6,0x84,0x14,0x68,0xad,0x7d,0x1f,0x4d,0xe7,0x79,0xb3,0xfc,0xc2,0x87,0x6b,0xad,0x11,0x52,0x0,0xac,0x85,0x1,0x96,0x36,0x36,0xd7,0x11,0x52,0xa0,0xb4,0x46,0xfd,0xa9,0x58,0xc8,0x8d,0xf9,0x77,0x21,0x5,0x1b,0x9b,0xeb,0x0,0x4b,0x9d,0x24,0xab,0x7b,0x99,0xdc,0x91,0xb1,0xfb,0x5b,0x3b,0xdf,0x67,0xa5,0x94,0xa1,0x1b,0x66,0xdb,0x76,0x23,0x3d,0x9c,0x7d,0x52,0xdf,0x5e,0xbd,0x15,0xa,0xa8,0x7f,0xab,0x47,0x80,0x44,0xef,0x70,0xbb,0xc7,0x4,0xfc,0x74,0xb,0xae,0x8,0x5,0xfc,0x8b,0xfd,0x2,0xb8,0xb3,0xcd,0xf1,0xa1,0x77,0xab,0xc4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x36,0x36,0x55,0x46,0x2e,0x76,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xbd,0x49,0x44,0x41,0x54,0x38,0x8d,0x8d,0x93,0x4f,0x6b,0x13,0x51,0x14,0xc5,0x7f,0x93,0x99,0x84,0xa1,0xd2,0x8c,0x90,0x49,0xba,0xea,0xb6,0x1f,0xa0,0x8,0x76,0xa3,0xad,0x6d,0x53,0x4a,0x96,0x22,0x4a,0xb,0x2e,0x55,0xfc,0x6,0x36,0x74,0x2b,0x45,0xba,0xaf,0x71,0x61,0x71,0x95,0x42,0x37,0x52,0xdc,0x34,0x85,0x92,0xa2,0xb8,0xb7,0x4,0x4d,0xd5,0xb8,0xd2,0x85,0x98,0xcc,0x22,0x23,0x99,0xc9,0xcc,0xa4,0x6f,0xba,0xc8,0x4c,0x9b,0x92,0x97,0xd2,0xb,0x8f,0xb,0xef,0xbd,0x73,0xce,0xfd,0xab,0xd0,0x37,0x5,0x48,0x0,0x5a,0xe4,0xaf,0x32,0x1,0xf4,0x22,0x1f,0x2a,0x11,0x38,0x9,0x64,0x80,0x49,0x20,0x7d,0x5,0x89,0x0,0x6c,0xe0,0x37,0x60,0x1,0x41,0xac,0x98,0xd1,0x54,0x6d,0x6e,0x61,0x3e,0x5f,0x4e,0x26,0x93,0x52,0x64,0x36,0x97,0x65,0xad,0xf8,0x2,0xd7,0x75,0x99,0x99,0xb9,0xfd,0xd8,0x75,0xdd,0x43,0xe0,0x9f,0xa,0xa4,0x80,0xa9,0xa5,0xfc,0xf2,0xbe,0xe7,0x79,0xd8,0xb6,0x8d,0xe3,0x38,0x43,0xe7,0xd9,0xd3,0x27,0x8c,0xa7,0xc7,0x29,0x6d,0xbd,0x21,0x97,0x9d,0xb8,0xff,0xfd,0xc7,0xc9,0x2e,0xd0,0x4c,0x44,0x11,0x18,0x9a,0xa6,0xd1,0xed,0x76,0xa5,0xea,0x85,0x42,0x81,0xe9,0x5b,0xd3,0xec,0xbd,0xdf,0xa3,0x56,0xab,0x11,0x86,0x21,0x80,0x1,0x24,0xe2,0x5c,0x95,0x41,0x80,0xaa,0xaa,0x97,0x8,0x1e,0x3e,0x7a,0x40,0xe3,0xe7,0x2f,0xaa,0xd5,0x23,0x82,0x20,0x40,0x8,0x41,0x24,0xac,0x48,0x8b,0xb5,0xb2,0xba,0x42,0xa9,0xf4,0x1a,0xc3,0x30,0xb8,0x3b,0x77,0x87,0xb1,0x1b,0x63,0x54,0x2a,0x7,0x74,0x3a,0x9d,0xa1,0xbf,0x9a,0x8c,0x60,0xa7,0xbc,0xc3,0xe2,0xe2,0x3c,0x1b,0x1b,0x2f,0xe9,0x7a,0x1e,0xdf,0xbe,0xd6,0x39,0xfe,0x72,0x2c,0x4d,0x4f,0x1a,0x81,0x10,0x82,0x62,0x71,0x9d,0xf4,0x4d,0x3,0xd3,0xcc,0x50,0xd9,0x3f,0xc0,0xb2,0xac,0xeb,0x13,0x84,0x61,0x88,0xd5,0x6a,0xb1,0xf9,0x6a,0x13,0xdb,0xfe,0x4f,0xbd,0x5e,0x97,0x82,0x47,0x12,0x0,0x78,0x9e,0x8f,0xe3,0xb8,0x6c,0xbf,0xdd,0xa6,0xdd,0x6e,0x8f,0x24,0x88,0x6b,0x10,0xca,0x1e,0x1b,0x8d,0x6,0xa6,0x99,0x89,0xdb,0x76,0xa1,0xda,0x6f,0xde,0x79,0x2b,0x4,0xd0,0xee,0xf5,0x7a,0xe8,0xba,0x3e,0x94,0x4a,0xb3,0xd9,0xba,0x74,0xa7,0xeb,0x3a,0xbe,0xef,0x43,0x7f,0xa4,0x4f,0x15,0x40,0x5,0x26,0x52,0xa9,0x54,0xfe,0xde,0xec,0xc2,0xbb,0x51,0xa3,0x1c,0x5b,0x10,0x4,0x7c,0xfa,0xfc,0xf1,0xb9,0xe3,0x74,0x3e,0x0,0x7f,0x7,0x97,0xc9,0xe4,0xfa,0xcb,0xf4,0x7,0x68,0x1,0x7e,0x3c,0x81,0x83,0xeb,0xac,0xca,0xb1,0xe7,0x76,0xca,0xc0,0x3a,0x9f,0x1,0x62,0x9,0xad,0x4a,0x1e,0xbc,0xe7,0x4d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -55,7 +55,7 @@ static const unsigned char close_png[]={ static const unsigned char close_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x14,0x12,0x9e,0xa0,0x13,0x1f,0x0,0x0,0x1,0xbf,0x49,0x44,0x41,0x54,0x38,0xcb,0xcd,0x52,0x4d,0x8f,0xd2,0x50,0x14,0x3d,0x7d,0xaf,0xad,0xbc,0x9a,0xf6,0xd5,0x21,0x8,0x63,0x13,0x61,0xe1,0x8a,0xb5,0x23,0x6,0x8b,0x2b,0xd8,0xba,0x98,0x59,0xcd,0x2f,0x30,0xf3,0x3,0xf4,0x87,0x68,0x4c,0xf4,0x1f,0xe8,0x4f,0x30,0xb3,0xd3,0x8d,0xbb,0x59,0x98,0x8,0x21,0x10,0x9d,0x90,0x20,0x8f,0x41,0xd3,0x7,0x25,0xd8,0xf,0x5a,0x37,0x25,0x61,0x9a,0xea,0x56,0xcf,0xe6,0xdd,0x77,0xee,0xbd,0x27,0xb9,0xf7,0x5c,0xe0,0x5f,0x43,0x29,0xf8,0xab,0x59,0x1c,0xe5,0x72,0x5a,0xf6,0xc6,0x0,0xd2,0x1d,0x49,0x73,0xcd,0xb7,0xea,0xf5,0xfa,0x31,0x0,0x33,0x8,0x2,0x9,0x20,0xc8,0x78,0x9b,0x73,0x7e,0xbf,0x56,0xab,0xb9,0x52,0xca,0x9,0x80,0x5f,0x45,0x2,0x5a,0xa3,0xd1,0x38,0x69,0xb5,0x5a,0xaf,0x75,0x5d,0x3f,0x16,0x42,0x5c,0x24,0x49,0xf2,0x3,0x0,0xd3,0x34,0xed,0x51,0xaf,0xd7,0x7b,0x47,0x8,0x79,0x42,0x29,0x1d,0x49,0x29,0xbf,0x0,0x48,0xf2,0x2,0x34,0x8a,0xa2,0x1b,0x8a,0xa2,0x9c,0x10,0x42,0x2a,0x9c,0xf3,0xc7,0xcb,0xe5,0xf2,0x9b,0xaa,0xaa,0xf7,0x3a,0x9d,0xce,0xcb,0xf5,0x7a,0x5d,0x59,0xad,0x56,0xde,0x64,0x32,0x79,0x15,0xc7,0xf1,0xf7,0x9d,0x40,0x7e,0x7,0x9c,0x10,0xf2,0xb0,0xd9,0x6c,0xbe,0x31,0xc,0xa3,0xee,0xfb,0xbe,0x60,0x8c,0x29,0x9c,0xf3,0xdb,0xb3,0xd9,0xec,0xb2,0xdf,0xef,0x3f,0x4d,0xd3,0xf4,0x13,0x0,0x59,0x34,0x2,0x0,0x84,0x69,0x9a,0xfe,0xf4,0x3c,0xef,0xab,0x61,0x18,0x6d,0xd3,0x34,0xf,0x9,0x21,0x37,0x85,0x10,0xd3,0xf1,0x78,0xfc,0x3c,0x49,0x92,0x8f,0xfb,0xcd,0x0,0x40,0x8a,0xac,0x21,0x84,0xd0,0x52,0xa9,0x44,0x1,0x20,0x4d,0x53,0x10,0x42,0x88,0xaa,0xaa,0xb4,0xa8,0x36,0x4f,0xda,0xba,0xae,0xbb,0xae,0xeb,0xbe,0x60,0x8c,0xd5,0x16,0x8b,0xc5,0x34,0x8a,0xa2,0x95,0x65,0x59,0x87,0xa6,0x69,0x3e,0x90,0x52,0x7e,0xde,0x6e,0xb7,0xe2,0x8f,0x2e,0xd8,0xb6,0x7d,0xd4,0xed,0x76,0xdf,0xfa,0xbe,0x5f,0x99,0xcf,0xe7,0x97,0xa3,0xd1,0xe8,0x99,0xe7,0x79,0xef,0x2d,0xcb,0x3a,0x32,0xc,0xe3,0x6e,0xb9,0x5c,0xee,0x6d,0x36,0x9b,0xf,0x41,0x10,0x4c,0x77,0x4b,0xbc,0x36,0x82,0xe3,0x38,0xd,0x21,0x84,0x2a,0xa5,0xbc,0x1a,0xe,0x87,0x67,0x71,0x1c,0x9f,0x87,0x61,0x78,0x3e,0x18,0xc,0xce,0xc2,0x30,0xbc,0xa2,0x94,0xea,0x9c,0xf3,0x3b,0x7f,0xbb,0xca,0x3,0xc7,0x71,0x4e,0x19,0x63,0x6d,0x0,0x3c,0xe3,0x14,0x0,0x9c,0x31,0xd6,0xae,0x56,0xab,0xa7,0x0,0xe,0xa,0xdc,0xbb,0x26,0xa2,0xed,0x9d,0xf3,0x3e,0xd4,0x2c,0xa7,0xe0,0xbf,0xc2,0x6f,0x5f,0x7b,0xa6,0x3c,0x3f,0xa9,0x93,0x5b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x11,0x4,0x37,0xf7,0xbe,0xdc,0xa,0x0,0x0,0x1,0x29,0x49,0x44,0x41,0x54,0x38,0x8d,0xa5,0xd3,0x4d,0x2b,0x45,0x61,0x10,0x7,0xf0,0xdf,0x71,0xaf,0x2c,0xa4,0x2e,0xd7,0xc2,0x95,0xb0,0xba,0x5b,0x1b,0x59,0x78,0xd9,0x5b,0x58,0xc8,0x57,0xb0,0xb2,0xb5,0xf0,0x41,0x2c,0x90,0x85,0xf2,0x1,0x94,0xb2,0xb2,0x56,0x4a,0x36,0x4a,0x36,0x36,0x3a,0x29,0x25,0xa5,0xbc,0x24,0x6f,0xb9,0x16,0xe6,0xea,0xe9,0x1c,0x56,0x77,0x6a,0x7a,0x3a,0xf3,0xfc,0xff,0xff,0x33,0x33,0xcf,0x4c,0xd6,0x6c,0x36,0x75,0x62,0x5d,0x1d,0xb1,0x51,0x2d,0x7c,0x67,0x49,0xec,0xa3,0x70,0xd7,0x1d,0xe7,0x27,0x5a,0xed,0x60,0xa5,0x5e,0xaf,0xa7,0xe4,0x7e,0x2c,0xa1,0xf,0xf,0x78,0x8b,0x78,0xd,0x93,0x98,0xc5,0x35,0x5e,0xdb,0xa4,0xb4,0x84,0x2a,0x16,0xb0,0x85,0xbd,0x0,0xf,0x84,0xcf,0x62,0x1f,0x1b,0x81,0xa9,0xfe,0x25,0x0,0x97,0x78,0xc6,0x20,0x36,0x31,0x1f,0xbe,0x1d,0xd9,0xbd,0x4,0xe6,0xd7,0xd2,0x12,0xbe,0xf0,0x84,0x53,0xcc,0x61,0x14,0x33,0x21,0x30,0x84,0x1c,0xcb,0x38,0xb,0xa1,0x92,0x0,0xbc,0xe3,0x1e,0x57,0x98,0x46,0x3,0xbd,0xb8,0xc1,0x1a,0x8e,0xa2,0x37,0xbf,0xf6,0xdf,0x33,0x56,0xc2,0x53,0x5c,0xe5,0x4f,0x60,0x21,0x83,0x9a,0x9f,0x86,0xad,0x47,0xda,0x37,0x51,0x56,0x3,0x53,0x38,0xc7,0xad,0x7f,0x5e,0xa1,0x1b,0x13,0xd8,0xd,0x42,0x8e,0xd5,0xf0,0x1c,0x23,0xd8,0x9,0x4c,0x7b,0x26,0x4a,0x83,0x34,0x1e,0xb1,0x3b,0xac,0xe0,0x24,0xe2,0x8f,0x21,0xdc,0x83,0xe1,0x94,0x90,0xa,0x7c,0xe2,0xc0,0x4f,0x23,0x73,0x5c,0x4,0x11,0x8e,0xb1,0x88,0x31,0x1c,0x6,0x16,0x64,0x85,0x65,0x6a,0x8f,0x72,0x2b,0x5,0x25,0x3f,0xcb,0x14,0x46,0xb9,0x58,0x42,0x4b,0x79,0x7,0xd2,0xc,0x4b,0xd6,0xf1,0x36,0x7e,0x3,0x2b,0x36,0x3d,0x6b,0xfa,0xe7,0xaf,0xa6,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -65,7 +65,7 @@ static const unsigned char dosfont_png[]={ static const unsigned char dropdown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x18,0x18,0xd2,0xc0,0xb5,0xd,0x0,0x0,0x0,0x8e,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x60,0x60,0x60,0xf8,0xf0,0xf6,0x33,0x33,0x3,0x1a,0x80,0x89,0x31,0x7e,0x78,0xfb,0x99,0xf9,0xdf,0xbf,0x7f,0x7a,0x28,0xb2,0xff,0x19,0x98,0x19,0x18,0x18,0x18,0x84,0xc4,0xf8,0xcf,0xb0,0xfc,0xfd,0xfb,0xcf,0xfe,0xcb,0xc7,0x6f,0x7b,0x19,0xb0,0x80,0x57,0xcf,0xde,0x75,0x33,0x31,0x31,0x32,0xde,0x87,0xf2,0xff,0xa0,0x2b,0x60,0x62,0x66,0xba,0xc4,0xc4,0xc8,0xc4,0xf8,0x94,0x4f,0x90,0x5b,0x8a,0x81,0x81,0x81,0x85,0x81,0x81,0xe1,0x2f,0x4c,0x92,0x9b,0x97,0x33,0x4e,0x44,0x5c,0x60,0x9,0x23,0xd4,0x41,0x6c,0xff,0xff,0xff,0x17,0xfe,0xf4,0xfe,0xeb,0x33,0xb8,0xa4,0x84,0xc0,0x62,0x74,0x57,0xb3,0xbd,0x7b,0xfd,0x49,0xee,0xcd,0x8b,0xf,0xa9,0xc,0xb8,0xc0,0x87,0xb7,0x9f,0x99,0xd0,0xc5,0x0,0x9d,0xb3,0x34,0xc7,0x2,0xa0,0x66,0xfc,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x1c,0x1b,0x52,0x41,0x72,0xa4,0x0,0x0,0x0,0x8b,0x49,0x44,0x41,0x54,0x18,0x95,0x6d,0x8e,0x31,0xe,0x2,0x21,0x10,0x45,0x3f,0xc3,0x66,0x1b,0x12,0x1a,0xa8,0x2c,0x3c,0x82,0x57,0xf0,0x26,0x76,0x9e,0xc6,0x63,0xec,0x5e,0xc3,0x1b,0x58,0x79,0x1,0x2b,0x2d,0x8,0x21,0x13,0x42,0x29,0x8c,0xcd,0x92,0x6c,0x88,0xd3,0xfd,0xff,0x7e,0x26,0xf,0x0,0xc0,0xcc,0x1a,0xc3,0xf5,0x4e,0x31,0xb3,0x6e,0xad,0x9d,0xf6,0x50,0x44,0x34,0x0,0x38,0xe7,0x1e,0x53,0xad,0xf5,0x5c,0x4a,0xb9,0x8f,0x1f,0x0,0x20,0x84,0x70,0x23,0xa5,0xd4,0x6b,0xcb,0xdf,0x71,0x40,0x44,0x4f,0x22,0xa2,0xb7,0xb5,0xf6,0x0,0x60,0x2,0x50,0x3b,0x34,0xc6,0x5c,0xbc,0xf7,0xab,0xda,0x84,0x66,0x11,0x71,0x39,0xe7,0xcf,0xe,0x2e,0xa3,0xf5,0x9c,0x52,0x3a,0xc6,0x18,0xaf,0xff,0x7c,0xfa,0x88,0xc6,0xee,0x7,0x3f,0xda,0x36,0xc7,0xfa,0xc,0x38,0x2c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -75,7 +75,7 @@ static const unsigned char error_icon_png[]={ static const unsigned char focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x34,0x0,0x2e,0x0,0x39,0xc0,0x34,0x46,0xdb,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x3,0x2b,0x70,0x4f,0xca,0x23,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x41,0x49,0x44,0x41,0x54,0x38,0xcb,0xad,0x53,0x3b,0x6e,0xc2,0x50,0x10,0x9c,0xb5,0xcd,0x47,0xf,0x1b,0x9,0x21,0x71,0x1,0xce,0x90,0x1b,0xa4,0xd,0x17,0x40,0xe9,0x42,0x84,0x94,0x2a,0x5d,0x4,0x32,0x2d,0xe9,0xa8,0xd2,0xc4,0xe9,0x72,0x84,0xb4,0xa9,0x28,0x49,0xc5,0x1,0xb8,0x80,0x45,0x1a,0x40,0x18,0x23,0xfb,0x4d,0x9a,0x67,0xc9,0x21,0x18,0x85,0x28,0x23,0x8d,0xb6,0x9a,0x91,0x76,0x77,0x46,0x60,0x40,0x52,0x0,0x58,0x86,0xc8,0xcd,0xc,0x3a,0x37,0xb5,0x88,0x10,0x0,0x24,0x27,0x76,0x0,0x94,0xd,0x9d,0x3,0x33,0x6d,0x98,0x0,0xd8,0x1b,0x26,0x22,0x42,0xc9,0x89,0xab,0x93,0xbb,0xd7,0x60,0xb5,0x59,0x5d,0x26,0xc9,0xbe,0x89,0x23,0x70,0x9c,0xf2,0x67,0xdd,0xad,0xbf,0xdf,0x3f,0x5d,0xf7,0x0,0xec,0x0,0x24,0x20,0x69,0x93,0xac,0x8d,0x7b,0xc1,0xb4,0xdf,0x19,0x30,0x9c,0xf3,0xa8,0x18,0x0,0xc2,0x39,0x9b,0xfd,0xce,0x80,0xe3,0x5e,0x30,0x25,0x59,0x23,0x69,0x83,0x64,0x89,0x64,0xc3,0xef,0x4e,0xa2,0x34,0xa6,0x78,0x2d,0xb4,0x8b,0xc,0xbc,0x16,0xda,0x69,0x4c,0xf1,0xbb,0x93,0x88,0x64,0x83,0x64,0x29,0xdb,0xd3,0x21,0x59,0xb5,0x2b,0xc2,0x75,0x88,0x45,0x91,0xc1,0x3a,0xc4,0xc2,0xae,0x8,0x49,0x56,0xb3,0x3b,0x15,0x5d,0xfc,0x37,0xb0,0x70,0xe2,0x65,0x67,0x1b,0xfc,0x19,0xd6,0x41,0x48,0xce,0x81,0xfe,0x37,0x3,0x6d,0x52,0x15,0x9d,0xca,0x40,0x3e,0xb,0x22,0x12,0x99,0x54,0xea,0xcc,0x60,0xaf,0x94,0x3b,0x1b,0xf9,0xc3,0x65,0x1a,0xd3,0x2b,0x12,0xa7,0x31,0xbd,0x91,0x3f,0x5c,0x2a,0xe5,0xce,0x4c,0x9c,0x75,0x3e,0xca,0xea,0xf1,0xf6,0xe5,0x6d,0xbb,0xdd,0x5c,0x98,0x3f,0xff,0x80,0x88,0xec,0x94,0x72,0x3f,0x1e,0x9e,0x6f,0xae,0x0,0x6c,0x1,0x24,0x59,0x99,0x6c,0xb3,0xce,0x39,0x65,0xd2,0x22,0x92,0x4a,0x41,0x9d,0xad,0x13,0x87,0xfb,0x56,0xe7,0x2f,0x3a,0x44,0xa3,0xad,0xf6,0x7e,0xe,0x1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x37,0x23,0x98,0xdc,0x7f,0x32,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x33,0x49,0x44,0x41,0x54,0x38,0x8d,0xad,0x53,0x3b,0x6e,0xc2,0x50,0x10,0x9c,0x85,0xe7,0x8,0x65,0xe5,0x2,0x71,0x4,0xce,0x90,0x1b,0xa4,0xcd,0x2d,0x9c,0x23,0xb8,0x40,0xb2,0x84,0xa9,0x38,0x44,0x8e,0x91,0x36,0x15,0x25,0x39,0x3,0xfd,0x2b,0x48,0x85,0x5e,0x8c,0x60,0xf3,0x26,0x5,0x7e,0x91,0x45,0x70,0x94,0xdf,0x48,0xa3,0xad,0x66,0xa4,0xdd,0x9d,0x11,0xb4,0x20,0x29,0x0,0x6,0x2d,0xd1,0x99,0x9,0xb1,0x33,0xa3,0x88,0x10,0x0,0xa4,0x23,0x76,0x0,0xae,0x5a,0xba,0x33,0xb3,0xd8,0xd2,0x0,0x1c,0x5a,0x9a,0x88,0x50,0x3a,0xe2,0xd1,0x72,0xb9,0x7c,0xd8,0xed,0x76,0xb7,0xc7,0xe3,0x71,0x82,0xb,0xc8,0xb2,0xec,0x25,0xcf,0xf3,0xa7,0xd9,0x6c,0x76,0xf,0x60,0xf,0xc0,0x40,0x72,0x48,0x52,0xeb,0xba,0x5e,0x15,0x45,0x41,0xef,0xfd,0x45,0x31,0x0,0x78,0xef,0x27,0x45,0x51,0xb0,0xae,0xeb,0x15,0x49,0x25,0x39,0x4,0xc9,0x8c,0xe4,0xb8,0x2c,0xcb,0xc6,0xcc,0x44,0x55,0xa7,0x7d,0x6,0xaa,0x3a,0x35,0x33,0x29,0xcb,0xb2,0x21,0x39,0x26,0x99,0xa5,0x3d,0x1d,0xc9,0x91,0x73,0x8e,0x21,0x84,0x4d,0x9f,0x41,0x8,0x61,0xe3,0x9c,0x23,0xc9,0x51,0xba,0x53,0xdf,0xc5,0xbf,0x83,0x41,0x57,0xf8,0x67,0x83,0x5f,0xa3,0xfb,0xe7,0x9f,0x22,0xfe,0x9b,0x41,0xc4,0x29,0x55,0xcd,0x57,0x19,0x48,0xf0,0xde,0x4f,0x44,0xa4,0xc1,0x29,0x95,0x31,0x19,0x1c,0x54,0x75,0x5d,0x55,0xd5,0xd6,0xcc,0xf2,0x3e,0xb1,0x99,0xe5,0x55,0x55,0x6d,0x55,0x75,0x8d,0x53,0x9c,0x63,0x37,0xca,0xd7,0x8b,0xc5,0xe2,0x31,0x84,0x70,0xd3,0xfe,0xf9,0x13,0x44,0x64,0xaf,0xaa,0xcf,0xf3,0xf9,0xfc,0xe,0xc0,0x2b,0x0,0x4b,0x65,0x1a,0xb6,0xeb,0xfc,0xa4,0x4c,0x51,0x44,0xde,0x24,0xb9,0x9f,0xd5,0xb9,0xef,0xbd,0xc9,0xe8,0xa3,0xce,0xef,0x1,0xe9,0xa5,0x7b,0x14,0xf7,0x5d,0x8c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -95,27 +95,22 @@ static const unsigned char font_normal_png[]={ static const unsigned char full_panel_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x73,0x7a,0x7a,0xf4,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x13,0x34,0x38,0xc1,0xd7,0xb6,0x4a,0x0,0x0,0x4,0x58,0x49,0x44,0x41,0x54,0x58,0xc3,0xbd,0x97,0xb1,0x72,0x1d,0x37,0xc,0x45,0xf,0xf6,0xad,0x9e,0xe4,0xc2,0x6d,0x92,0x36,0xfa,0x88,0x64,0x26,0x95,0x93,0x49,0x93,0xaf,0x76,0xe7,0x19,0xfb,0x23,0x5c,0xdb,0x6e,0x5d,0x59,0x4b,0xe2,0xa6,0x0,0x48,0x62,0x9f,0x14,0xa7,0x4a,0x76,0x46,0xab,0x5d,0x3e,0x92,0x0,0x81,0x7b,0x2f,0xb0,0xf6,0xd7,0x1f,0x7f,0x4a,0x12,0xee,0x1e,0x7f,0x12,0x92,0x0,0x40,0x2,0xbb,0x79,0x34,0x40,0xcc,0xf1,0xd3,0xa5,0x17,0xc6,0xc6,0x22,0x81,0x99,0xb1,0x6d,0xc6,0x66,0x1b,0xdb,0xb6,0x61,0x9b,0xb1,0xcb,0x45,0xf7,0x4e,0x6b,0x8d,0xd6,0x3a,0x5d,0x1d,0x77,0x27,0x7c,0xd0,0x79,0xf3,0x97,0x8c,0xbe,0xf4,0x9b,0xaa,0x71,0x40,0x86,0x19,0x6c,0x97,0x8d,0xcb,0x76,0x61,0xbf,0x5c,0xd8,0xf7,0x9d,0xcd,0x2e,0xec,0xbd,0x77,0x8e,0xde,0xf8,0xfa,0xf5,0x2b,0x9f,0xbe,0x7c,0xe6,0xff,0xb8,0x7e,0xfa,0xe1,0x47,0x5e,0xbf,0x7e,0xcd,0x9d,0x60,0xef,0x72,0x8e,0xd6,0xf8,0xf4,0xe5,0x33,0xbf,0xfd,0xf2,0x2b,0x8f,0x8f,0x8f,0xff,0xa9,0xf1,0x8f,0x1f,0x3f,0xf2,0xee,0xc3,0x7b,0x1e,0x5e,0x3d,0x70,0xd9,0x8c,0xdd,0x7b,0xa7,0xf7,0x6,0xc0,0xcf,0x8f,0x3f,0xf3,0xf6,0xed,0x5b,0xee,0xaf,0xd7,0xef,0x46,0x98,0xef,0xa4,0xdf,0xfe,0x21,0x23,0x6,0x7c,0x7b,0x7a,0xe2,0xcd,0xef,0x6f,0x78,0xf7,0xe1,0x3d,0xbd,0x77,0x7a,0x77,0x76,0x97,0xe3,0xde,0x1,0xf0,0xee,0x5c,0xef,0xee,0xf0,0x4,0xa1,0xfd,0xb,0xbe,0xce,0xde,0x9,0x1,0x4a,0x17,0x84,0x2d,0x8,0xe4,0xed,0xee,0xee,0xe,0xef,0xe,0x40,0xf7,0xc0,0xda,0xee,0xe,0x69,0x3f,0x6,0x7,0x3,0x10,0x92,0x4d,0x2f,0x6c,0x6c,0xaa,0x30,0x84,0x19,0x96,0xd6,0x83,0x21,0xc3,0xa8,0xc6,0x28,0x5e,0x9c,0x94,0x9,0x53,0xd8,0x0,0x90,0x83,0xb,0xf6,0xf0,0x56,0x33,0x2,0x41,0xc1,0x3c,0x96,0x7c,0xc6,0x21,0x67,0x84,0x53,0xe3,0x79,0x4,0x5c,0xc2,0xd3,0x57,0xa5,0x83,0x66,0x63,0x5d,0xc6,0xc2,0x85,0xc,0xbc,0xa7,0x3,0x69,0x67,0xa7,0xf0,0xbe,0xf7,0x8e,0x3c,0x23,0x60,0xb1,0x71,0xf2,0x91,0x69,0x37,0x9d,0x33,0x55,0x87,0xe2,0x74,0x9e,0xa7,0xc4,0xc,0xc9,0xc3,0xb7,0x5c,0x6b,0x8,0xdc,0xe8,0xe9,0xc0,0xb0,0xbb,0x3b,0x9a,0xe7,0xeb,0xde,0x11,0xa9,0x1,0x23,0xb7,0x99,0x6,0xf3,0x34,0x6e,0xb9,0x38,0xf3,0x6d,0x16,0xf3,0x57,0xe2,0xc,0xdc,0xb1,0x2,0x20,0x49,0x33,0x4d,0xdd,0x7d,0xc6,0x4f,0x88,0x3d,0x5e,0x98,0x11,0x70,0x1f,0xa7,0x67,0x49,0x60,0x79,0x5d,0x8e,0xc5,0x3c,0xf9,0xad,0xf0,0x45,0xd0,0x49,0xa3,0x6b,0x72,0xdc,0xfb,0x4c,0x41,0xc,0xec,0x2a,0x61,0xee,0xbd,0xcf,0xd0,0x4d,0xf0,0x94,0x3d,0xcc,0x86,0x43,0x76,0x92,0xe7,0xe9,0xd3,0x98,0x43,0x1a,0xb7,0x0,0x72,0x9d,0x33,0x53,0x30,0x22,0x50,0xe9,0xe5,0xdd,0x71,0x39,0x3,0xdf,0xc,0x5c,0x6b,0xa1,0x7a,0x5,0x67,0xcd,0x18,0x83,0x4a,0xcd,0x1f,0x2c,0x40,0xb1,0x4a,0x5,0xc8,0x3d,0x69,0x18,0xf3,0x14,0xb5,0x60,0x80,0xb0,0xf5,0x9e,0x11,0x17,0x15,0xeb,0x83,0xe3,0xb1,0x61,0x8c,0x2e,0x27,0xbd,0xa4,0x48,0x33,0x9,0xb1,0xc3,0x4d,0x7e,0xa4,0x95,0x82,0x8c,0xd2,0xae,0x49,0x9,0xe8,0xbd,0x2d,0xf4,0x9a,0x4d,0xc3,0xf6,0x82,0xfa,0xe8,0xe6,0x79,0xa2,0x1f,0x2f,0x79,0xd7,0x33,0x2d,0x6d,0xa9,0xba,0x52,0xb0,0x7c,0x47,0x3e,0xb7,0xeb,0x7d,0x9,0x91,0xb9,0x46,0x15,0xad,0xc9,0x40,0xaa,0x5a,0xc7,0x0,0x6,0x9e,0x69,0x9a,0x1c,0x37,0x9b,0xd8,0xb2,0xe1,0x98,0xac,0x44,0x20,0x34,0x67,0x57,0x71,0xb4,0xb5,0x96,0xd1,0x48,0x3d,0x73,0x8a,0x13,0x99,0xe7,0xb1,0xaf,0x59,0xee,0xbf,0xc2,0x2c,0x2f,0x98,0xcf,0x9b,0x19,0x79,0xa8,0x10,0xb6,0xa5,0x3,0xa4,0x10,0xd,0xc4,0x4e,0x16,0x14,0x8f,0x54,0xc2,0x37,0xc0,0x5f,0xe9,0xf9,0x42,0x91,0x50,0xa9,0xd,0xc3,0xa9,0x29,0x6c,0x40,0x6f,0xad,0x24,0xcf,0x93,0x86,0x39,0xb9,0xb5,0x50,0x42,0x95,0xda,0x16,0xda,0x5f,0x4a,0xcb,0xd,0x35,0x31,0x61,0xb2,0x53,0x7,0x34,0x22,0x91,0x72,0x70,0x2a,0x4f,0xad,0x15,0x29,0x9e,0x20,0xa4,0xb2,0x20,0x1d,0xb0,0x30,0xee,0xb5,0xec,0xd,0x8a,0xcd,0x32,0xa1,0x41,0x82,0x29,0x14,0xe6,0x2b,0x4d,0x13,0xc6,0xb2,0x94,0xf,0x9f,0xa5,0x5f,0x80,0x5c,0x11,0x81,0x95,0x82,0x86,0xcb,0x73,0x23,0xc7,0xb,0xfe,0xc5,0x59,0x5a,0xcf,0x2c,0xd3,0x39,0x3a,0xe3,0x79,0xe0,0xc9,0x7c,0x92,0xa2,0x95,0x62,0x24,0xc4,0xee,0x65,0xf3,0x0,0x61,0x24,0x4e,0xe7,0x5a,0xf6,0xbc,0x35,0xd1,0xb3,0xc6,0xaf,0x38,0x72,0x2,0x4b,0x46,0x23,0x80,0xdd,0x5a,0x2b,0x3a,0x48,0x54,0x43,0x7c,0x1,0xc4,0x5d,0x98,0x55,0x14,0x9c,0x99,0xbd,0x8,0x39,0xf5,0xf3,0xdc,0xbc,0xc,0x21,0xb3,0x97,0x23,0xd7,0x13,0x3,0x78,0xbc,0x47,0x39,0xce,0x69,0x47,0x6b,0xc1,0xcf,0x1b,0x10,0xa9,0x1e,0xca,0xce,0x32,0xf4,0x2c,0x45,0x5a,0xeb,0x46,0xfd,0x18,0x38,0x33,0xc1,0x51,0x31,0xc0,0x28,0x46,0x79,0x1d,0x29,0x44,0x27,0x2e,0xab,0x80,0xcd,0xc,0x73,0xc5,0xff,0xc5,0xce,0xe7,0x7d,0x60,0xa1,0xef,0xa9,0xbf,0x1,0xda,0x71,0x2c,0x91,0xf,0x16,0xac,0x8,0xf4,0xe3,0x0,0xf7,0x94,0xe1,0x1b,0xe3,0x83,0x92,0x36,0x30,0x62,0x8b,0x1,0x76,0x2b,0xba,0x2a,0x5,0x29,0x5b,0x8a,0x6c,0x99,0x8e,0xa9,0x84,0xe1,0xc4,0x1e,0xb9,0x60,0xea,0x80,0xcf,0x36,0xe6,0x4c,0x37,0x4b,0xb9,0x5d,0xd6,0xb4,0x1a,0x14,0xb7,0xa5,0x90,0x44,0xff,0x17,0xa7,0x5f,0xd5,0x74,0x48,0xb1,0x1f,0x6d,0x9,0x94,0x88,0x8e,0x68,0x84,0xee,0xa9,0x1d,0x93,0x5,0x21,0x28,0xb,0xf1,0xc2,0x66,0x63,0x39,0xde,0xe7,0x9,0xb,0xfa,0x23,0xd7,0xc9,0x51,0xb3,0x73,0x8f,0x69,0xe2,0xa9,0x1d,0x8c,0x12,0xe2,0x12,0x7b,0xad,0x74,0xab,0x1a,0x8e,0x1e,0xc0,0x17,0xb8,0x4c,0x21,0x32,0x83,0xb,0x56,0x2a,0xe5,0xed,0xfc,0xd1,0x94,0xf8,0x60,0x43,0xf4,0x88,0x96,0x54,0xaf,0xd7,0x1e,0xde,0x6c,0x91,0x82,0xa3,0x85,0x14,0x5b,0xa1,0x53,0x65,0xc0,0xc8,0xa7,0x8c,0xa,0x5e,0xcd,0xa2,0xb3,0xe8,0x36,0xfa,0xa0,0xf1,0x8d,0x99,0x81,0x9b,0xe,0x98,0xc5,0x8c,0x9d,0xcd,0xd8,0x2e,0xc6,0xf5,0xfe,0x9e,0xa7,0x6f,0xdf,0x6e,0x44,0xa6,0x56,0xb6,0xf5,0x7c,0xee,0x6,0x9e,0x2d,0x79,0xd6,0x31,0xd4,0xeb,0x68,0x8d,0xeb,0xc3,0x3d,0xdb,0x65,0x83,0xcd,0xd8,0x4d,0xf1,0xb9,0xfc,0xf0,0xea,0x15,0xd7,0xeb,0x15,0x97,0xcf,0x2e,0xb6,0x72,0xac,0x7c,0xa3,0x7c,0xff,0xfb,0xcc,0x5e,0x7e,0x37,0xb,0x35,0xdc,0xb6,0x8d,0xed,0x72,0x61,0x63,0xc3,0x30,0xfe,0x6,0x66,0xdc,0xf6,0xe9,0x76,0x8a,0xde,0xff,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x73,0x7a,0x7a,0xf4,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xe,0x1c,0x26,0x8,0x6f,0x80,0xec,0x0,0x0,0x0,0xfb,0x49,0x44,0x41,0x54,0x58,0x85,0xed,0x97,0x31,0x6a,0x3,0x31,0x10,0x45,0x9f,0x66,0xa4,0xda,0x39,0x81,0xd,0x6e,0x16,0xdf,0xff,0x1a,0x29,0x72,0x2,0x83,0xdd,0x6,0x43,0x5c,0x6b,0x35,0x4a,0xe1,0x68,0x77,0x45,0x16,0xd2,0xac,0x36,0x8d,0x6,0x84,0x40,0xcd,0x7b,0xcc,0xa8,0x98,0xef,0x86,0xe1,0x92,0xf9,0xa9,0x9c,0x73,0x75,0x6f,0x5d,0xce,0xb9,0xea,0x6,0xf0,0x5,0xb8,0x76,0xb6,0x86,0xaf,0x9d,0x4a,0x20,0xa5,0x44,0x4a,0xa9,0xa9,0x80,0xaa,0xa2,0xaa,0xd3,0x9b,0x5f,0xc2,0xdf,0xe,0x7,0x4e,0xc7,0x33,0x66,0x23,0x66,0xb6,0xa9,0x80,0x88,0x20,0xe2,0xb9,0xdd,0xaf,0x7c,0x3d,0x9f,0xa8,0x2a,0x39,0xe7,0xb9,0x3,0x29,0x25,0x4e,0xc7,0x33,0x8f,0xc7,0x27,0x31,0xc6,0x4d,0xe1,0xa5,0x42,0x8,0x2f,0xc6,0xc7,0x3b,0x22,0xf2,0x12,0x5b,0xce,0xdc,0x6c,0x6c,0x6,0x7,0x88,0x31,0x62,0x36,0x56,0xff,0x4c,0x80,0x85,0xc0,0xb6,0x6d,0x5f,0x2b,0x33,0xab,0xfe,0x98,0x34,0x27,0xfe,0x51,0x5d,0xa0,0xb,0x74,0x81,0x2e,0xd0,0x5,0xba,0x40,0x17,0xe8,0x2,0x5d,0x40,0x60,0xde,0xd9,0xcb,0xa6,0xda,0x14,0x28,0x32,0xf1,0x0,0x64,0x99,0x52,0x44,0x3c,0x21,0x84,0x66,0xf0,0x10,0x2,0x22,0xfe,0x77,0x32,0x2a,0x89,0xe5,0x76,0xbf,0xee,0x12,0x4c,0x54,0x75,0xce,0x89,0xc3,0x70,0xc9,0x65,0x55,0xde,0x33,0x9a,0x95,0x91,0x4f,0x1d,0x0,0x50,0x55,0x44,0x64,0xb7,0x70,0xa,0xcc,0x2,0xce,0xb9,0x7f,0x89,0xe7,0xdf,0x5f,0xef,0xae,0xd,0xbd,0x13,0x36,0x6e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; -static const unsigned char hscroll_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x30,0x1c,0x3c,0x99,0xa,0x1c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x53,0x49,0x44,0x41,0x54,0x18,0xd3,0x7d,0x8f,0xc9,0xd,0x80,0x20,0x0,0xc0,0xca,0x21,0xe8,0x5f,0x12,0x89,0x84,0xfd,0x5c,0x48,0x26,0x34,0x3e,0x74,0x2,0xa2,0xe8,0x2,0x40,0xbf,0xed,0xa7,0xc2,0xbb,0xb0,0x3,0x1b,0x75,0x92,0xf0,0x2e,0x7c,0x46,0x9b,0xaa,0xcd,0x4f,0x46,0x3,0x8c,0x76,0xea,0x7,0x4a,0x29,0x5a,0x68,0x0,0x29,0x65,0x3f,0x30,0x83,0xed,0x6,0xe9,0xbc,0x8e,0xf6,0x45,0x79,0xb,0xc0,0x5c,0xb3,0xeb,0x12,0xef,0x1f,0xc6,0x6f,0x12,0x2,0xa,0xbd,0xc9,0x5d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0xc,0x14,0x10,0x3,0x2e,0x15,0xb6,0x7,0x4a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x6a,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xbb,0x6e,0x13,0x51,0x10,0x86,0xbf,0xf1,0x2e,0xb1,0x83,0x85,0x63,0x5,0x10,0xe2,0x22,0xa5,0x0,0x1a,0x24,0x90,0x22,0x9e,0x81,0x2,0xd1,0x53,0xf1,0x2,0x20,0xa,0x1a,0xa,0xa0,0x44,0xd0,0xd0,0x20,0x81,0xe0,0x5,0xa8,0xe8,0x11,0x5,0xcf,0x80,0x22,0x81,0x42,0x3,0x14,0x91,0xb8,0x4,0x85,0x58,0x8e,0x21,0x78,0xd7,0xd9,0x73,0x86,0xe2,0x9c,0xdd,0xec,0xae,0xd7,0xce,0x85,0xe,0xed,0x34,0xbb,0x3a,0x3e,0xf3,0xcd,0xcc,0x3f,0x63,0x69,0x47,0xd8,0x36,0x1,0x1a,0x40,0xe0,0x9f,0x42,0xd1,0x14,0xb0,0x80,0xf1,0x4f,0x25,0x77,0xa9,0x1,0x1c,0x4,0xe6,0x81,0xa3,0x40,0x7,0x38,0x50,0x2,0x6c,0x1,0x3,0x60,0xd,0xe8,0x1,0x7f,0x0,0x9b,0x46,0x6d,0x3,0x67,0xe6,0xe,0x75,0xaf,0xb7,0x9a,0xad,0xcb,0x33,0x33,0xcd,0x53,0x54,0xd8,0x68,0x14,0x7f,0x89,0xe2,0xe8,0xf5,0xc6,0xaf,0xfe,0x73,0xe0,0x13,0xb0,0x29,0x3e,0xd2,0xc2,0x7c,0xf7,0xf0,0xe3,0xd3,0xb,0x67,0xaf,0x3c,0xb8,0xfb,0x88,0xd9,0x4e,0xab,0xca,0x9f,0xe1,0x20,0xe2,0xde,0xc3,0xdb,0x7c,0x5e,0xf9,0xf8,0xaa,0xd7,0x5f,0xbf,0x5,0xac,0x8,0xd0,0x2,0x16,0x8f,0x1f,0x3b,0xf9,0xe6,0xc5,0xb3,0x97,0xed,0x24,0xb1,0x24,0xa3,0xa4,0x12,0x10,0xce,0x84,0x84,0x61,0x83,0x6b,0x37,0xae,0x6e,0x7e,0xff,0xf1,0xf5,0x12,0xb0,0x14,0x7a,0x1d,0xda,0x61,0x10,0xb6,0x87,0xbf,0x63,0x10,0x75,0x47,0xa,0x2a,0x79,0x85,0x95,0x51,0xbc,0xc5,0x28,0x86,0x30,0x8,0xdb,0xbe,0x6c,0x49,0x1,0x1,0x80,0x51,0xeb,0xfc,0x9d,0xc0,0x4e,0x6b,0xf,0xd1,0xfc,0xb9,0xb3,0x20,0x5,0x68,0xfa,0x8b,0x5a,0x8b,0xaa,0x80,0x28,0x82,0xa0,0x28,0xa2,0x92,0x73,0xd3,0xb1,0xde,0x86,0x85,0x46,0x5b,0x45,0x51,0x50,0x45,0xc4,0x95,0x61,0x53,0x27,0x71,0x61,0x74,0x1a,0xc0,0xaa,0xcd,0x6e,0xa8,0x64,0x2f,0xee,0x5d,0x29,0x8a,0x32,0x39,0x3,0x5f,0xb6,0x2f,0x4c,0x45,0x73,0x5a,0xd8,0x31,0x48,0x1,0x60,0xac,0x2d,0xf1,0x5,0x51,0x75,0x45,0x68,0x5a,0xbf,0x4e,0xcf,0x60,0xfb,0x82,0x2b,0x5a,0x73,0x4e,0xb6,0xe2,0xf,0x52,0x2,0xd8,0x82,0xe2,0x14,0x50,0x54,0xc4,0x2f,0x8b,0x68,0xad,0x1f,0x99,0x54,0x79,0x41,0xdd,0x0,0xf8,0xb6,0x82,0x88,0x4e,0xeb,0x82,0x66,0x89,0xaa,0x3b,0xc8,0x52,0x48,0x41,0x56,0x76,0xcc,0x60,0x7b,0x74,0x75,0xac,0x1a,0x49,0x47,0x72,0x72,0x6,0xe2,0xe7,0x56,0x45,0xfd,0x5d,0xc9,0x44,0x28,0x40,0x2b,0x45,0x34,0xea,0x7,0xa8,0x14,0xc9,0x92,0x75,0x64,0x7,0x11,0x8d,0x8f,0x98,0x9b,0x87,0xf2,0xf4,0x4d,0xd5,0x40,0xd5,0xc9,0x97,0xf,0xa3,0x5a,0x74,0x9c,0x36,0x89,0xf7,0x9f,0xdc,0x61,0xaf,0x96,0x1,0x92,0x2d,0xc3,0xe2,0xf9,0x8b,0xbb,0x72,0x5a,0x7a,0xff,0xb6,0x3a,0x83,0x8d,0x41,0x7f,0xcf,0x19,0x34,0xf8,0x47,0xab,0x1,0x35,0xa0,0x6,0xd4,0x80,0x1a,0x50,0x3,0x6a,0xc0,0x7f,0x9,0x90,0x8a,0x4f,0xe0,0x3d,0x67,0x60,0xf7,0xe1,0x6b,0x53,0x80,0x5,0x22,0x63,0x4c,0x6c,0x93,0x5d,0x78,0x25,0x60,0x8c,0x89,0x81,0x8,0xb0,0xd,0xbf,0xca,0xae,0x47,0xf1,0x70,0x79,0xad,0xb7,0xca,0x34,0x88,0x4d,0x60,0xad,0xb7,0x4a,0x14,0xf,0x97,0x81,0x75,0xc0,0xa4,0x9b,0xeb,0x1c,0x70,0xa1,0xd3,0xee,0x3e,0x6d,0x35,0x67,0xcf,0x5,0x41,0x50,0x29,0xae,0x31,0xc6,0x46,0xf1,0xf0,0xc3,0x60,0xb3,0x7f,0x13,0x78,0x7,0x6c,0x48,0x6e,0x85,0xeb,0x0,0x27,0x80,0x23,0x40,0x73,0xc2,0xf2,0x1d,0x3,0x3f,0x81,0x6f,0x7e,0x8f,0x36,0x52,0x12,0x34,0x4c,0xf7,0xc1,0x9,0x55,0xa8,0x2f,0x39,0xd9,0xa7,0xf0,0xe3,0xf6,0x17,0x4c,0x97,0x1d,0x24,0x5b,0x8,0x8b,0x95,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; -static const unsigned char hscroll_bg_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x30,0x29,0x6a,0x2a,0xce,0x3f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x53,0x49,0x44,0x41,0x54,0x18,0xd3,0x7d,0x8f,0xc9,0xd,0x80,0x20,0x0,0xc0,0xca,0x21,0xe8,0x5f,0x12,0x89,0x84,0xfd,0x5c,0x48,0x26,0x34,0x3e,0x74,0x2,0xa2,0xe8,0x2,0x40,0xbf,0xed,0xa7,0xc2,0xbb,0xb0,0x3,0x1b,0x75,0x92,0xf0,0x2e,0x7c,0x46,0x9b,0xaa,0xcd,0x4f,0x46,0x3,0x8c,0x76,0xea,0x7,0x4a,0x29,0x5a,0x68,0x0,0x29,0x65,0x3f,0x30,0x83,0xed,0x6,0xe9,0xbc,0x8e,0xf6,0x45,0x79,0xb,0xc0,0x5c,0xb3,0xeb,0x12,0xef,0x1f,0xc6,0x6f,0x12,0x2,0xa,0xbd,0xc9,0x5d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_node_close_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0xc,0x15,0x14,0x15,0x39,0x35,0x48,0xf8,0xe3,0x0,0x0,0x0,0x80,0x49,0x44,0x41,0x54,0x28,0xcf,0xa5,0xd1,0xb1,0xa,0xc2,0x40,0x10,0x84,0xe1,0x4f,0xe5,0x30,0xad,0x9d,0xb5,0x60,0xeb,0x3,0x88,0x2f,0x6d,0xfa,0xb4,0x29,0x83,0xbd,0xb5,0xb5,0x9d,0x68,0x15,0x9b,0x3d,0xb9,0x4,0x11,0xe,0x7,0xb6,0xd9,0xfd,0x67,0xb9,0xb9,0xa5,0x52,0xab,0xa8,0x13,0xb6,0x78,0xe0,0x39,0x63,0x36,0x38,0x60,0x87,0x1b,0x34,0xb8,0x60,0xc4,0x19,0xa9,0x80,0x53,0xf4,0xc6,0x60,0x9a,0x72,0xd0,0xc6,0xa0,0x2b,0xc,0x5d,0xf4,0xda,0xd9,0xa2,0x8f,0x29,0x3,0x43,0x54,0x5e,0x90,0x7e,0xe5,0xca,0x60,0x36,0x4e,0xb4,0xf4,0x87,0xaa,0x9e,0x54,0x15,0xba,0xea,0x5b,0x17,0x71,0xb8,0x23,0x5e,0xb8,0xe2,0xfe,0xe5,0x70,0x7b,0xac,0xd1,0x57,0x7,0x7d,0x3,0x51,0x8f,0x29,0x6b,0x3c,0x49,0x28,0x81,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; -static const unsigned char hscroll_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x2f,0x24,0xd9,0xc1,0xbc,0x1c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x93,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0x8f,0xb1,0xa,0x82,0x50,0x18,0x46,0x8f,0xf9,0x73,0xad,0x74,0x68,0xa8,0x20,0x68,0x71,0x72,0x10,0x5a,0x5b,0x7a,0xfc,0x96,0xa6,0xa0,0x47,0x88,0xa0,0x92,0x1b,0x86,0x10,0x79,0xed,0xbf,0xda,0x10,0x4,0x2d,0x79,0x96,0x6f,0x3b,0x1f,0x27,0x58,0xcc,0x96,0x1d,0x7f,0x10,0x11,0x61,0x3a,0x99,0xb3,0x5e,0x6d,0x18,0x45,0x31,0x0,0x4f,0xf7,0x60,0x77,0xd8,0x62,0xef,0x5,0x2,0x90,0xa5,0x39,0xd7,0xdb,0x19,0xef,0x3d,0x0,0x61,0x18,0x92,0xa5,0x39,0x76,0x5f,0x20,0xaa,0x8a,0x6b,0x6a,0x5c,0x53,0x7f,0xb5,0xea,0x5f,0x9f,0x55,0x45,0x8c,0x18,0x4e,0x97,0x23,0x91,0x19,0xfe,0x7c,0xbb,0xa6,0xc0,0x88,0x61,0x10,0x8f,0x13,0xca,0xca,0xe2,0x5b,0xa5,0xa3,0xa5,0xa3,0xc5,0xb7,0x4a,0x59,0x59,0xe2,0x71,0x42,0xd0,0x57,0xd1,0xcb,0x1b,0xea,0x76,0x39,0x31,0xbf,0x4b,0x5d,0xcc,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 -}; - - -static const unsigned char hscroll_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x2e,0x38,0xd4,0xdb,0xd1,0x12,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x95,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0x8f,0x21,0xf,0x82,0x40,0x0,0x85,0x3f,0xe4,0x6e,0x27,0xca,0xa0,0x58,0x1c,0xc5,0x60,0x21,0x11,0x28,0x56,0x83,0xbf,0xda,0x60,0xb0,0xf8,0x23,0x9c,0xc5,0x9d,0xe0,0x70,0x34,0xc7,0xb1,0x3b,0xd0,0x80,0x73,0xb3,0xc8,0xf7,0xc2,0x4b,0xef,0xbd,0x3d,0x6f,0x95,0xac,0x5f,0xfc,0x41,0x48,0x29,0x59,0x2e,0x12,0xb6,0x9b,0x1d,0xc1,0x74,0xe,0x40,0x63,0x9e,0x1c,0x4e,0x7b,0x8a,0x87,0x46,0x0,0x64,0x69,0xce,0xed,0xae,0x71,0x5d,0x37,0xa4,0x7c,0x9f,0x2c,0xcd,0x29,0x8e,0x1a,0x61,0xad,0xc5,0x98,0x6,0xd3,0x36,0xdf,0x5a,0xe7,0x6,0xb7,0xd6,0x22,0x94,0x54,0x5c,0xae,0x67,0x2,0x35,0xfb,0xd9,0x6e,0x5a,0x8d,0x92,0x8a,0x49,0x14,0xc6,0x54,0x75,0x89,0xeb,0x2d,0xfd,0x47,0xae,0xb7,0x54,0x75,0x49,0x14,0xc6,0x78,0x63,0x2f,0x46,0x79,0x3,0x79,0x63,0x38,0x4a,0x58,0xf8,0x57,0x67,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +static const unsigned char graph_port_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x6,0x0,0x0,0x0,0x8d,0x32,0xcf,0xbd,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0xc,0x14,0x17,0x20,0x3,0xeb,0x8f,0x3a,0xdb,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x65,0x49,0x44,0x41,0x54,0x18,0xd3,0x4d,0xd0,0x4f,0x6b,0xda,0x70,0x1c,0x7,0xe0,0xcf,0x37,0x7f,0x7e,0x49,0x66,0xd2,0x64,0x61,0x5,0x61,0x76,0x47,0xf1,0xa4,0x2d,0xdb,0x75,0x5,0x11,0x84,0xb0,0x5e,0xeb,0xd9,0xeb,0xf4,0x6d,0xec,0x2d,0xf8,0x26,0xb6,0x77,0xe0,0x45,0xba,0xa3,0x6c,0xa0,0x3b,0xad,0x39,0xb6,0x36,0x8,0x1b,0x4b,0x32,0xd2,0xc6,0x6c,0x9a,0x4f,0x4f,0x85,0x3e,0x2f,0xe1,0x11,0x0,0x20,0x29,0xd3,0xe9,0xd4,0xda,0x6e,0xb7,0x23,0xdf,0xf7,0xbb,0x0,0x90,0xe7,0xf9,0x8f,0x66,0xb3,0xf9,0x79,0x36,0x9b,0x55,0x22,0x42,0x83,0xa4,0x44,0x51,0xf4,0xea,0xe2,0xe2,0xc3,0xf7,0xf1,0x78,0xdc,0xa,0x82,0x40,0x8,0x20,0xcf,0x32,0x2e,0x97,0xcb,0x4f,0x51,0x14,0xbd,0x25,0xf9,0x5b,0x26,0x93,0x89,0xdd,0xe9,0x74,0xe2,0xf7,0xe7,0xe7,0x27,0x59,0xfa,0x87,0x65,0xb9,0x13,0x0,0xb0,0x1d,0x9b,0xe1,0xcb,0x50,0xbe,0x5e,0x5d,0xdd,0xfe,0xbc,0xbe,0x6e,0x6b,0x49,0x92,0x8c,0x4e,0x7b,0xa7,0xad,0xbf,0x79,0x4e,0xd3,0x54,0x12,0x86,0x21,0xc2,0x30,0x84,0x32,0x95,0xe4,0x79,0xc6,0xde,0xd9,0x59,0x2b,0x49,0xee,0x46,0x86,0xeb,0xba,0x5d,0xfb,0x85,0x23,0x87,0xfd,0x1e,0xb6,0xed,0x40,0xd7,0x35,0x0,0x40,0x7d,0x38,0xa0,0xdc,0xed,0x44,0x37,0x74,0xb8,0xae,0xd7,0x35,0x48,0x62,0xff,0xff,0x1f,0xfc,0x20,0x80,0xae,0xe9,0x78,0x42,0x0,0xca,0xb2,0x90,0x65,0x19,0x58,0xd7,0xd0,0x8a,0xa2,0x58,0xa7,0x69,0x56,0x6b,0xa2,0x51,0x29,0x5,0xcb,0x52,0xb0,0x94,0x5,0x4b,0x29,0x88,0x8,0xd3,0x34,0xad,0x8b,0xfb,0x62,0xad,0xf,0x6,0x83,0xb8,0xaa,0xaa,0xb1,0xe7,0x79,0xbe,0x77,0x74,0x44,0xb7,0xe1,0x89,0x69,0x1a,0x28,0xcb,0x92,0x9b,0xcd,0x46,0x56,0xab,0xd5,0x86,0xe4,0x47,0x21,0x29,0xc3,0xe1,0xf0,0xb8,0xdf,0xef,0x7f,0x6b,0xb7,0xdb,0xaf,0x1b,0x8d,0x86,0x46,0x10,0xf,0xf7,0xf,0x75,0x1c,0xc7,0x77,0x8b,0xc5,0xe2,0xdd,0x7c,0x3e,0xff,0x25,0xcf,0xc3,0x6f,0x6e,0x6f,0x2e,0x1d,0xdb,0xe9,0x9,0x80,0xb2,0x2a,0xd7,0x27,0xad,0x37,0x5f,0x9e,0xc2,0x1f,0x1,0x3a,0xe6,0xa5,0x7b,0xef,0xf2,0xf3,0xcd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -125,32 +120,32 @@ static const unsigned char hseparator_png[]={ static const unsigned char hslider_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x16,0x2b,0x22,0x53,0xc7,0x74,0xf1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xd1,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0x93,0x31,0x4a,0x4,0x41,0x14,0x44,0xdf,0xff,0xfd,0x77,0x86,0x41,0x57,0x10,0x19,0x99,0xc1,0x89,0xd,0x4d,0x4,0xf,0xe0,0x49,0xc4,0xcc,0x23,0x98,0xb8,0x18,0x9,0x5e,0xc0,0x4c,0x3c,0x8f,0x60,0x62,0x68,0xec,0xb2,0xa2,0x88,0x81,0x8b,0x83,0xd2,0xfd,0xdb,0xc8,0xd8,0xde,0x7c,0xb,0x2a,0xac,0x82,0x57,0x50,0xb0,0x96,0x0,0xf4,0xed,0x70,0x2,0x9c,0x1,0x47,0x85,0xb9,0x7b,0xe0,0x66,0xf1,0xf6,0x7c,0x27,0x7d,0x3b,0x5c,0x84,0x10,0x2e,0x45,0x4,0x45,0x8b,0xd2,0x8e,0x93,0x73,0x26,0xa5,0x34,0x93,0xbe,0x1d,0x16,0x4d,0xdd,0x74,0xaa,0x8a,0x4a,0x28,0x2b,0xc8,0x9,0x77,0x67,0xfc,0x1e,0x5f,0xc,0xe8,0xaa,0x49,0x8d,0xaa,0xae,0x40,0x6e,0x7f,0x5,0x9d,0x1,0x73,0x33,0xdb,0x13,0x74,0xa5,0xf1,0x54,0x1d,0x60,0x1e,0xa6,0x1b,0x5b,0xd,0x39,0x1f,0x57,0x93,0x1a,0x33,0x43,0x55,0xff,0xb5,0xbb,0xf3,0x35,0x2e,0x89,0x29,0x5e,0xb,0xc0,0xc1,0xfe,0xe1,0xd5,0xc7,0xe7,0xfb,0x69,0x8c,0x71,0xb7,0x8,0xc0,0xec,0x75,0x7b,0xba,0x73,0xfb,0xf8,0xf4,0x70,0x2e,0x0,0x9e,0xbc,0x2,0x36,0xa1,0x98,0xc3,0x81,0xa5,0x6,0xfd,0x59,0x3f,0x1,0x7e,0x1,0xa,0xde,0x42,0x4a,0x10,0xf4,0x3a,0xdc,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xf,0xc,0x8,0x9f,0xb9,0xf5,0x45,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x4d,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0x14,0x3,0x46,0x18,0x43,0x42,0x42,0x62,0x1a,0x3,0x3,0x43,0x26,0x91,0xfa,0xa6,0xbf,0x78,0xf1,0x22,0xb,0xdd,0x80,0xff,0xec,0xec,0x9c,0x44,0xe9,0xfe,0xf9,0xf3,0x3b,0xc3,0x8b,0x17,0x2f,0x18,0x19,0x18,0x18,0x18,0x98,0x88,0x76,0x2b,0xe,0x30,0xf0,0x6,0xb0,0x20,0xb1,0xa7,0xff,0xfc,0xf9,0x9d,0xe8,0x40,0xa4,0xd4,0xe2,0x51,0x80,0x4,0x0,0x2b,0x51,0x10,0x8d,0x9f,0x1f,0x30,0xd7,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char hslider_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x16,0x29,0x3a,0x72,0x9d,0x8e,0x25,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xd8,0x49,0x44,0x41,0x54,0x38,0xcb,0x7d,0x92,0xb1,0x6b,0x13,0x51,0x1c,0xc7,0x3f,0xaf,0x9,0x69,0xd2,0x33,0x26,0x2d,0x6d,0x48,0x8a,0x2d,0x94,0x82,0x48,0x43,0x3b,0x38,0x64,0xa,0x85,0x4e,0x3a,0x65,0x32,0xbb,0xab,0xb3,0x53,0x17,0x41,0x71,0xe8,0x1f,0x20,0x38,0x9,0xee,0x3a,0x39,0xb9,0xb8,0x9,0x82,0x83,0x83,0x42,0x87,0x82,0x83,0xb6,0x31,0xe1,0x25,0xc6,0xea,0xe5,0x72,0x97,0xcb,0xbd,0xfb,0x39,0x24,0x17,0x72,0xcd,0xe9,0x17,0x1e,0xf7,0xde,0xef,0xf7,0x7d,0x9f,0xdf,0xef,0xdd,0x7b,0x8a,0xa9,0x4a,0xa5,0x12,0x29,0xc9,0xdc,0x7,0x1e,0x0,0x35,0x92,0xf5,0x11,0x78,0x6e,0x94,0xff,0x52,0x6b,0xd,0x40,0x3a,0xca,0xa4,0x24,0xf3,0xa8,0xbc,0xbe,0xf9,0xf8,0xe0,0xe6,0x6d,0xd6,0xa,0x1b,0x89,0xbb,0xfb,0xbf,0xbb,0xb5,0xcf,0x67,0x9f,0x6a,0x9d,0xde,0x8f,0x6d,0xe0,0x9,0x80,0x8a,0x92,0x95,0x8d,0x1b,0xed,0xbb,0xf5,0x46,0xd9,0x71,0x1d,0xbc,0x91,0x9b,0x8,0xc8,0x2e,0xe7,0xb0,0x72,0x16,0x6f,0xdf,0xbf,0xe9,0xb4,0xbb,0x17,0x95,0x58,0x7,0x40,0xf9,0xd2,0xfe,0x85,0x31,0x86,0x7f,0xc9,0x1b,0xb9,0x8c,0x3,0x1f,0xa0,0x1c,0xc5,0xe6,0x1,0xf8,0x63,0x6f,0xae,0x29,0x99,0x7e,0x55,0xc,0x12,0x84,0x41,0x6c,0x1d,0x3,0x84,0x2,0x4a,0x42,0x44,0x81,0x42,0x81,0x80,0x10,0xa2,0x50,0x88,0x92,0x49,0x6c,0x6,0x4e,0x0,0x48,0x28,0x88,0x12,0x8,0x15,0x82,0xcc,0xec,0x82,0xa0,0x44,0x8,0x91,0x85,0x8e,0xe2,0x0,0x9,0xa7,0x5,0x26,0x46,0x99,0xab,0x96,0x34,0x4b,0x0,0xcc,0x27,0x25,0xf1,0x47,0x5e,0x8d,0xc6,0x0,0xbd,0x4b,0xcd,0xda,0xf5,0x75,0xfe,0xa7,0xfe,0x9f,0x5e,0x6c,0xbd,0x14,0x4d,0x1a,0x47,0xcd,0x43,0xdd,0xef,0x30,0x70,0x6d,0x26,0xa7,0x5d,0x1c,0x3,0xd7,0x46,0xf7,0x3b,0x34,0x8e,0x9a,0x87,0x5c,0xbd,0xa3,0xe9,0x53,0xbe,0x97,0x4e,0xa7,0x5f,0x6d,0x57,0x76,0xc8,0xa4,0x33,0xb1,0x4a,0x7e,0xe0,0x73,0xd1,0xfe,0x86,0x1f,0xf8,0x4d,0xa3,0xfc,0xd7,0xd1,0x53,0x4e,0x45,0x6,0xcb,0xb2,0x10,0x65,0x4e,0x9,0x95,0xed,0x8d,0xdc,0x3b,0x56,0x2e,0xcf,0x92,0x9a,0xf0,0x3,0x63,0x68,0xeb,0x73,0x46,0xe3,0xd1,0x43,0xa3,0xfc,0x17,0x0,0x8e,0xe3,0x2c,0x2,0xb4,0xd6,0xac,0x5c,0xcb,0x7e,0x30,0x81,0x64,0xfd,0xb1,0x57,0xcf,0x5b,0x5,0x0,0xda,0xdd,0x73,0x86,0xde,0xf0,0xc4,0x28,0xff,0xa9,0xd6,0x1a,0xcb,0xb2,0x16,0x1,0xd5,0x6a,0x95,0x5b,0x5b,0x7,0xac,0x14,0x96,0x29,0xac,0xe6,0xdf,0xf5,0xba,0xfd,0x6c,0x60,0x82,0xba,0xe3,0xe,0xb0,0x87,0xf6,0xc9,0xd6,0xce,0xe6,0x71,0xb1,0x58,0x9c,0x79,0x5a,0xad,0xd6,0xe2,0x2d,0xcc,0x6b,0x6f,0x77,0xff,0xf8,0xf4,0xeb,0x97,0xef,0x40,0x6a,0x6f,0x77,0xff,0x99,0x1d,0xfe,0x4c,0xf4,0xfd,0x5,0x7b,0xf0,0xd8,0x4,0x34,0x6f,0x3,0xa9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x92,0x0,0x92,0x0,0x99,0x25,0xc1,0x88,0x71,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x2,0x21,0x6d,0xbf,0x58,0x46,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x4b,0x49,0x44,0x41,0x54,0x38,0x8d,0xa5,0x93,0x31,0x6b,0xc2,0x40,0x14,0xc7,0xff,0x77,0xbd,0x34,0x26,0x97,0x5a,0x2c,0x41,0xa,0x9d,0x6b,0x8,0x86,0x2e,0xe,0xfd,0x4,0x1d,0xb2,0xf8,0x29,0x3a,0x15,0xec,0x87,0xa9,0x63,0xfb,0x3d,0x9c,0x3b,0x76,0xd0,0x82,0x8,0xe1,0x14,0xdc,0x82,0x74,0xc8,0x50,0xc4,0xdc,0x5d,0x32,0xd8,0xe5,0x22,0xa1,0x60,0x95,0xfa,0x1f,0x1f,0xef,0xf7,0xe3,0xdd,0xe3,0x1d,0x70,0x62,0xc8,0xef,0x42,0x10,0x4,0x37,0x0,0x6,0x0,0x62,0x0,0x1d,0x53,0x9e,0x3,0x18,0x1,0x18,0xa,0x21,0xd2,0xbd,0x82,0x20,0x8,0x1e,0x1,0xbc,0x84,0x61,0xe4,0xb8,0x2e,0x87,0x65,0x9d,0x3,0x0,0xca,0xb2,0x40,0x9e,0x6f,0x90,0x24,0x33,0x9,0xe0,0x59,0x8,0xf1,0x56,0x31,0x67,0x75,0xb8,0xd5,0xba,0x7a,0xed,0x76,0xef,0x2c,0xcf,0x6b,0x82,0x31,0x6,0x42,0x8,0x8,0x21,0x60,0x8c,0xc1,0x71,0x5c,0xb4,0xdb,0xd7,0x96,0x52,0xb2,0xcf,0x39,0x4f,0xb3,0x2c,0x9b,0xec,0x26,0x30,0x63,0x2f,0x7a,0xbd,0x7b,0xc7,0xb6,0x1b,0x7f,0xbe,0x59,0x6b,0x85,0xf1,0xf8,0x43,0x2,0xb8,0x15,0x42,0xa4,0xd4,0xd4,0x7,0x61,0x18,0x1d,0x84,0x1,0xc0,0xb6,0x1b,0x8,0xc3,0xc8,0x31,0x7b,0x42,0x25,0x88,0x5d,0x97,0x1f,0x84,0xab,0x98,0xde,0xb8,0x2e,0xe8,0x54,0xb,0x3b,0x26,0xa6,0xb7,0x53,0x17,0xfc,0x3b,0x95,0x60,0x5e,0x96,0xc5,0xd1,0x90,0xe9,0x9d,0xd7,0x5,0xa3,0x3c,0xdf,0x1c,0x2d,0x30,0xbd,0xa3,0xba,0x60,0x98,0x24,0x33,0xa9,0xb5,0x3a,0x8,0x6b,0xad,0xaa,0x83,0x1a,0x2,0xe6,0x90,0xb2,0x2c,0x5b,0xfb,0xbe,0xff,0xa5,0x94,0xec,0x37,0x9b,0x97,0x60,0x8c,0xed,0x85,0x97,0xcb,0x5,0x94,0x92,0x4f,0x42,0x88,0xf7,0x9d,0xc0,0x48,0x26,0x9c,0xf3,0x74,0xb5,0x4a,0x1f,0x3c,0xef,0xc2,0xa2,0x94,0x82,0x52,0x8a,0xed,0x76,0x8b,0xa2,0xd0,0x58,0xaf,0xbf,0x31,0x9d,0x7e,0x4a,0x3,0xef,0x4e,0xf9,0xe4,0xcf,0x74,0x72,0x7e,0x0,0xd9,0x87,0x82,0x9b,0x21,0x12,0xa2,0x6e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char hslider_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x16,0x2a,0x25,0xd4,0xb8,0xd0,0x13,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xd9,0x49,0x44,0x41,0x54,0x38,0xcb,0x7d,0x92,0x3d,0x6f,0x13,0x41,0x10,0x86,0x9f,0xbd,0xe0,0xf8,0xe3,0x8c,0x7c,0x12,0xc2,0x36,0x10,0x12,0xb9,0x40,0x41,0xb6,0x44,0x41,0xe1,0x2a,0x4a,0x43,0x81,0x52,0xd1,0x80,0xbb,0x48,0xb4,0xd4,0x54,0x69,0x90,0x40,0x14,0xf9,0x1,0x48,0x54,0x48,0xd4,0x40,0xc3,0xf,0x48,0x8d,0x94,0x82,0xd2,0x12,0x5,0x22,0x9,0x3e,0xd9,0x3e,0xc7,0x6,0xfc,0xb5,0xb9,0x3b,0xef,0x2e,0x85,0xed,0x70,0x8e,0x8f,0x8c,0xb4,0x5a,0xcd,0xcc,0xbb,0xcf,0x8c,0x76,0x46,0x30,0xb3,0x7c,0x3e,0xcf,0xaa,0x48,0x3f,0x5,0x9e,0x1,0x55,0xe2,0xed,0x10,0x78,0x1b,0x18,0xf9,0xde,0xf3,0x3c,0x0,0xae,0xcc,0x33,0xab,0x22,0xfd,0xe2,0x56,0x61,0xfd,0xe5,0xfd,0x72,0x95,0x6b,0xce,0xf5,0xd8,0xd7,0xdd,0xdf,0x9d,0xea,0xd7,0xfa,0x61,0xd5,0x6d,0x9f,0xac,0x3,0xaf,0x0,0xc4,0x3c,0xb9,0x56,0xd8,0x68,0x3e,0x7a,0x50,0x2b,0x8e,0xc6,0x43,0xa4,0x2f,0x63,0x1,0xe9,0x64,0x1a,0x3b,0x93,0xe5,0xf3,0xc1,0x87,0x56,0xa3,0x7d,0x7c,0x63,0xa1,0x3,0xa0,0xf8,0xab,0xdf,0x43,0x29,0xc5,0xff,0x4c,0xfa,0x92,0x60,0x12,0x0,0x14,0xe7,0xb1,0x28,0x80,0x20,0x94,0x91,0xa6,0xcc,0xec,0x16,0xb,0x90,0x89,0xe,0x17,0xfc,0x5,0x80,0x36,0x20,0xb4,0xc6,0x58,0x20,0x10,0xa0,0xc1,0xa0,0x11,0x8,0x8c,0x65,0xa6,0xb1,0x73,0x70,0x1c,0x40,0x19,0x10,0x6,0xd4,0x54,0x68,0x1,0x7a,0xd6,0x8d,0xa5,0xc,0xa,0xb3,0xd4,0xd1,0x2,0xc0,0x18,0x3d,0x2b,0x30,0x15,0xaa,0x48,0xb5,0x7f,0x3f,0x63,0x2e,0x3,0x44,0x93,0x26,0xf6,0x23,0x2f,0x46,0xad,0xa8,0xe3,0xf5,0x5a,0x68,0xad,0x2f,0x3d,0x9d,0x5e,0x2b,0x1e,0x50,0xdb,0xd9,0xdd,0x6e,0x9e,0xba,0xc,0xc6,0x7d,0xc,0x3a,0xf6,0xc,0xc6,0x7d,0x9a,0xa7,0x2e,0xb5,0x9d,0xdd,0x6d,0x2e,0xce,0x68,0xb6,0xca,0x8f,0x13,0x89,0xc4,0xc7,0xd2,0xda,0x1d,0x92,0x89,0xd5,0x85,0x4a,0x7e,0x18,0x70,0xdc,0xf8,0x8e,0x1f,0xfa,0x4f,0x2,0x23,0x3f,0xcd,0x57,0x79,0x65,0x2e,0xb0,0x6d,0x1b,0xc5,0xa4,0x2e,0xb4,0x35,0x90,0x67,0xe3,0x87,0xd9,0x4c,0xe,0xcb,0x9a,0xf2,0xc3,0x89,0xa2,0xd1,0x3c,0xe2,0x2c,0x90,0xcf,0x3,0x23,0xdf,0x1,0x8c,0x46,0xa3,0x65,0x80,0xe7,0x79,0xa4,0xec,0xe4,0x17,0xad,0x4c,0xca,0xf,0xe5,0x56,0xce,0x76,0xc0,0xc0,0xcf,0xf6,0x11,0x23,0x39,0xdc,0xf,0x8c,0x7c,0xed,0x79,0x1e,0xb6,0x6d,0x2f,0x3,0x2a,0x95,0xa,0x77,0x6f,0xdf,0x23,0x93,0x4b,0x72,0xd5,0xc9,0x1e,0x74,0x3b,0xbd,0xd4,0x44,0x85,0x5b,0x83,0x71,0x9f,0xfe,0xf0,0xcf,0xfe,0xcd,0x8d,0xc2,0x9e,0xe3,0x38,0xe7,0x1a,0xd7,0x75,0x97,0xc7,0x18,0xb5,0xcd,0x52,0x79,0xef,0xdb,0x8f,0xfa,0x9,0xb0,0xb2,0x59,0x2a,0xbf,0x19,0xe8,0x6e,0xac,0xee,0x2f,0x2,0xc9,0xee,0x56,0x52,0x6e,0x3f,0xf8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x92,0x0,0x92,0x0,0x99,0x25,0xc1,0x88,0x71,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x2,0x1d,0x42,0xd0,0x24,0xc1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x30,0x49,0x44,0x41,0x54,0x38,0x8d,0xa5,0x93,0xb1,0x6a,0xc2,0x50,0x14,0x86,0xbf,0x63,0xe2,0x90,0xd0,0x2e,0xc1,0xad,0x8b,0xad,0x60,0x9e,0xc0,0xbe,0x41,0x7,0x33,0x38,0x7,0x1d,0xba,0x74,0x2a,0xe8,0xc3,0xe8,0x68,0xc1,0x49,0xc8,0xec,0x10,0x9f,0xa1,0x8,0xee,0x71,0xcf,0x52,0x4d,0x70,0x73,0x8a,0xb7,0x83,0x37,0x72,0x11,0xb4,0xa1,0xfe,0xe3,0xe5,0x7c,0xdf,0xbd,0x1c,0xfe,0xb,0x77,0x46,0x2e,0xf,0x7c,0xdf,0x7f,0x2,0x86,0x40,0x17,0x68,0xeb,0xe3,0xd,0xb0,0x4,0x26,0x49,0x92,0xa4,0x57,0x5,0xbe,0xef,0x7f,0x0,0xe3,0x30,0x1c,0x38,0x9e,0xd7,0x40,0xa4,0x6,0x80,0x52,0x47,0xf2,0x7c,0x47,0x14,0xcd,0xf,0xc0,0x28,0x49,0x92,0xaf,0x92,0xb1,0x4c,0xb8,0xd9,0x7c,0x9e,0xf6,0xfb,0xef,0x75,0xd7,0x7d,0xd4,0xb0,0x0,0x82,0x48,0xd,0xd7,0x7d,0xa0,0xd3,0x79,0xad,0x6f,0xb7,0x3f,0x3d,0xdb,0xb6,0xd2,0x2c,0xcb,0xd6,0x0,0x35,0xe3,0xd9,0xe3,0x20,0xe8,0x21,0x62,0x71,0x2d,0x22,0x16,0x41,0xd0,0x3,0x18,0x6b,0xe6,0x24,0x0,0x86,0x61,0x38,0x70,0x6e,0xc1,0xa6,0x24,0xc,0x7,0x8e,0xde,0xd3,0x59,0xd0,0xf5,0xbc,0xc6,0x9f,0x70,0x19,0x3d,0xdb,0x35,0x5,0xed,0x72,0x61,0x55,0xa2,0x67,0xdb,0xa6,0xe0,0xdf,0x29,0x5,0x1b,0xa5,0x8e,0x95,0x21,0x3d,0xbb,0x31,0x5,0xcb,0x3c,0xdf,0x55,0x16,0xe8,0xd9,0xa5,0x29,0x98,0x44,0xd1,0xfc,0xa0,0x54,0x51,0xe1,0xf6,0xa2,0x2c,0xd4,0xe4,0x2c,0xd0,0xf5,0x1c,0xc5,0xf1,0x82,0x5b,0x12,0xa5,0xa,0xe2,0x78,0x1,0xa7,0x36,0xa6,0x60,0x34,0x31,0xcb,0xb2,0xb5,0x6d,0x5b,0xe9,0x6a,0xf5,0xfd,0xd6,0x6a,0xbd,0xd4,0x1d,0xc7,0x41,0x44,0x34,0x78,0x24,0xcf,0xb7,0xcc,0x66,0xd3,0xc3,0x7e,0xbf,0xff,0x34,0xab,0x7c,0xf7,0x67,0xba,0x3b,0xbf,0x4d,0x78,0x75,0x34,0x1f,0x21,0x5d,0xa6,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char hslider_tick_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x31,0xb6,0xde,0xf3,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x17,0x21,0x8,0xd7,0xb2,0xc8,0x2e,0x0,0x0,0x0,0x63,0x49,0x44,0x41,0x54,0x18,0xd3,0xbd,0x8f,0x21,0x12,0x40,0x50,0x14,0x0,0x97,0x4f,0xf2,0x83,0x22,0x71,0x9,0xc7,0x73,0x7,0x4d,0x76,0x3,0x7,0x70,0xb,0xa3,0xf8,0x81,0x88,0x31,0x23,0x31,0x9e,0x4a,0xa1,0x20,0xdb,0xb8,0x69,0x57,0x1,0xe4,0x59,0x96,0xb8,0x58,0x62,0xba,0x76,0xb2,0x1,0x44,0x84,0x9b,0x97,0x50,0x0,0xbe,0xa7,0x5,0x98,0x4d,0xd7,0xae,0xe,0xc0,0xa0,0x83,0x8a,0x5f,0x51,0x0,0x69,0x51,0xb2,0x1e,0x8a,0xbe,0xa9,0xaf,0xd2,0xfd,0x91,0x1e,0x2d,0x63,0x12,0x6e,0x73,0xfc,0xf9,0xf2,0x12,0x27,0xf1,0xc,0x27,0x85,0x5f,0x3c,0x99,0x1e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x31,0xb6,0xde,0xf3,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x34,0x2e,0xcd,0x40,0x50,0x4c,0x0,0x0,0x0,0x65,0x49,0x44,0x41,0x54,0x18,0x95,0xbd,0x8f,0xb1,0x9,0x80,0x30,0x10,0x0,0x8f,0x44,0xb0,0x4a,0x61,0xa3,0x73,0x38,0x5e,0x76,0x70,0x80,0xc,0xe1,0x0,0x6e,0x21,0x36,0xc2,0xf7,0x16,0x62,0xa,0x41,0x78,0xc1,0x4a,0x1b,0xb5,0x50,0xb0,0xf4,0xca,0xab,0xee,0x2c,0x40,0x8,0xc1,0x1b,0x63,0x54,0x44,0x46,0x3,0xa0,0xaa,0x5c,0xbc,0x84,0x5,0x70,0xce,0x29,0x10,0x45,0x64,0x49,0x0,0xa6,0x34,0x6b,0xf9,0x15,0xb,0x50,0xd5,0xd,0xcb,0x6e,0x19,0xfa,0xee,0x2c,0x5d,0x1f,0xe9,0xc5,0x1a,0x7d,0xbe,0xcd,0xe5,0x2d,0x3e,0xe7,0xe,0xef,0x24,0x27,0x89,0xb7,0xa5,0x60,0x2,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char hsplit_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x3b,0x0,0x36,0x0,0x38,0x27,0x56,0x13,0x54,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xc,0x1b,0x3,0x20,0x14,0x7b,0xdd,0x35,0x55,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x7d,0x49,0x44,0x41,0x54,0x18,0xd3,0x4d,0x8e,0x41,0xe,0x2,0x31,0xc,0x3,0xc7,0x65,0xbf,0x89,0xb8,0xf0,0x7f,0x9,0xa4,0xdd,0xa5,0xaa,0x53,0x73,0xa0,0x2,0x72,0x4b,0x3c,0xb1,0xad,0xfb,0xf5,0x96,0xc7,0xe3,0x89,0x4,0xae,0x89,0x3d,0xa8,0x2a,0x5c,0x45,0xef,0x2f,0xb6,0xfe,0xea,0xb8,0x4c,0x95,0xb1,0xeb,0x2b,0xce,0x32,0xe7,0xd9,0x69,0x21,0x90,0x40,0xc4,0xff,0x4,0x21,0x42,0x93,0x84,0x24,0x50,0x0,0x21,0x40,0x1f,0x82,0xd6,0x2e,0xb4,0xdf,0x8b,0x90,0x42,0xd6,0xaa,0x45,0x36,0x8,0x4,0x58,0xa2,0xbe,0x11,0xcb,0x5,0xb4,0xae,0x42,0x8b,0xfd,0x6f,0xb2,0xed,0xfb,0xce,0x71,0x9c,0x38,0xa6,0x66,0xc8,0xc,0xd3,0x66,0xd8,0x8c,0x31,0x78,0x3,0x89,0x16,0x57,0xf3,0xfa,0x1c,0xf,0x2c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x13,0x21,0x13,0xd5,0xb7,0xd9,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x15,0x49,0x44,0x41,0x54,0x18,0x95,0x63,0x54,0x57,0xd7,0xfc,0xcf,0x80,0x7,0x30,0xe1,0x93,0x1c,0x3e,0xa,0x0,0x86,0x1b,0x1,0x86,0x56,0xb4,0xba,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char hsplitter_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x27,0x4,0x36,0x8a,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xc,0x18,0xf,0x2b,0x9,0xe0,0x80,0xd6,0xcd,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x3c,0x49,0x44,0x41,0x54,0x48,0xc7,0x63,0x60,0x20,0x6,0x2c,0x9b,0x35,0xe7,0x7f,0x76,0x7c,0xd2,0x7f,0x6c,0x7c,0x26,0x6,0x6,0x6,0x86,0xa3,0x47,0x8f,0x31,0x5c,0xbe,0x79,0x1d,0xae,0x1,0x9d,0x4f,0x5,0x30,0xea,0x86,0x51,0x37,0x8c,0xba,0x61,0xd4,0xd,0xa3,0x6e,0x18,0x75,0xc3,0xa8,0x1b,0x6,0x8b,0x1b,0x0,0x64,0xbb,0x3b,0x50,0x70,0x4,0xe8,0x8b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x27,0x4,0x36,0x8a,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x34,0x17,0x92,0x45,0xd8,0x44,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x3c,0x49,0x44,0x41,0x54,0x48,0x89,0x63,0x60,0x20,0x6,0x2c,0x58,0xb0,0xe0,0x7f,0x6a,0x6a,0xea,0x7f,0x6c,0x7c,0x26,0x6,0x6,0x6,0x86,0xa3,0x47,0x8f,0x32,0x5c,0xbb,0x76,0xd,0xae,0x1,0x9d,0x4f,0x5,0x30,0xea,0x86,0x51,0x37,0x8c,0xba,0x61,0xd4,0xd,0xa3,0x6e,0x18,0x75,0xc3,0xa8,0x1b,0x6,0x8b,0x1b,0x0,0xa,0x48,0x3b,0xf0,0x67,0x1e,0xb,0x3a,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -160,27 +155,27 @@ static const unsigned char icon_close_png[]={ static const unsigned char icon_folder_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x11,0x39,0x4f,0x6b,0x1e,0x1a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x3f,0x49,0x44,0x41,0x54,0x38,0xcb,0xc5,0x92,0x4d,0x4e,0x2,0x41,0x10,0x46,0x5f,0x55,0x37,0x3,0xe3,0x8,0x12,0x7e,0xa2,0x2e,0x3c,0xa,0x57,0xd0,0xa5,0x47,0xf0,0x22,0x7a,0xa,0xae,0xe0,0xce,0xa5,0x3b,0x4f,0xa0,0xb,0x3,0x6,0x43,0x42,0x58,0xa0,0x41,0x12,0xe2,0x68,0x10,0x86,0xe9,0x76,0x33,0x90,0xa8,0x18,0x99,0x95,0x95,0xf4,0xa2,0x53,0x5d,0xd5,0xef,0xfb,0xaa,0xe0,0xbf,0x43,0x6,0xbd,0x91,0xdf,0x94,0x8,0x4a,0x85,0xab,0xc3,0xa3,0xc6,0xf1,0x74,0x12,0x7,0x1b,0xd2,0xbe,0x5a,0x2f,0x27,0x0,0x32,0xec,0x3f,0x8f,0x5c,0xea,0xf6,0x1,0x1,0x3c,0xb0,0xcc,0x1e,0x15,0xc2,0xa8,0x78,0x21,0x22,0xb3,0xef,0xc5,0x22,0x32,0x6e,0x1c,0x54,0xdb,0x0,0xd6,0x18,0x1d,0xba,0xd4,0x35,0x1,0x3,0xc8,0xce,0x6e,0xe9,0xdc,0x7b,0x5f,0x0,0x10,0x91,0x79,0xd6,0xf8,0xb,0x35,0xf8,0x35,0x95,0x3c,0xd,0x5f,0x2e,0xe7,0x1f,0xc9,0x9,0xa0,0x51,0x39,0x3c,0x7b,0x8f,0x67,0xed,0xad,0xf5,0x8b,0xbc,0xaa,0x1a,0x1d,0x0,0xe,0x50,0x8f,0x8f,0x72,0xf8,0xe7,0xd4,0xe8,0x48,0x55,0xa5,0xf,0xd8,0x95,0xbe,0x3c,0xd,0xac,0xd5,0xae,0x8a,0xea,0x23,0xa0,0x59,0x79,0x5,0x58,0xe4,0x20,0xe8,0xaa,0x88,0xf4,0x0,0xac,0x35,0x9d,0x65,0x92,0xb6,0x32,0x33,0xb7,0x89,0x40,0x8d,0xde,0x69,0xad,0x59,0xe9,0x3,0xd8,0xc0,0xdc,0x24,0x8b,0xa4,0xb5,0xa6,0xd9,0x22,0x54,0xe5,0xd6,0xae,0x2f,0x46,0xef,0xbd,0x27,0xcc,0xb3,0x85,0xb5,0xe6,0x5e,0xc7,0x66,0xe3,0x78,0xcb,0xf3,0x73,0x66,0xb6,0x63,0xe5,0xbe,0x1a,0x19,0xe3,0xb1,0x40,0x9a,0x9d,0x3f,0xe6,0xcf,0xd2,0x58,0xf3,0x0,0x60,0xa7,0x93,0x58,0x5d,0xea,0x4e,0x45,0xa5,0x1b,0x46,0xc5,0xfa,0x2f,0xdb,0xf7,0x83,0xc0,0x18,0xbd,0x9e,0x4e,0x62,0x11,0x80,0xe9,0x24,0x36,0x19,0x52,0x21,0x87,0x8c,0xb4,0x5a,0x2f,0xa7,0x9f,0xdb,0x2b,0x65,0xf1,0xeb,0xc5,0x60,0x57,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x33,0x39,0x1,0xd2,0x43,0x4c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x36,0x49,0x44,0x41,0x54,0x38,0x8d,0xc5,0x92,0xcd,0x4a,0xc3,0x40,0x14,0x85,0xbf,0x7b,0x67,0x12,0x48,0x3,0x12,0x62,0x45,0xfa,0x30,0x7d,0x5,0x5d,0xfa,0x8,0xbe,0x88,0x3e,0x45,0x5f,0xc1,0x9d,0x4b,0x77,0x3e,0x81,0x2e,0xa4,0x15,0xa5,0x10,0xb2,0xc8,0xa2,0x9b,0x41,0x2c,0x62,0x4c,0x66,0x5c,0x34,0x8a,0x3f,0x95,0x26,0x2b,0xf,0xc,0xcc,0x9d,0x3b,0xe7,0xce,0x39,0x87,0x81,0xff,0x86,0x14,0x45,0x11,0xb6,0x35,0xe2,0x38,0xbe,0x9c,0x4c,0x26,0x47,0xce,0xb9,0x78,0x4b,0x3b,0x64,0x59,0xf6,0x6,0x20,0x65,0x59,0x56,0xde,0xfb,0x43,0x40,0x80,0x0,0x34,0xdd,0xa5,0x28,0x49,0x92,0x73,0x11,0x79,0xf9,0x49,0x16,0x91,0xd5,0x78,0x3c,0x9e,0x1,0x58,0x63,0x4c,0xe9,0xbd,0x3f,0x0,0xc,0x20,0xa3,0xd1,0xe8,0x2c,0x84,0x10,0x1,0x88,0xc8,0x6b,0x37,0xf8,0x9b,0xea,0x10,0xc2,0xa7,0x2a,0xa9,0xaa,0xea,0xa2,0xae,0xeb,0x63,0x40,0xd3,0x34,0x3d,0x5d,0xaf,0xd7,0xb3,0xde,0xfe,0x45,0x9e,0xd4,0x18,0x53,0x0,0x1e,0xd0,0x10,0x42,0xda,0x97,0xc,0x78,0x55,0xad,0x54,0x44,0x96,0x80,0xfd,0xf0,0x37,0x64,0x80,0x31,0x66,0xa1,0xaa,0xfa,0x8,0x68,0x77,0xb8,0x7,0xd4,0x83,0x6,0x88,0xc8,0x3,0x80,0x31,0x66,0xde,0x34,0xcd,0x94,0x4d,0x98,0x7d,0x10,0xab,0xea,0xad,0xe6,0x79,0xbe,0x4,0x88,0xa2,0xe8,0xba,0xae,0xeb,0xe9,0x17,0x35,0x3b,0xa1,0xaa,0x37,0xf6,0x4b,0x71,0x7,0x24,0x7d,0xc9,0x0,0x79,0x9e,0xcf,0x2d,0x80,0x88,0x3c,0xf,0x79,0x99,0x4d,0xd8,0x1e,0xba,0xf4,0x55,0x75,0xd5,0xed,0xdb,0x6e,0xed,0x42,0x63,0xad,0xbd,0x7,0xb0,0xce,0x39,0x6d,0xdb,0xf6,0x44,0x55,0x17,0x49,0x92,0xec,0xff,0xf1,0xfb,0x7e,0x29,0x50,0xd5,0x2b,0xe7,0x9c,0x8,0x80,0x73,0xce,0x74,0x92,0xa2,0x1,0x36,0xda,0x2c,0xcb,0xda,0x77,0xe3,0x5,0x64,0xf1,0xba,0x53,0xe9,0x44,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_play_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x3,0x35,0x2,0xc,0xc,0xc2,0xf6,0x0,0x0,0x0,0xb3,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0xa0,0x6,0xf8,0xf0,0xf6,0x33,0x33,0x12,0x9b,0x89,0x2c,0x43,0x1e,0xde,0x7e,0xfe,0xff,0xd9,0xc3,0xd7,0xa7,0xde,0xbd,0xfa,0x68,0x46,0x8a,0x41,0x28,0x8a,0x7e,0xff,0xfa,0x63,0xfc,0xf9,0xe3,0xb7,0x93,0xcf,0x1e,0xbe,0x3e,0xf9,0xef,0xef,0x3f,0x13,0x62,0xc,0x62,0xc2,0xc6,0xff,0xfd,0xeb,0x8f,0x9,0xb1,0x6,0x31,0xe1,0x33,0x98,0x18,0x83,0x98,0x88,0xf1,0x22,0x3e,0x83,0x18,0x91,0x3,0x91,0x88,0x30,0xfb,0xc7,0xc0,0xc0,0xc0,0xc4,0xca,0xc6,0x72,0x82,0x9d,0x93,0xad,0x8a,0x99,0x99,0xe9,0x10,0x13,0xa5,0x49,0x80,0x85,0x48,0x75,0x30,0x9b,0xcf,0x70,0x70,0xb2,0xe5,0xa,0x89,0xf1,0x9f,0xfa,0xf0,0xf6,0x33,0x93,0x80,0x30,0xef,0x3f,0x26,0x22,0x34,0x32,0xb0,0xb2,0xb1,0x9c,0xe1,0xe5,0xe7,0x32,0x97,0x92,0x17,0x35,0x67,0x62,0x66,0x3a,0xc3,0xc0,0xc0,0xc0,0x20,0x20,0xcc,0xfb,0xf,0x5f,0x20,0x12,0xd4,0x88,0x2b,0x16,0x88,0xd6,0x48,0xb5,0xa4,0x4c,0xbd,0xcc,0x44,0x2e,0x0,0x0,0x8c,0xcd,0x82,0xb2,0x7b,0xf9,0xcd,0xd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x33,0x2d,0x1b,0x8,0x97,0x31,0x0,0x0,0x0,0xb4,0x49,0x44,0x41,0x54,0x38,0x8d,0xad,0x93,0xbd,0xe,0xc2,0x20,0x14,0x46,0x3f,0xb9,0x12,0x16,0x6,0x12,0x36,0x5e,0xc3,0xc6,0x3e,0x95,0x2f,0xe0,0xe3,0x39,0xd9,0xa6,0x2f,0xc1,0xc2,0x46,0xc2,0xc0,0xd6,0x94,0xba,0xb4,0x49,0xad,0x69,0x40,0xf4,0x4c,0x24,0x7c,0xf7,0x70,0xf9,0x3,0xfe,0x41,0x8,0x81,0x36,0x63,0x56,0x25,0xb1,0xd6,0xce,0xce,0xb9,0xde,0x7b,0x7f,0xfd,0x46,0xf4,0x16,0x1a,0xc7,0xf1,0x12,0x63,0xec,0x9c,0x73,0xdd,0x34,0x4d,0x4d,0x89,0x68,0x3f,0xc9,0x16,0x51,0x53,0x2a,0x3a,0xb2,0x17,0x8b,0x72,0xfb,0xcc,0x8a,0x4e,0x6b,0xd2,0x5a,0x3b,0x67,0x64,0x0,0x90,0x0,0x30,0xce,0xf9,0x53,0x8,0x71,0x27,0xa2,0x47,0xdd,0x95,0x6d,0x38,0x17,0xe6,0xd6,0x95,0x7,0x21,0xc4,0x4d,0x6b,0xdd,0x87,0x10,0x98,0x52,0x2a,0xe5,0x3a,0x48,0x0,0xc0,0x39,0x1f,0xa4,0x94,0xad,0x31,0xa6,0x25,0xa2,0x1,0x0,0x94,0x52,0x9,0x38,0x3e,0xc4,0x6c,0xe1,0xca,0x5e,0x50,0x5c,0xf8,0x41,0xed,0x53,0xc6,0x12,0xfe,0xfd,0x33,0xd5,0xf2,0x2,0x84,0xae,0x82,0xae,0xa4,0x17,0x47,0xe1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char icon_stop_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x3,0x35,0x39,0xbd,0x7,0x2b,0xd2,0x0,0x0,0x0,0x34,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0xa0,0x6,0xf8,0xf0,0xf6,0x33,0x33,0xb9,0x7a,0x18,0x61,0x2,0xf,0x6f,0x3f,0xff,0x4f,0x8a,0x1,0xf2,0xaa,0x92,0x8c,0xc,0xc,0xc,0xc,0x4c,0x94,0xba,0x7e,0xd4,0x80,0x51,0x3,0x6,0x87,0x1,0x14,0x67,0x26,0x8a,0x1,0x0,0x2a,0xbb,0xf,0x64,0x53,0x81,0x8c,0xd3,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x33,0x24,0x62,0xd4,0x2f,0x95,0x0,0x0,0x0,0x39,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0xa0,0x6,0xf8,0xf0,0xe1,0x3,0x33,0xb9,0x7a,0x18,0x61,0x2,0xf,0x1f,0x3e,0xfc,0x4f,0x8a,0x1,0xf2,0xf2,0xf2,0x8c,0xc,0xc,0xc,0xc,0x4c,0xa4,0xda,0x8c,0xe,0x46,0xd,0x18,0x35,0x60,0x70,0x18,0xc0,0xc0,0xc0,0x40,0x59,0x66,0xa2,0x18,0x0,0x0,0x2a,0xc7,0xf,0x64,0xd5,0xe,0x11,0x85,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char line_edit_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x3e,0x0,0x34,0x0,0x44,0xb5,0x81,0x75,0x5d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x15,0x14,0xdf,0xfe,0x44,0x4c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc0,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xd0,0x2d,0x8e,0x2,0x41,0x10,0x86,0xe1,0xb7,0x7f,0x66,0x4,0x20,0xd6,0xb0,0x21,0x60,0x20,0x70,0x1,0x34,0x8a,0x5b,0xac,0x26,0x5c,0x62,0x4f,0xc0,0x11,0x30,0x4,0xcd,0x29,0x40,0xa1,0xb9,0x0,0x9,0x6a,0x12,0x2,0x6,0x1,0x23,0x9a,0xa9,0x2e,0xcc,0x1e,0x60,0x3a,0xeb,0x8,0xaf,0xff,0x9e,0x4a,0xca,0xa8,0x2a,0x83,0xde,0x68,0x5,0xfc,0x0,0x4d,0xea,0xf5,0x0,0x36,0xa7,0xe2,0x38,0x37,0xfd,0xee,0x70,0xeb,0xbc,0x9f,0x7a,0xef,0x48,0xa9,0xaa,0x4,0xa9,0xaa,0x9d,0xe9,0x77,0x87,0xd2,0x68,0x36,0xac,0x73,0xe,0x6b,0xea,0x21,0x51,0x5,0x11,0xa1,0x7c,0x94,0xd1,0x3,0x36,0xf3,0x79,0xd2,0x75,0x6b,0x1c,0xd6,0x3b,0xa0,0xb4,0x96,0x7f,0xf6,0x1,0xde,0x6,0x28,0xa2,0x4a,0xf2,0xf0,0x6f,0x53,0x58,0x60,0x19,0x42,0x20,0x5,0x89,0x2a,0x84,0x10,0x0,0x96,0x46,0x55,0x99,0x8c,0xa7,0x8b,0xeb,0xed,0x3c,0x7b,0x86,0xe7,0x77,0x1d,0x20,0xcb,0xb3,0x4b,0xfb,0xab,0xb3,0xde,0x1f,0x76,0xbf,0x46,0x55,0x41,0xc9,0x81,0x56,0xc2,0x4f,0x22,0x70,0xc7,0x10,0x5e,0xb5,0x47,0x48,0x5e,0x61,0x62,0xef,0xf5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x27,0x0,0x27,0x0,0x27,0x12,0xaa,0xad,0x65,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x16,0x1e,0x2f,0x66,0x6e,0x58,0x30,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0x3b,0x4e,0x3,0x41,0x10,0x84,0xe1,0x6f,0x4c,0x4b,0x1e,0x56,0x1b,0x10,0xef,0x8,0x4e,0xc0,0xe3,0x6c,0x9c,0x84,0xb3,0x19,0x3b,0x26,0x41,0xeb,0x98,0x0,0xd9,0x63,0x69,0x90,0x9,0xd8,0x78,0x17,0xc9,0x9,0x1,0x15,0xb6,0xba,0xfe,0xee,0xa0,0x2a,0xa1,0xc3,0xd,0x7a,0x5c,0x21,0x99,0xd7,0x19,0x5f,0xf8,0xc4,0x47,0x4c,0xe6,0x47,0xdc,0x22,0xff,0x12,0x50,0xf1,0x8e,0xd7,0x98,0x2e,0xdf,0x3d,0xdc,0x3f,0xbd,0x94,0xa1,0x74,0x11,0x31,0xeb,0x6e,0xad,0x19,0xf7,0xe3,0x61,0xbb,0xdb,0x3c,0xe3,0x2d,0x10,0x58,0x97,0xa1,0x74,0xb5,0x56,0xb5,0xd6,0x59,0x40,0xce,0x59,0x19,0x4a,0xb7,0xdd,0x6d,0xd6,0x88,0xd5,0x34,0x4f,0x11,0xb1,0x68,0x86,0x5a,0xab,0xe9,0xcb,0x4,0xab,0xf9,0xf5,0x65,0xfd,0x3,0xfe,0x12,0xe0,0xdc,0x5a,0x93,0x73,0x5e,0x34,0xe4,0x9c,0xb5,0xd6,0xf8,0x89,0xb4,0x40,0xc3,0x69,0xdc,0x8f,0xc7,0x32,0x94,0xeb,0xbe,0xef,0x67,0x1,0x53,0x94,0x8f,0x38,0xa1,0x25,0xc,0x2e,0x28,0x53,0x72,0x61,0x9d,0xbf,0x1,0x2c,0xf1,0x42,0x3f,0xf1,0x88,0x6f,0x8a,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char line_edit_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x3e,0x0,0x34,0x0,0x44,0xb5,0x81,0x75,0x5d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x1d,0x13,0x89,0x43,0x5b,0xe7,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc0,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xce,0x2f,0x4e,0x3,0x41,0x14,0xc7,0xf1,0xef,0x9b,0x37,0xb3,0x5b,0x1c,0x8,0x12,0xb2,0xaa,0xc9,0x1e,0xa0,0xad,0x45,0x91,0xe0,0xb8,0x8,0x47,0xe0,0xc,0x48,0x24,0xc7,0x58,0x83,0x23,0x41,0xd5,0xb6,0x17,0x68,0x52,0xd5,0x34,0x59,0x1,0xaa,0x90,0xd9,0xf9,0x83,0xe1,0x0,0x33,0xc1,0x11,0xbe,0xfe,0xf7,0x79,0x4f,0x0,0xe6,0x5d,0xff,0x0,0xdc,0x2,0x33,0xca,0xfa,0x2,0x5e,0xf7,0x87,0xdd,0xa3,0xcc,0xbb,0xfe,0x49,0xad,0x5d,0x59,0xab,0xd4,0x14,0x42,0x24,0x86,0xb0,0xb1,0xc0,0xa2,0x6d,0x1b,0x54,0x15,0x23,0x65,0x48,0xca,0x11,0xd5,0xc8,0x29,0x84,0x85,0x5,0x8c,0xb3,0x4d,0xd5,0x75,0x23,0x8a,0xb1,0xa,0x9c,0x8c,0xe1,0x97,0xfd,0x3,0x7f,0x6,0x18,0x53,0x8e,0xd5,0xc3,0x9f,0xcd,0x68,0x80,0xc1,0x7b,0x4f,0xd,0x92,0x72,0xc4,0x7b,0xf,0x30,0x8,0xc0,0xf5,0xf2,0xe6,0x7e,0xfc,0x38,0xde,0x4d,0x7e,0xba,0x28,0x1,0x5c,0xe3,0xde,0x2f,0xcf,0xaf,0x5e,0xd6,0xdb,0xb7,0x67,0x1,0xc8,0x29,0x3b,0xe0,0xc,0x90,0xc2,0x27,0x32,0xf0,0x29,0x46,0xa6,0x6f,0xea,0x47,0x3d,0x8f,0x5e,0xa4,0x39,0x87,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x27,0x0,0x27,0x0,0x27,0x12,0xaa,0xad,0x65,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x16,0x1e,0x28,0xf8,0xa,0xcd,0x93,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xb8,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x93,0x31,0xa,0xc2,0x50,0x10,0x44,0xdf,0x97,0x8d,0x59,0x24,0x8d,0xa4,0xcb,0x7,0x4f,0xa0,0x78,0x22,0x4f,0xe7,0x89,0x42,0x72,0x2,0x21,0x29,0x4,0x5b,0x59,0x75,0x31,0x16,0x89,0xa5,0x49,0xc0,0xc6,0xc2,0xe9,0x67,0x66,0x67,0x99,0x9,0x40,0xa,0xac,0x0,0x5,0x16,0xcc,0xc3,0x13,0x30,0xe0,0x2a,0x3,0x79,0x3,0xe4,0x40,0x2,0x84,0x9,0x72,0x7,0x3c,0x80,0xb,0x70,0x92,0xc1,0x39,0xdf,0x6d,0xf7,0x87,0x58,0xc4,0xa5,0x88,0x8c,0xa,0xb8,0x7b,0xd7,0xb4,0xcd,0xbd,0xaa,0xcb,0x23,0x70,0x96,0xe1,0xec,0x24,0x16,0x31,0x35,0x33,0xcc,0x6c,0xd4,0x5e,0x55,0x43,0x2c,0x62,0x5a,0xd5,0x65,0x2,0x2c,0xde,0x99,0x83,0x88,0x4c,0x92,0x1,0xcc,0xc,0x11,0x81,0x21,0xea,0xdc,0xa7,0x7d,0xc4,0x5f,0xe0,0x97,0x4,0x3a,0x77,0x47,0x55,0x27,0x9,0xaa,0x8a,0xbb,0x43,0x5f,0x69,0x84,0x7e,0x18,0x8f,0xa6,0x6d,0x6e,0xb1,0x88,0xcb,0x2c,0xcb,0x66,0x55,0x99,0x7e,0xf,0xcf,0x0,0xac,0xf9,0x62,0x4c,0x81,0x2f,0xe7,0xfc,0x2,0xba,0x32,0x42,0x24,0xee,0x6e,0x22,0x60,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -195,12 +190,12 @@ static const unsigned char logo_png[]={ static const unsigned char option_arrow_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x89,0x0,0x76,0x0,0x95,0x95,0xac,0x1a,0xb5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x35,0x3,0xc9,0xa9,0xe5,0x29,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc7,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0x18,0x9e,0xc0,0xdb,0x3e,0x88,0x81,0x87,0x41,0x58,0x82,0x9f,0x47,0xf0,0x3f,0xf,0x83,0xb0,0x84,0xb7,0x7d,0x10,0x69,0x6,0xf0,0x30,0x8,0xb3,0x28,0xcb,0xaa,0xfd,0x5f,0x39,0x6b,0xf3,0x7f,0x65,0x59,0xb5,0xff,0x3c,0xc,0xc2,0x2c,0x24,0x19,0xa0,0x2c,0xab,0xf6,0x7f,0xf9,0xf4,0xd,0xff,0x4f,0x1f,0xba,0xf8,0x7f,0xf9,0xf4,0xd,0xff,0x95,0x65,0xd5,0xfe,0xe3,0x52,0xcb,0x88,0x4d,0x70,0x5e,0xef,0x8a,0xff,0xba,0xa6,0x9a,0x70,0xfe,0xe5,0xd3,0xd7,0x19,0x92,0x8a,0x23,0x18,0x89,0x36,0x80,0x87,0x41,0x98,0x7,0x5d,0xec,0xb,0xc3,0xdb,0x2f,0x44,0x7b,0x41,0x52,0x54,0xe6,0x3f,0x3,0x3,0x3,0x1c,0x43,0xf9,0xc4,0x7b,0x61,0x4e,0xf7,0xb2,0xff,0xfa,0xe6,0xda,0x70,0xfe,0xc5,0x93,0x57,0x19,0x52,0x4a,0xa3,0x18,0x49,0x89,0x5,0x89,0xd,0x8b,0x76,0xfe,0x3f,0x7d,0xe8,0xe2,0xff,0xd,0x8b,0x76,0xfe,0xe7,0x61,0x10,0x96,0xc0,0xa5,0x96,0x9,0x9b,0xe0,0x4f,0x86,0x4f,0x3c,0xaa,0xac,0x6e,0x1c,0xcf,0x1f,0xbf,0x64,0x50,0x65,0x75,0xe3,0xf8,0xc9,0xf0,0x89,0x87,0x61,0x14,0xe0,0x4,0x0,0x59,0x95,0x3d,0x5c,0xd0,0x53,0x81,0xde,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x1c,0x2e,0x4,0xf2,0xb6,0x87,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x61,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0xbc,0x7b,0xf7,0x2e,0x3,0x25,0x80,0x89,0x22,0xdd,0xb4,0x36,0x40,0x82,0x81,0x81,0xe1,0x3f,0x94,0x26,0xd9,0x0,0x16,0x6,0x6,0x86,0xe7,0x50,0xf6,0x73,0x28,0x9f,0x24,0x3,0x7e,0x13,0xe0,0x13,0x34,0x80,0x68,0x80,0xcb,0x69,0xbc,0x94,0x1a,0xf0,0x19,0x8b,0x18,0x23,0x36,0x85,0x34,0x8b,0x46,0x49,0x2,0x7c,0x82,0x6,0xf0,0x30,0x30,0x30,0x70,0x40,0xd9,0x1c,0x50,0x3e,0x56,0x80,0x2b,0xc,0xee,0x40,0x69,0x46,0x34,0x3e,0xd1,0x2e,0x20,0x1a,0xc,0xbc,0x1,0x0,0x1e,0x2d,0xa,0xcc,0x68,0x85,0xc9,0x5b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char option_button_disabled_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x89,0x0,0x76,0x0,0x95,0x95,0xac,0x1a,0xb5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x32,0xf,0x8f,0x5e,0x3f,0xc5,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x9,0x49,0x44,0x41,0x54,0x48,0xc7,0xbd,0x95,0xb1,0x6b,0x14,0x51,0x10,0xc6,0x7f,0xb3,0x2e,0x77,0xb7,0xa7,0xa8,0x88,0x84,0x90,0x2a,0x90,0xbf,0x40,0xb4,0x53,0xc4,0xc2,0xc2,0x26,0x29,0x52,0x58,0xa,0x36,0x16,0xfe,0x49,0x96,0x76,0x76,0x12,0x1b,0x2b,0x2b,0xb,0x11,0x82,0x8d,0x60,0x23,0x28,0x21,0xe6,0xc8,0x9d,0x60,0x23,0x49,0xf6,0xf6,0xbd,0x19,0x8b,0x7d,0xbb,0xf7,0xf6,0x6e,0xf,0xf6,0x2e,0xe0,0xc0,0xb2,0x8f,0xb7,0xf3,0x66,0xbe,0xf9,0xe6,0x9b,0xb7,0x2,0xb0,0xbd,0xb5,0xf3,0x0,0xd8,0x5,0xee,0xd2,0xc1,0xf2,0x22,0xe7,0x92,0x76,0x8,0xbc,0x1b,0x4d,0x8e,0x3f,0xca,0xf6,0xd6,0xce,0xd3,0x7e,0x6f,0xf0,0x22,0xeb,0xf,0xe9,0xf,0xfa,0x9d,0x4e,0x1f,0x9d,0xfc,0xe4,0xf9,0xfe,0xcb,0xb5,0xb3,0x8f,0x26,0xbf,0x38,0xfc,0xfa,0x89,0xc9,0x9f,0xd3,0x57,0x29,0xb0,0x77,0xfd,0xda,0xd,0xb2,0xc1,0x10,0x11,0xe9,0x1c,0x44,0xbd,0xe7,0xc7,0xf1,0xf7,0xb5,0x0,0x64,0xd9,0x55,0xee,0xdf,0x79,0xc4,0xdb,0xf,0x6f,0xf6,0x52,0x60,0x33,0x1b,0xc,0x1,0x30,0xb3,0xce,0x41,0xa,0x5f,0xac,0xe4,0x1f,0xdb,0xd9,0xd9,0x5f,0xf2,0x69,0xe,0xb0,0x99,0xb6,0x25,0x36,0x40,0x30,0x8c,0x92,0x91,0x6a,0x1d,0xf3,0xe3,0xbc,0xbb,0x94,0x8,0xbc,0x2b,0x0,0x48,0x1,0xbc,0x6a,0x19,0x5c,0x4a,0x30,0x22,0x82,0x19,0x20,0x1a,0x98,0x11,0x10,0x43,0x23,0xa0,0xae,0x70,0x78,0x2d,0xbf,0x27,0x32,0x43,0xae,0x61,0x59,0xed,0x69,0x54,0x5b,0x12,0x72,0xd4,0x55,0x56,0x0,0xd4,0x7c,0xb9,0xaf,0x15,0x88,0xe0,0x13,0xde,0x12,0x1d,0xa8,0x2b,0x50,0x87,0x9a,0x5f,0x48,0x52,0x6b,0xa4,0x6d,0xf,0xc0,0x57,0x48,0x6c,0x6,0xc0,0x54,0x67,0xf1,0xe3,0x83,0xd2,0x4,0x12,0x9b,0x73,0xe,0xf5,0xda,0xe6,0x4e,0x9b,0x32,0xe2,0xf6,0x5,0xdc,0x11,0x3,0x81,0x4a,0xc4,0xc0,0xa4,0xd6,0x0,0x32,0x43,0xb0,0xa8,0x81,0x2,0xe7,0xb5,0x99,0x38,0xa1,0xee,0x41,0x2b,0x98,0x64,0x81,0x8f,0xa0,0x81,0xba,0x5,0x82,0x89,0x22,0x6,0x2a,0x82,0x58,0xd0,0x0,0xe5,0x5a,0xa5,0xc9,0x80,0xa9,0x7,0xc,0x1f,0xb1,0x97,0x98,0x34,0xf6,0x92,0x88,0x3,0x35,0x23,0x9,0x88,0x34,0x14,0x17,0xa6,0x40,0x31,0xb,0xea,0xf,0xc,0x60,0x5a,0x4f,0x1,0x84,0xb5,0x35,0xa7,0xc0,0x99,0x6b,0x52,0x6b,0x42,0x7c,0xaa,0x6a,0x79,0xcd,0x44,0xf5,0x5d,0xa9,0xbd,0xca,0x16,0xf8,0x19,0x6f,0x5d,0x27,0xdb,0x7b,0x87,0x7a,0xbf,0x9c,0xef,0x65,0x82,0x98,0xbb,0xeb,0x52,0x60,0xec,0xd5,0x6f,0x88,0xac,0x90,0x1d,0x70,0xae,0xc0,0xd7,0xe3,0xd2,0xe2,0xb0,0x2c,0x96,0x55,0x5,0x14,0x0,0xe3,0x4,0x38,0xc8,0x8b,0xb,0xcc,0xac,0xf3,0x53,0xb6,0xc0,0x7,0x82,0x57,0x7f,0x9c,0x9b,0x72,0x32,0x3e,0x2,0x38,0x10,0x80,0x87,0xf7,0x1e,0x3f,0x3b,0xfd,0x3d,0x7a,0x92,0x4f,0x2f,0x36,0xfe,0xc7,0xdf,0xb0,0x97,0xf6,0xc6,0xb7,0x6e,0xde,0x7e,0xff,0xe5,0xdb,0xe7,0xd7,0xe5,0x1d,0xa3,0x96,0x2,0xd9,0xfc,0xa0,0x2c,0xb3,0x75,0xff,0x1,0x73,0x33,0x78,0x9e,0x5c,0x49,0xdc,0x3f,0x60,0x6c,0x40,0xa3,0x6f,0xcc,0xee,0xbb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x5a,0x0,0x5a,0x0,0x5a,0x61,0x75,0x7f,0x99,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x16,0x18,0x29,0x61,0xeb,0x3d,0xe6,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc9,0x49,0x44,0x41,0x54,0x48,0x89,0xed,0x95,0xb1,0xaa,0xc2,0x40,0x10,0x45,0xcf,0x86,0x11,0x46,0x4c,0x61,0xb1,0x55,0xb6,0x4f,0xa5,0xbc,0xff,0xff,0x87,0xd7,0x88,0x56,0xf6,0xb1,0x4a,0x61,0xa1,0x30,0xe0,0x10,0x2d,0x76,0x53,0x3f,0xf1,0x11,0xd3,0x64,0x60,0x58,0xd8,0x62,0xee,0xb9,0x53,0xdc,0x9,0x80,0x0,0xab,0xf2,0x86,0xd2,0x53,0xd6,0xb3,0xb4,0x3,0x8f,0x51,0x7c,0xb,0x6c,0x80,0xea,0x4b,0x0,0x3,0x70,0x7,0xae,0x42,0x76,0xbe,0xd9,0xef,0x7e,0xb6,0xa9,0x49,0xad,0x88,0x4c,0xaa,0xee,0xee,0x74,0x97,0xee,0x7c,0x3c,0x1d,0x0,0x6e,0x42,0x76,0x5d,0xa5,0x26,0xb5,0x66,0x86,0x99,0xfd,0x39,0x24,0xc6,0x48,0xdf,0xf7,0x1f,0x1,0xa8,0x2a,0xa9,0x49,0xed,0xf1,0x74,0xf8,0x5,0xaa,0xaa,0xfc,0x7,0x11,0x79,0x4b,0xfc,0xbf,0x65,0x66,0x94,0x2d,0x7,0xc8,0xee,0x67,0xad,0x5,0x60,0x1,0x58,0x0,0x46,0x80,0xa7,0xbb,0xa3,0xaa,0x93,0xb,0xaa,0x2a,0xee,0xe,0x39,0x92,0x11,0x72,0x2e,0xf,0xdd,0xa5,0x3b,0xa7,0x26,0xb5,0x75,0x5d,0xbf,0x35,0x28,0xc6,0xf8,0x11,0xc0,0x18,0xc5,0xa3,0x6e,0x0,0xd6,0xcc,0x78,0x8c,0x2,0x33,0x9f,0xe3,0x17,0x68,0xff,0x45,0x43,0x59,0xe8,0x6b,0xa8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -210,27 +205,27 @@ static const unsigned char option_button_focus_png[]={ static const unsigned char option_button_hover_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x89,0x0,0x76,0x0,0x95,0x95,0xac,0x1a,0xb5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x30,0x2f,0x86,0x6,0x7d,0x8f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x3,0x49,0x44,0x41,0x54,0x48,0xc7,0xbd,0x95,0x31,0x68,0x14,0x41,0x14,0x86,0xbf,0x99,0xbb,0xa8,0x18,0x4b,0x89,0x78,0xc1,0xe0,0xa1,0xad,0x55,0x10,0xb,0x8b,0x54,0xa9,0xac,0xc4,0xc2,0xde,0xee,0x5a,0x41,0x4b,0xc5,0xc6,0x42,0x6c,0xc4,0xe2,0xb0,0xd1,0xd2,0x52,0x4,0xbb,0x58,0x59,0xa7,0xb1,0x12,0x11,0x63,0x38,0xf1,0x34,0x41,0x50,0x48,0x24,0xb9,0x9d,0x37,0xef,0x59,0xec,0xec,0xde,0xde,0x65,0x23,0x97,0x13,0x6e,0x61,0x60,0xf9,0xe7,0x9f,0xf9,0xff,0xf7,0xcf,0x1b,0xc6,0x99,0x19,0xed,0xc5,0x8b,0xd7,0x81,0xe,0xb0,0xca,0x6c,0xbe,0x35,0xa0,0xbb,0xd9,0xff,0xfc,0xca,0x9d,0x6f,0x5d,0xb8,0xd3,0x5a,0x38,0xf7,0x68,0xf9,0xd2,0x15,0x5a,0xb,0x8b,0x13,0xad,0x7e,0xf6,0xf2,0x9,0xf7,0x6e,0x3f,0x9c,0x5a,0xfd,0xc7,0x56,0x9f,0x37,0x6b,0xaf,0xe9,0x6f,0x7f,0xbd,0xdb,0x4,0x3a,0x57,0x97,0x57,0xd8,0x1b,0xec,0xf1,0xe9,0xcb,0xc7,0x89,0x37,0xd1,0x18,0xd9,0xd8,0xdc,0x98,0xca,0xc0,0xfc,0xfc,0x49,0x6e,0x5c,0xbb,0xc9,0xd3,0x17,0x8f,0x3b,0x4d,0xa0,0xfd,0x7b,0xe7,0x17,0x12,0xe4,0x48,0x9b,0x84,0x28,0x98,0xda,0x54,0x6,0x76,0x77,0xfe,0xb0,0x3f,0xc8,0x0,0xda,0x1e,0x38,0xb2,0x38,0x80,0x44,0xf9,0xaf,0x26,0x90,0x2c,0x0,0xd0,0x4,0x50,0x8d,0xe0,0xd2,0x8c,0x41,0x51,0x97,0xfb,0x7,0x26,0x99,0x10,0x55,0x1,0xf0,0x15,0x9e,0xa6,0xdf,0x2,0xab,0x86,0xe4,0x61,0x44,0xa7,0x34,0x10,0x2d,0x82,0xb9,0x7c,0xb5,0xaf,0xd8,0xac,0x4b,0xd8,0x8a,0x1e,0x10,0xd4,0xe4,0x80,0x48,0xd9,0x23,0x75,0x18,0x40,0x2c,0x34,0x6c,0x68,0x40,0xa2,0x2,0xe,0x8f,0x41,0x74,0x89,0x6c,0xb9,0xa9,0x6a,0x35,0x15,0x4c,0x44,0xd0,0xa8,0x39,0xa6,0x89,0xe7,0x2b,0xbc,0x84,0xe1,0x2d,0x55,0x3f,0x2c,0x5d,0xa3,0x1b,0x35,0xa0,0x2a,0x80,0x2b,0xe3,0x2b,0xaa,0x2c,0x96,0x88,0xab,0xc1,0x62,0x20,0x84,0x38,0x82,0x45,0xa3,0x3c,0x83,0x52,0x2e,0xa6,0x39,0xc6,0xd2,0x4d,0xc4,0x94,0x80,0xe1,0x2d,0x7,0xd4,0x81,0xb7,0x5c,0xb1,0x34,0x54,0x83,0x49,0x88,0x79,0xef,0x54,0x79,0x76,0x90,0x37,0xd4,0x74,0xa8,0x59,0x11,0x8,0x9a,0x9a,0xa9,0x59,0xdc,0x69,0x43,0xf3,0x74,0xcd,0xa3,0x68,0x59,0x1,0x80,0xd5,0x60,0x41,0x84,0xa0,0x61,0x94,0x87,0x27,0x8e,0xf1,0x74,0x24,0xd4,0x34,0xaf,0x39,0x77,0xec,0x8,0xa,0xa6,0x52,0x31,0x7d,0x28,0x26,0x22,0xa8,0xc4,0xfa,0xbc,0x6b,0xba,0xbd,0x3c,0x8,0x57,0xf9,0x4f,0x6,0x7a,0x59,0x18,0x2c,0x35,0x1a,0x73,0x87,0x76,0x7c,0x1d,0x26,0x92,0x95,0xd7,0x70,0x9a,0x2f,0xc4,0xc,0xa0,0xe7,0x81,0xee,0xb7,0xed,0x1e,0x41,0x32,0x8c,0x38,0xd1,0x0,0x8,0x41,0x50,0xa6,0x1b,0x99,0xc,0x78,0xff,0x61,0x1d,0xa0,0xeb,0xcc,0x8c,0x95,0xcb,0xab,0xf7,0xb7,0x7e,0x7e,0xbf,0x35,0xc8,0xf6,0x97,0x66,0xf1,0x14,0x1e,0x3f,0x76,0xa2,0x77,0xe6,0xf4,0xd9,0xe7,0xef,0xd6,0xdf,0x3e,0x70,0x66,0x86,0x99,0xcd,0x1,0xa7,0x80,0xc6,0x8c,0x9e,0xe3,0x8,0xec,0x7a,0xef,0xc3,0x5f,0x3e,0xcd,0x47,0x5a,0x1d,0xdb,0x7d,0x47,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x49,0x0,0x4e,0x38,0x4f,0x8,0xff,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x16,0x17,0x13,0x20,0x7f,0xf8,0x9b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xd8,0x49,0x44,0x41,0x54,0x48,0x89,0xed,0xd5,0xb1,0x4e,0x2,0x51,0x10,0x85,0xe1,0xef,0xe2,0x46,0x8c,0x31,0x91,0x64,0xab,0xdd,0xe5,0xfa,0x4,0xa8,0x2f,0x26,0xbe,0x8c,0xbe,0x18,0x42,0x4d,0x73,0x59,0x68,0x97,0xc4,0x42,0x12,0xc,0x16,0x40,0x67,0x14,0x49,0x56,0x1a,0x4e,0x39,0x99,0x9c,0xf9,0x27,0x93,0x9c,0x9,0xb8,0x46,0xf,0x37,0xb8,0x40,0xd0,0xae,0x36,0xf8,0xc4,0x3b,0x9a,0x6c,0x37,0xfc,0x1,0x11,0x57,0xff,0x4,0xf0,0x81,0x84,0xb7,0xcc,0x76,0xf3,0xbb,0xfb,0xc1,0xe3,0xa0,0x2a,0xab,0xa7,0xd8,0x8f,0xad,0x2,0xa4,0x59,0xda,0xd4,0xf3,0xfa,0x75,0x3c,0x19,0x5,0x4c,0x33,0x64,0xe8,0x56,0x65,0x35,0xcc,0xf3,0xdc,0x7c,0xb1,0xf8,0xd5,0xa4,0x2c,0x8a,0x83,0xfa,0xbe,0x53,0x9e,0xe7,0x1,0xc3,0xf1,0x64,0xf4,0x8c,0xac,0xb3,0xab,0x87,0xd8,0x8f,0x9a,0x66,0x79,0x94,0xe9,0x5f,0xd4,0x34,0x4b,0xb1,0x1f,0xd9,0x9d,0xba,0xf3,0x73,0x7b,0xfb,0x3a,0x3,0x9c,0x1,0xce,0x0,0x7b,0x80,0x4d,0x9a,0x25,0xbd,0xde,0x6d,0xeb,0x3,0xbb,0xdd,0x4b,0x69,0x96,0xd8,0x46,0xb2,0xc,0x6b,0xac,0xea,0x79,0xfd,0x82,0x83,0xa3,0xb8,0x2c,0x8a,0xa3,0x0,0xf6,0x51,0x8c,0x15,0xd6,0x1,0xa5,0x13,0x3e,0xa3,0xe0,0xc4,0xef,0xf8,0xb,0x70,0x57,0x43,0xed,0x5d,0x76,0xf,0x70,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char option_button_normal_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x89,0x0,0x76,0x0,0x95,0x95,0xac,0x1a,0xb5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x2d,0xd,0xac,0xa,0x50,0x77,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xfb,0x49,0x44,0x41,0x54,0x48,0xc7,0xbd,0x95,0xbd,0x6b,0x14,0x51,0x14,0xc5,0x7f,0x77,0x76,0x4c,0x11,0x2d,0xfc,0x8a,0xdf,0x6,0x52,0xd8,0xc4,0x42,0x48,0xa1,0xad,0x8d,0x8d,0x8d,0xf8,0x27,0x68,0xb7,0x9d,0x8d,0x82,0x95,0xd8,0xfa,0xf,0x2c,0x58,0x28,0x76,0x76,0x29,0x45,0x4,0x4b,0xb,0x1b,0x2b,0x9,0x4,0x89,0xb0,0x44,0xa2,0x46,0xe2,0x7,0x59,0x48,0xe6,0xdd,0xfb,0xae,0xc5,0xcc,0x6c,0x66,0x77,0x26,0xeb,0x66,0x85,0x1d,0x78,0x30,0x73,0xde,0x79,0xf7,0x9e,0x7b,0xee,0x1d,0x9e,0xb8,0x3b,0xe7,0x4e,0x5d,0xbc,0xd,0xb4,0x81,0x1b,0x4c,0xe7,0x79,0x3,0x74,0x36,0x36,0xd7,0x97,0xe5,0xec,0xdc,0x85,0xfb,0x73,0xc7,0x4e,0x3f,0xb9,0x7c,0xe9,0xa,0x67,0x4e,0x9c,0x1f,0xeb,0xf4,0xcb,0x57,0xcf,0xb9,0x77,0xe7,0xe1,0xc4,0xd9,0x37,0xbe,0x7f,0xe1,0xed,0xbb,0xd7,0x6c,0xfe,0xfc,0xf6,0x20,0x5,0xda,0x4b,0x8b,0x57,0xd9,0xc9,0x76,0x58,0x5b,0x5f,0x1d,0x3b,0x48,0x34,0x63,0xad,0xfb,0x69,0x22,0x1,0xb3,0xb3,0x87,0xb9,0x79,0xfd,0x16,0x2f,0x96,0x9f,0xb6,0x53,0x60,0xe1,0x4f,0xef,0x37,0xaa,0x7a,0xa0,0x20,0xc1,0x2,0xee,0x3e,0x91,0x80,0x5e,0x6f,0x9b,0xdd,0x6c,0x17,0x60,0x21,0x1,0xe,0x9c,0x1c,0x40,0x4d,0xff,0x6b,0x8,0x34,0x4,0x0,0x52,0x0,0x8f,0x11,0xa4,0xd8,0x71,0x28,0xeb,0x92,0x11,0x98,0x6,0xc5,0x62,0x4,0x20,0xa9,0xf0,0x62,0xf1,0x5a,0x62,0xb1,0x62,0x52,0x2,0x3,0x79,0xfa,0x2,0xcc,0xd,0x5c,0x72,0x50,0x2a,0x32,0x9b,0x1c,0x2e,0x30,0x33,0x25,0xba,0xd5,0x92,0xf4,0x67,0xa4,0x9,0x3,0xb0,0x52,0x89,0x57,0x4,0xc4,0x8,0x8,0x82,0xe7,0x42,0x0,0xaf,0xbc,0x97,0x55,0x57,0x31,0x55,0x25,0x5a,0xfc,0x27,0xf,0xc9,0x13,0x49,0xa5,0x74,0x37,0x19,0x14,0x10,0xa3,0xd,0x96,0x5e,0xa8,0x2f,0x91,0x28,0x75,0x4c,0x2d,0xa0,0x6a,0x3,0x98,0x27,0xf4,0x7b,0x20,0x4d,0x26,0x26,0x35,0x3f,0x4a,0x7,0x1c,0xf1,0x1c,0x70,0x1,0x71,0x29,0xeb,0xe8,0x47,0x1b,0xc6,0x54,0xb5,0x10,0xee,0xfd,0xbe,0xe3,0x90,0x14,0xbc,0x58,0xcb,0x29,0x44,0x77,0x12,0x2f,0x8b,0x92,0x8a,0x3,0x66,0x8,0x9e,0xbb,0x56,0x4,0x18,0x18,0x85,0x6,0x4c,0x55,0x51,0xd7,0x1a,0x2f,0xe,0xf1,0xac,0xea,0x44,0xb9,0x1f,0xf7,0xa2,0xe5,0x2,0x8a,0x61,0xc2,0x87,0x3c,0x6b,0xf2,0x51,0xf6,0x7e,0xc3,0x58,0xb4,0x60,0x14,0xaf,0x36,0xc8,0x32,0xf8,0x99,0x2,0xdd,0xa0,0xd9,0x7c,0x2b,0x49,0xf7,0x9d,0xf8,0x26,0x4c,0x35,0x60,0x45,0xdb,0x46,0xf1,0xf6,0x3d,0x6f,0x1,0xa0,0x9b,0x0,0x9d,0xcd,0xad,0xaf,0xa8,0x5,0x9c,0x38,0xd6,0x2a,0x5b,0xe0,0xd8,0x44,0x2b,0x68,0xc6,0xea,0xe7,0x8f,0x0,0x1d,0x71,0x77,0x96,0x16,0xaf,0x3d,0xda,0xfa,0xf5,0xe3,0x6e,0xa6,0xd9,0xfc,0x34,0xae,0xc2,0x99,0x74,0xa6,0x7b,0xfc,0xe8,0xc9,0x67,0x1f,0x56,0xde,0x3f,0x16,0x77,0xc7,0xa3,0x1f,0x2,0x8e,0x0,0xad,0x29,0x5d,0xc7,0x6,0x6c,0x27,0xad,0x24,0xfc,0x5,0xbc,0xa8,0x41,0xe0,0x6f,0x35,0x49,0x88,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x16,0x11,0x12,0x1,0x22,0x6f,0x8b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xd5,0x49,0x44,0x41,0x54,0x48,0x89,0xed,0x95,0xb1,0x6e,0xc2,0x50,0xc,0x45,0xcf,0xa3,0x96,0x6a,0x55,0x19,0x3a,0xbc,0xe9,0x3d,0xc1,0x17,0xa4,0xed,0x8f,0x91,0xfe,0xc,0xfc,0x18,0x85,0x99,0x5,0x85,0x29,0x3,0x43,0x7,0x47,0x72,0x95,0xe,0x24,0x6b,0x8b,0x40,0x81,0x25,0x77,0xb4,0x2c,0xdf,0x63,0x59,0xba,0xe,0xc0,0xb,0xf0,0xa,0x14,0xc0,0x13,0x10,0x18,0x57,0x1d,0xf0,0x3,0x7c,0x3,0x27,0xe9,0xcd,0xdf,0x81,0x39,0xa0,0x77,0x2,0x30,0xe0,0x0,0x7c,0x9,0xe7,0xcd,0x17,0x6f,0xe5,0x47,0x99,0x53,0x5e,0x8a,0xc8,0xa8,0x0,0xee,0xde,0xd5,0xc7,0x7a,0xbd,0xdd,0x6d,0x2,0xb0,0x17,0x40,0x80,0xe7,0x9c,0x72,0x65,0x66,0x98,0xd9,0xbf,0x43,0x62,0x8c,0x34,0x4d,0x73,0x15,0x80,0xaa,0x86,0x9c,0x72,0xb5,0xdd,0x6d,0x3e,0x1,0x99,0xf5,0xf5,0x20,0x22,0x17,0x99,0xdf,0x2a,0x33,0x43,0x44,0xa0,0x3f,0xf5,0xec,0xef,0xf6,0xf1,0x35,0x1,0x4c,0x0,0x13,0xc0,0x0,0xd0,0xb9,0x3b,0xaa,0x3a,0xba,0xa1,0xaa,0xe2,0xee,0x70,0x8e,0x64,0x4,0x70,0xa0,0xad,0x8f,0xf5,0x2a,0xa7,0xbc,0x2c,0x8a,0xe2,0xa2,0x28,0x8e,0x31,0x5e,0x5,0x30,0x44,0x31,0xd0,0x2,0x1e,0x80,0xc4,0x3,0x9f,0x51,0xe0,0xc1,0xef,0xf8,0x17,0x29,0x4,0x47,0x72,0x2c,0x4,0x5,0x25,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char option_button_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x89,0x0,0x76,0x0,0x95,0x95,0xac,0x1a,0xb5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x15,0x31,0x33,0x8b,0x1c,0x10,0x81,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x8,0x49,0x44,0x41,0x54,0x48,0xc7,0xbd,0x95,0xbf,0x8a,0x14,0x41,0x10,0xc6,0x7f,0x35,0x37,0xee,0x3f,0xf,0x15,0x31,0xba,0xe0,0xb8,0xe3,0x9e,0x40,0x30,0x13,0xc4,0x40,0x1f,0x40,0xdf,0x40,0xb3,0x35,0xd7,0x54,0x4c,0x7d,0x81,0xcd,0xcc,0x8d,0x34,0x17,0x8c,0x45,0x10,0x13,0xc1,0x44,0x50,0x86,0xf3,0x96,0xbb,0x15,0x4c,0x8e,0xe3,0x66,0xa7,0xbb,0xca,0x60,0x7a,0x66,0x7b,0x6e,0x67,0x61,0x76,0xf,0x6c,0x68,0xa6,0xe9,0xa9,0xae,0xfa,0xea,0xab,0xaf,0xba,0x5,0x60,0x6f,0xe7,0xe0,0x11,0x30,0x6,0x1e,0xd2,0x61,0xe4,0x45,0xce,0x25,0xc7,0x7,0x60,0x32,0x9d,0x1d,0xbe,0x93,0xbd,0x9d,0x83,0xe7,0xfd,0xde,0xe0,0xf5,0xb0,0x3f,0xa2,0x3f,0xe8,0x77,0x3a,0x9d,0x1d,0xfd,0xe2,0xc9,0xe3,0x67,0x1b,0x47,0x9f,0xce,0x7e,0xf3,0xe5,0xdb,0x27,0x66,0x7f,0x8f,0x5f,0xa4,0xc0,0xf8,0xda,0xf6,0x75,0x86,0x83,0x11,0x22,0xd2,0xd9,0x89,0x7a,0xcf,0xcf,0xc3,0x1f,0x1b,0x1,0x18,0xe,0xaf,0x72,0xf7,0xf6,0x7d,0xde,0x7f,0x7c,0x3b,0x4e,0x81,0xfd,0xe1,0x60,0x4,0x80,0x99,0x75,0x76,0x52,0xf8,0x62,0x2d,0xfb,0x78,0x9c,0x9d,0x9d,0x92,0xcf,0x73,0x80,0xfd,0xb4,0x2d,0xb0,0x1,0x82,0x61,0x94,0x8c,0x54,0xeb,0x98,0x1f,0xe7,0xdd,0xa5,0x44,0xe0,0x5d,0x1,0x40,0xa,0xe0,0x55,0x4b,0xe7,0x52,0x82,0x11,0x11,0xcc,0x0,0xd1,0xc0,0x8c,0x80,0x18,0x1a,0x1,0x75,0x85,0xc3,0x6b,0xf9,0x3f,0x91,0x5,0x72,0xd,0xcb,0x6a,0x4f,0xa3,0xdc,0x92,0x10,0xa3,0xce,0xb2,0x2,0xa0,0xe6,0xcb,0x7d,0xad,0x40,0x4,0x9b,0xf0,0x95,0xe8,0x40,0x9d,0x81,0x3a,0xd4,0xfc,0x52,0x90,0x5a,0x23,0x6d,0x7b,0x0,0xbe,0x42,0x62,0xb,0x0,0xa6,0xba,0xf0,0x1f,0x1f,0x94,0x26,0x90,0x78,0x38,0xe7,0x50,0xaf,0x6d,0xe6,0xb4,0x29,0x23,0x2e,0x5f,0xc0,0x1d,0x31,0x10,0xa8,0x44,0xc,0x4c,0x6a,0xd,0x20,0xb,0x4,0xcb,0x1a,0x28,0x70,0x5e,0x9b,0x81,0x13,0xea,0x1a,0xb4,0x82,0x49,0x96,0xf8,0x8,0x1a,0xa8,0x4b,0x20,0x98,0x28,0x62,0xa0,0x22,0x88,0x5,0xd,0x50,0xae,0x55,0x9a,0xc,0x98,0x7a,0xc0,0xf0,0x11,0x7b,0x89,0x49,0x63,0x2f,0x89,0x38,0x50,0x33,0x92,0x80,0x48,0x43,0x72,0xa1,0xb,0x14,0xb3,0xa0,0xfe,0xc0,0x0,0xa6,0x75,0x17,0x40,0x58,0x5b,0xb3,0xb,0x9c,0xb9,0x26,0xb5,0x26,0xc4,0xa7,0xaa,0x92,0xd7,0x4c,0x54,0xff,0x95,0xda,0xaa,0x2c,0x81,0x5f,0xf0,0xd6,0xb5,0xb3,0xbd,0x77,0xa8,0xf7,0xab,0xf9,0x5e,0x25,0x88,0xb,0x77,0x5d,0xa,0x64,0x5e,0xfd,0xae,0xc8,0x1a,0xd1,0x1,0xe7,0xa,0x7c,0xdd,0x2e,0x2d,0x6,0xab,0x7c,0x59,0x95,0x40,0x1,0x90,0x25,0xc0,0x24,0x2f,0xce,0x31,0xb3,0xce,0xb3,0x2c,0x81,0xf,0x4,0xaf,0x3f,0x9d,0x9b,0x73,0x74,0x92,0x1,0x4c,0x4,0xe0,0xde,0x9d,0x7,0x2f,0x8f,0xff,0x4c,0x9f,0xe6,0xf3,0xf3,0xdd,0xff,0xf1,0x1a,0xf6,0xd2,0x5e,0x76,0xf3,0xc6,0xad,0x37,0x5f,0xbf,0x7f,0x7e,0x55,0xde,0x31,0x6a,0x57,0x80,0x6d,0x60,0xab,0x8b,0x83,0x4d,0xdf,0x80,0xb,0xda,0x3c,0x4d,0xb6,0x92,0xe2,0x1f,0x29,0x56,0x40,0xcc,0x4c,0xed,0x94,0xcb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x77,0x0,0x7d,0x59,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x2f,0x0,0x2d,0x0,0x31,0xdb,0x99,0xd6,0x23,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x16,0x15,0x22,0x43,0x97,0x9a,0x23,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xd2,0x49,0x44,0x41,0x54,0x48,0x89,0xed,0xd5,0x31,0x4e,0xc3,0x50,0x10,0x84,0xe1,0xef,0x5,0x4b,0x20,0x44,0xc1,0xeb,0x6c,0x3f,0xc1,0x9,0x2,0x5c,0x2c,0xe1,0x32,0x70,0xb1,0x90,0xd4,0x34,0xc8,0x9,0x9d,0x29,0x28,0x1c,0x29,0xc8,0x14,0x76,0x44,0x7,0x51,0x90,0x93,0x26,0x53,0xaf,0x76,0xfe,0xd5,0x4a,0x33,0x1,0x97,0xb8,0xc6,0x15,0xce,0x10,0xc,0xab,0x16,0x5f,0xf8,0xc4,0x47,0xd6,0x9b,0xdf,0xe3,0x6,0x17,0x7,0x2,0x68,0xf0,0x86,0x97,0x4c,0x77,0xf9,0xed,0xdd,0xf8,0x61,0x9c,0xca,0x34,0xd1,0xe,0xc,0x10,0xb4,0xd5,0xb2,0x7a,0x9e,0x2f,0x66,0x1,0xaf,0x19,0x32,0x9c,0xa7,0x32,0x4d,0x9b,0xa6,0x51,0xd7,0xf5,0x9f,0x3b,0x8a,0xbc,0xb0,0x7a,0x5f,0xed,0xe5,0x1f,0x63,0xc,0xa9,0x4c,0xd3,0xf9,0x62,0xf6,0x88,0x6c,0xf4,0xc3,0x65,0x27,0xf3,0xff,0xaa,0xae,0xeb,0xee,0x9,0xfd,0xab,0x47,0xbf,0x4e,0x1f,0x40,0x27,0x80,0x13,0xc0,0x9,0x60,0xb,0xd0,0xa,0xc4,0x18,0x7,0x37,0x8c,0x31,0x6e,0xc3,0xbe,0xa5,0x4b,0xc1,0xd,0xd6,0xd5,0xb2,0x7a,0x4a,0x65,0x9a,0x14,0x79,0xb1,0x53,0x14,0x17,0x79,0xb1,0x1f,0x41,0x1f,0xc5,0x58,0x63,0x13,0x50,0x3a,0x62,0x19,0x5,0x47,0xae,0xe3,0x6f,0x22,0x6d,0x3e,0xb3,0x5c,0x94,0xd4,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char panel_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x41,0x0,0x3c,0x0,0x44,0xc0,0x10,0x53,0xfb,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x17,0xb,0xf,0x82,0x5e,0x66,0x11,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x16,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x74,0x77,0xf6,0xff,0xcf,0x80,0x7,0x30,0x31,0x10,0x0,0xc3,0x43,0x1,0x0,0xea,0x61,0x1,0xe8,0x68,0xbf,0x2f,0x36,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x10,0x25,0xd,0x33,0x8d,0xed,0x3b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x15,0x49,0x44,0x41,0x54,0x18,0x95,0x63,0x54,0x57,0xd7,0xfc,0xcf,0x80,0x7,0x30,0xe1,0x93,0x1c,0x3e,0xa,0x0,0x86,0x1b,0x1,0x86,0x56,0xb4,0xba,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char popup_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x1b,0x89,0xf8,0xcc,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x27,0x0,0x35,0x33,0xd3,0x97,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x11,0x1c,0x2f,0xb8,0x3e,0xbe,0xfd,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xea,0x49,0x44,0x41,0x54,0x48,0xc7,0xed,0x95,0xb1,0x6e,0xd4,0x40,0x10,0x86,0xbf,0xf1,0x39,0x77,0xb9,0x2,0x21,0x90,0x2,0x42,0x40,0x83,0x94,0x74,0x44,0x22,0xaf,0x40,0xcf,0x1b,0xa0,0xbc,0x4,0x75,0x8a,0x20,0xa8,0x78,0xb,0x3a,0xe8,0xe8,0x79,0x6,0xa,0xca,0x48,0x34,0x10,0x25,0x87,0x93,0xb,0xc7,0x9,0x2e,0x17,0xef,0xce,0x50,0x78,0x7d,0x59,0xaf,0x7c,0x76,0x91,0x16,0x4b,0xeb,0xd9,0xb5,0x67,0xfe,0xf9,0x67,0xfe,0xd5,0x2e,0xdc,0xf0,0x91,0xc8,0x66,0xc0,0x20,0x58,0x59,0xe3,0x6f,0x80,0x2,0x3e,0x58,0x93,0xe0,0x3c,0x0,0x36,0x9e,0x3c,0xda,0xfe,0xb4,0x58,0x2e,0x9e,0x77,0x1,0x8c,0x47,0xe3,0xcf,0xdf,0x7e,0x1c,0xbd,0x0,0x4a,0xc0,0xd7,0xc1,0xc3,0x7b,0x77,0x1f,0x1c,0x3e,0xbc,0xff,0xf8,0xd5,0xd3,0xed,0x67,0xdc,0xbe,0x75,0xa7,0x35,0x7a,0x36,0xbf,0xe0,0xeb,0xd1,0x17,0x8e,0x27,0xdf,0xdf,0xfd,0x9c,0x9e,0x1c,0x0,0x57,0x79,0xa0,0xbc,0x91,0x65,0xd9,0xfe,0xee,0xce,0x1e,0xf3,0xbf,0xbf,0x39,0x9f,0x15,0xad,0x0,0xa3,0xe1,0x26,0xbb,0x3b,0x7b,0x9c,0x14,0xc7,0xfb,0xc0,0x6b,0xc0,0xd5,0x0,0xb9,0x88,0x6c,0x4d,0x67,0xe7,0x78,0x75,0x6b,0xb,0xb8,0x5c,0x2e,0x28,0xcb,0x12,0x11,0xd9,0x2,0x72,0x20,0xcb,0xa3,0x1e,0xe0,0xb4,0xac,0xda,0x64,0x49,0x8b,0xed,0x1a,0xc4,0x69,0x59,0x4f,0x7,0x31,0x80,0x0,0x98,0x1a,0x82,0x60,0x71,0x44,0x4,0x20,0x8,0x66,0xd6,0x50,0x30,0x6f,0xfa,0x59,0x78,0x87,0xd4,0x96,0x52,0xd1,0x14,0x3a,0x1,0xb0,0x1a,0xc6,0x56,0x19,0xab,0x2f,0x1a,0x25,0x91,0x2e,0x80,0xc0,0x40,0xd2,0xc0,0x6b,0x46,0x9d,0xc,0x30,0xad,0x32,0x98,0x36,0xb2,0x9,0xf1,0x5a,0x3b,0x18,0x90,0x96,0xd0,0xac,0xbc,0x4d,0xdd,0x6,0x80,0x5a,0xc8,0x69,0x96,0xa8,0x17,0xd6,0x42,0x5f,0x13,0xab,0xdc,0xb2,0x72,0x6b,0xba,0x9b,0xf5,0x30,0xa8,0x6a,0x97,0x88,0xb2,0x44,0xf2,0xb2,0x5a,0xf5,0xc8,0xa8,0x2b,0xd7,0xb4,0x76,0x8b,0xfe,0xad,0x97,0x51,0x5a,0xa8,0x77,0xd4,0x91,0x0,0x68,0xa3,0x3,0x12,0x26,0x26,0xd1,0x6e,0xe8,0x4,0x48,0x1c,0x2c,0x99,0x58,0x9f,0x8c,0xd6,0xd6,0xe6,0x9e,0x27,0xbb,0xe9,0xa1,0xfa,0x1f,0xa0,0x2,0xb0,0x4a,0x0,0x2b,0xbc,0xba,0xde,0x0,0xaf,0xe,0x33,0x2b,0x6a,0x55,0x6b,0x0,0xef,0xbc,0xfb,0x50,0x4c,0x4f,0xe9,0x2,0xf1,0xea,0x28,0xa6,0xa7,0x38,0xe7,0x3e,0xd6,0xb7,0x53,0x1e,0x36,0xbf,0x3b,0xbb,0x98,0xbc,0xc5,0x18,0xce,0xff,0xcc,0x5f,0x66,0x59,0xb6,0xd9,0x6,0xa0,0xaa,0x97,0xde,0xfb,0xf7,0x67,0xbf,0x26,0x6f,0x0,0x7,0xe8,0xea,0x5a,0x3,0xc6,0x61,0x8c,0xc2,0x6,0x93,0xe4,0x60,0xb7,0x10,0xb4,0x4,0x16,0x61,0x94,0xf1,0xdd,0x98,0x3,0xc3,0x60,0x7,0x2d,0x7,0x90,0x5,0xda,0xe,0xb8,0xa,0xd6,0x4b,0x94,0x29,0x8b,0x46,0x7c,0x6b,0xc7,0xfb,0x5b,0x23,0x20,0x5,0xec,0x1f,0x7b,0x45,0xf9,0x5f,0xa9,0x9f,0xe1,0xbb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xd,0xd7,0x0,0x0,0xd,0xd7,0x1,0x42,0x28,0x9b,0x78,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xe,0x21,0x3,0x29,0x83,0x1c,0x15,0x0,0x0,0x0,0xc1,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0x3d,0x4b,0xc3,0x60,0x14,0xc5,0xf1,0x5f,0xea,0x85,0xda,0xe0,0xe0,0x56,0x92,0x87,0xba,0x48,0x37,0x5f,0x3e,0x9b,0x9f,0xc4,0xcf,0x56,0xdb,0xd9,0x45,0xd2,0xd0,0xcd,0x41,0x34,0x85,0x47,0xe2,0x60,0xe6,0xa4,0xd0,0xc5,0xc1,0x3b,0x5e,0xee,0xf9,0x1f,0x2e,0x9c,0x53,0xa0,0xc4,0x35,0xae,0x70,0x81,0xc2,0xf8,0xf4,0xf8,0xc6,0x7,0xde,0x63,0x10,0x3f,0x60,0x85,0xcb,0x13,0x1,0x1d,0xde,0xf0,0x12,0x83,0xf3,0xcd,0xfd,0xdd,0xe3,0x73,0xaa,0xd3,0x22,0x22,0x46,0x1,0x39,0xe7,0xbe,0xd9,0x37,0x5f,0xdb,0xdd,0xe6,0x9,0xaf,0x81,0xc0,0x3c,0xd5,0xa9,0xec,0xba,0x4e,0x7b,0x68,0x47,0xed,0xab,0x65,0x55,0xa4,0x3a,0x95,0xdb,0xdd,0x66,0x8e,0x98,0xd,0xfb,0x22,0x22,0x26,0xc5,0xd0,0x1e,0x5a,0x11,0xc1,0xf0,0xea,0x6c,0xfc,0x7c,0x7a,0xfe,0x1,0x7f,0x9,0xd0,0xe7,0x9c,0x55,0xcb,0x6a,0x52,0x50,0x2d,0x2b,0x39,0x67,0x7e,0x23,0x2d,0x90,0x71,0x6c,0xf6,0xcd,0x67,0xaa,0xd3,0x62,0x7d,0xbb,0x3e,0x29,0xca,0x38,0x22,0x17,0xa8,0x9d,0x51,0xa6,0xc2,0x99,0x75,0xfe,0x1,0x7d,0xe1,0x44,0x88,0x9a,0x7d,0x74,0x9f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -240,7 +235,7 @@ static const unsigned char popup_bg_disabled_png[]={ static const unsigned char popup_checked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xd9,0xb,0x17,0x6,0xe,0x15,0xb4,0x28,0xc,0xa7,0x0,0x0,0x0,0x4a,0x49,0x44,0x41,0x54,0x18,0xd3,0x85,0x8c,0xbb,0xd,0xc0,0x20,0x14,0x3,0xef,0xa1,0xcc,0x91,0x2a,0xb,0xb0,0xff,0xe,0xb0,0x0,0x4d,0xb2,0x88,0xd3,0xe4,0x21,0x44,0xf8,0xd8,0x95,0x7d,0xd2,0x99,0x10,0xab,0x4,0x36,0x39,0x66,0x20,0x97,0x47,0x53,0x83,0xc3,0x78,0x9d,0x16,0x7c,0x8c,0x60,0x35,0xf8,0xd9,0x43,0x0,0x13,0xa2,0xb5,0xb4,0x10,0x0,0x7d,0x4d,0xe5,0x96,0xf8,0xf7,0x5,0x67,0x99,0x30,0x2b,0xcf,0xbf,0xba,0xe0,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x16,0x5,0xf,0x4c,0x8a,0xd4,0x7,0x0,0x0,0x0,0x43,0x49,0x44,0x41,0x54,0x18,0x95,0x7d,0xcc,0xc9,0xd,0x0,0x20,0xc,0x3,0xc1,0xd,0xa2,0x18,0xe8,0xbf,0x98,0xd0,0x8d,0xf9,0x10,0x84,0xb8,0xe2,0x57,0x3c,0x92,0x4d,0x88,0xdf,0xa5,0xaf,0x2,0xf9,0x5,0xcd,0x9b,0x9e,0xb,0x81,0xa5,0x16,0x4b,0xf1,0xdc,0x70,0x2e,0x44,0xb9,0x23,0x80,0x9,0xb1,0xae,0xac,0x8,0x80,0x46,0xdc,0x5d,0xe2,0x4c,0x7,0x5d,0x41,0x30,0x13,0xdf,0x10,0x9e,0xf0,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -255,17 +250,27 @@ static const unsigned char popup_unchecked_png[]={ static const unsigned char popup_window_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x94,0x0,0x80,0x0,0xa0,0xea,0x26,0x82,0xc7,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x14,0x21,0x38,0x57,0xce,0xb1,0x6f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x9c,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0x3f,0x6b,0x14,0x51,0x14,0xc5,0x7f,0x77,0x76,0x92,0xac,0xa2,0x1,0x6d,0x8c,0x89,0x89,0x60,0x29,0x58,0x88,0xdf,0xc0,0x4f,0x20,0x76,0x56,0x96,0x36,0xb6,0x5a,0xa8,0xa5,0x5a,0x68,0x15,0xb0,0xb1,0xb4,0xb2,0x13,0x21,0xbd,0xdf,0x40,0x2c,0x4,0x5b,0x31,0x31,0x71,0x25,0x26,0x9a,0x7f,0x24,0x3b,0x7f,0xde,0xb1,0x78,0xef,0xcd,0xce,0x6c,0x26,0x89,0x41,0xc1,0x66,0x7,0x6,0x86,0xd9,0x7b,0xcf,0x3b,0xe7,0xdc,0x33,0x33,0xfb,0xe0,0x7f,0x1f,0x56,0x3b,0x93,0x99,0xa9,0xd9,0x9b,0x66,0x76,0xc7,0xcc,0xae,0xb7,0x15,0x4b,0x7a,0x27,0xe9,0xe5,0x72,0x6f,0xe9,0xd,0xe0,0x0,0x19,0x90,0x0,0x9d,0x99,0xa9,0xd9,0xfb,0xd3,0xe7,0x66,0x1e,0x3f,0x79,0xf0,0x9c,0x13,0x93,0xdd,0xd6,0xd5,0x76,0x37,0xf7,0x78,0xf8,0xf4,0x1e,0x2b,0xdf,0x97,0x1f,0x2d,0xf7,0x96,0x9e,0x1,0xa5,0x1,0x29,0x30,0x71,0xe1,0xfc,0xdc,0xa7,0x57,0x2f,0x5e,0xcf,0x15,0x85,0xa3,0xc8,0x8a,0x56,0x80,0x74,0x3c,0x25,0x4d,0x13,0x6e,0xdf,0xbd,0xb5,0xf8,0xf5,0xdb,0xe2,0x65,0xa0,0x9f,0x2,0x1d,0xa0,0x6b,0x66,0x73,0xbb,0xdb,0x7d,0x30,0x79,0x45,0xa,0xfc,0x2a,0xad,0x22,0xeb,0xe7,0x64,0x7d,0x30,0xb3,0x39,0xa0,0xb,0x14,0x11,0x60,0x1c,0xa0,0x94,0xf3,0xfd,0xc8,0x77,0xb9,0xe0,0xe,0xa0,0xfa,0x7d,0x7f,0x8c,0x3,0x9d,0x34,0x78,0x30,0x6,0x20,0xe7,0x90,0xc,0x4c,0x18,0x86,0x10,0x26,0xab,0xb5,0x89,0x1a,0xa9,0x31,0x20,0x49,0xe3,0x4,0x3c,0x80,0x10,0x2,0x9,0x33,0x2f,0xc3,0xc5,0x26,0xf3,0x4,0x6a,0x1c,0x12,0xc0,0xd2,0x1,0x49,0x70,0x72,0x55,0x85,0xac,0xba,0xf0,0xd7,0xa2,0x69,0x4a,0xb0,0x26,0x6d,0xcc,0xd9,0x9,0x45,0x44,0x85,0x15,0x4d,0x35,0x2f,0x5c,0x1d,0xc4,0x8,0x23,0xac,0x8e,0xd2,0xb9,0x7d,0x39,0x33,0xc9,0x8b,0x50,0xd4,0xaf,0xe6,0x68,0x87,0x19,0xc,0xa,0xbc,0x68,0xd5,0x9a,0x5c,0x5d,0x6f,0x3b,0x80,0x6b,0x38,0x4e,0x3,0x8a,0x96,0xf5,0x87,0x0,0x9c,0x73,0x21,0x32,0xd1,0x79,0x43,0x3e,0x0,0x61,0xac,0x60,0x76,0x88,0x4,0x27,0x55,0x44,0xe5,0x6f,0x54,0x14,0x22,0x90,0xb3,0x23,0x19,0xc,0xa2,0xab,0x7d,0x6a,0x2c,0x46,0xf2,0x60,0x6,0x16,0x72,0x2b,0x53,0xa8,0xb5,0xca,0x84,0x6,0x68,0xab,0x89,0xa5,0x42,0x80,0x86,0x56,0x72,0x54,0x13,0x39,0xc2,0xc4,0x32,0xac,0x58,0xcb,0xc3,0x70,0xfa,0xe,0xf5,0x40,0xf2,0xf6,0xa9,0xf1,0x1a,0x6a,0x36,0xe,0x1,0xe,0x31,0x50,0x1c,0x56,0x20,0x3b,0x48,0x80,0xe4,0x47,0x79,0x44,0x12,0x5d,0x23,0x79,0x98,0x2,0x3,0x6b,0x8c,0xf2,0x60,0x0,0x85,0xc,0x48,0x10,0x1e,0x67,0xa2,0xac,0xe0,0xab,0xd9,0x21,0x12,0xb2,0xac,0xef,0x1f,0xf4,0x8e,0xa1,0xd2,0x50,0x47,0x50,0x8a,0xa4,0xe3,0x9b,0x5c,0xa9,0xd6,0xd7,0xfa,0x24,0x70,0x76,0x76,0xfa,0xe2,0xe7,0xe3,0x7c,0xf,0x96,0x56,0xbe,0x5c,0x2,0xd6,0x2a,0x6,0x45,0x5e,0x72,0xf5,0xca,0xb5,0x3f,0x6a,0xfe,0xf0,0xf1,0x7d,0xbb,0x84,0x8d,0xcd,0x5f,0xc7,0xfe,0x32,0x25,0x7f,0xfb,0x69,0x1b,0x1,0x8c,0x0,0x46,0x0,0x23,0x80,0x11,0xc0,0x8,0x60,0x4,0xf0,0xef,0x0,0x14,0x1,0x14,0xf6,0x84,0x3f,0x5c,0x71,0x74,0x97,0x2b,0x7c,0x6d,0x4,0x89,0xc,0x5c,0x9e,0x67,0xb,0xab,0xeb,0x3d,0xe,0x3,0x71,0x5,0xac,0xae,0xf7,0xc8,0xf3,0x6c,0x21,0xfe,0xfd,0x4c,0x81,0x12,0x28,0xd6,0x36,0x56,0xe7,0x5,0x27,0xb7,0x76,0xb6,0x6e,0x24,0x49,0x32,0xd1,0xa,0xe0,0x5c,0x3f,0x2f,0xf2,0xb7,0xeb,0x1b,0xab,0xf3,0x40,0x11,0x37,0x9e,0x5d,0xe0,0x14,0x70,0x26,0x9c,0xa7,0xc3,0x96,0x6e,0xd8,0x1f,0x7,0x64,0xc0,0x16,0xf0,0x33,0x9c,0xdb,0x91,0xc1,0x5e,0xf8,0x81,0x50,0x34,0x16,0xf6,0x93,0x56,0x33,0xac,0x4,0x72,0x60,0x27,0xd4,0xee,0x45,0x6,0x49,0x90,0x32,0x1e,0xd8,0x4c,0x84,0xe6,0x64,0x8,0xc0,0x5,0x90,0x7e,0x68,0xce,0x80,0xe2,0x37,0x5,0x81,0x51,0xea,0x99,0x8b,0xa0,0x84,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xc2,0x0,0xc2,0x0,0xcc,0x6a,0x6f,0xcc,0x71,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x3,0x34,0x19,0x79,0x8d,0xec,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x64,0x49,0x44,0x41,0x54,0x58,0x85,0xed,0x97,0x3f,0x4e,0x2,0x41,0x14,0xc6,0x7f,0x33,0x2c,0x7f,0x62,0x34,0x84,0x92,0x25,0xf1,0x0,0x1e,0xc3,0xb,0x48,0xec,0xf4,0x2,0xd4,0x34,0x56,0x96,0x56,0x36,0xc4,0x92,0x13,0xd0,0x19,0xd,0xbd,0xc7,0xf0,0x0,0x26,0x2c,0x8d,0x81,0x10,0x35,0x61,0x99,0x61,0xc7,0x82,0x37,0x48,0x8,0xd1,0xcd,0x4a,0x42,0x33,0x2f,0x79,0xc9,0x4e,0xe6,0xfb,0x7e,0xf3,0xcd,0x6c,0xf5,0xe0,0xd0,0xa5,0x36,0x5a,0xc7,0x71,0x7c,0xa9,0x94,0xea,0x28,0xa5,0xce,0x77,0x89,0x9d,0x73,0x2f,0xce,0xb9,0x7e,0x92,0x24,0x8f,0x40,0x6,0x38,0x5,0x68,0xa0,0x14,0xc7,0xf1,0x4d,0xb3,0xd9,0xbc,0xeb,0xf5,0xfa,0xbf,0x9e,0xd8,0xed,0x76,0x18,0x8f,0xc7,0xb7,0x49,0x92,0xdc,0x3,0x4b,0x5,0x44,0x40,0xb5,0xd5,0x6a,0xbd,0xe,0x6,0xcf,0xa7,0x79,0x62,0x5f,0x5d,0x5d,0xbc,0x8d,0x46,0xa3,0x33,0x20,0xd5,0x40,0x9,0xa8,0x29,0xa5,0x72,0x99,0x1,0x44,0x5b,0x3,0x4a,0x1e,0x50,0xc9,0x6b,0xde,0xa8,0x8a,0x7,0x68,0xa0,0x5c,0x0,0x50,0x6,0xb4,0x46,0xfe,0x40,0x1,0x80,0x6,0x94,0x7,0x14,0x2d,0x55,0xe4,0xe4,0xb5,0xd9,0xc7,0xf8,0x57,0x5,0x40,0x0,0x4,0xc0,0x9e,0x0,0xd1,0xe6,0xe2,0xfa,0xba,0x5d,0x1c,0x60,0xad,0xa5,0x5e,0x6f,0xe4,0x32,0xcd,0x66,0xd3,0xf5,0xf7,0xe1,0xdf,0x20,0x0,0x2,0x20,0x0,0x2,0x20,0x0,0x2,0x20,0x0,0xf6,0x7,0x70,0x1e,0xe0,0x0,0x9c,0x73,0xef,0xb9,0x9d,0x3f,0x5a,0xe7,0x13,0x64,0xc6,0x98,0xa1,0x31,0xe9,0x9f,0x66,0x63,0x52,0x8c,0x31,0x43,0x56,0x83,0x27,0x11,0xb0,0x4,0xec,0x64,0x32,0x79,0x0,0x8e,0xa2,0x28,0x6a,0x6b,0xad,0xab,0xbb,0xcc,0x59,0x96,0xa5,0xd6,0xda,0x27,0xd1,0x5a,0x64,0xf0,0xac,0x1,0xc7,0x40,0x43,0xfa,0x84,0xd5,0x48,0xb7,0xfd,0x3e,0x19,0xb0,0x0,0x3e,0x80,0xa9,0xf4,0xa7,0x4f,0x30,0x97,0xd,0x44,0x54,0x66,0x35,0x4f,0xfa,0x81,0xcc,0x89,0xce,0x0,0x5f,0xa2,0x9d,0xfb,0x4,0x5a,0xae,0x52,0x91,0x34,0x55,0x31,0xeb,0x2d,0x40,0x26,0x90,0x54,0xcc,0xb,0xc0,0x7e,0x3,0xa,0x34,0x6f,0x6c,0x6b,0x15,0x5c,0x54,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char progress_bar_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x2d,0x0,0x31,0x39,0x29,0xd6,0x70,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0xe,0x26,0xb,0xfc,0x38,0xdf,0xa0,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xb2,0x49,0x44,0x41,0x54,0x38,0xcb,0x6d,0x92,0xbd,0x8e,0x13,0x51,0xc,0x85,0x3f,0x7b,0xa6,0x49,0x93,0x49,0xa,0x2a,0x9a,0x28,0x4a,0xc7,0xdf,0x2,0xed,0x2a,0x35,0x25,0x1d,0x88,0xdd,0x17,0x98,0x82,0x7,0x48,0x8f,0xc4,0x23,0xa4,0xdc,0x86,0x20,0xb6,0xa3,0xe4,0x25,0xb2,0x12,0x7f,0x55,0x14,0xa5,0xa2,0xa2,0x1,0x69,0xa5,0x14,0x7b,0x6d,0x53,0xcc,0xdc,0xd9,0x4c,0x58,0x4b,0x6e,0xae,0xcf,0xb1,0x8f,0x8f,0xaf,0x4c,0xa6,0x33,0x72,0xa8,0xf3,0x2,0xa8,0x81,0xe7,0xc0,0x7d,0xfa,0xf1,0xb,0x58,0x3,0xcb,0xed,0x6e,0xf3,0x25,0x3f,0xca,0x64,0x3a,0x43,0x9d,0xa,0x78,0x2f,0x22,0xb5,0x8a,0xa0,0x85,0x40,0x8,0x22,0x2,0x40,0x44,0x80,0x4,0x6e,0x81,0x47,0x10,0x11,0x4b,0x60,0xb1,0xdd,0x6d,0xfe,0x96,0xea,0x0,0xbc,0x53,0x91,0xba,0x28,0xb5,0x21,0x22,0x20,0x74,0xd,0xda,0x59,0xa8,0x6,0x2a,0x81,0x25,0xaf,0x3d,0xc2,0x80,0xb7,0x32,0x9d,0xcc,0x5e,0x89,0xc8,0xa7,0xb2,0x54,0x4,0x6d,0xa0,0x22,0xa8,0x8,0xd1,0x51,0xc9,0x93,0x1b,0x45,0x38,0x29,0x39,0x11,0xf1,0xba,0x4,0x6a,0x2d,0xa4,0x47,0x16,0x11,0x10,0xa1,0x3f,0x9f,0x6e,0x1d,0x41,0xd1,0x22,0xb0,0x14,0x75,0x9,0x9c,0xe8,0x11,0x39,0xa7,0xb6,0x2b,0x78,0x44,0xcf,0xcd,0x88,0x40,0x51,0xc,0x3f,0x29,0x81,0xea,0x98,0x78,0xa8,0xe2,0x70,0xfa,0x1d,0x51,0x95,0xdd,0x9,0xf,0xa5,0xe7,0x6c,0x95,0x21,0xde,0x5b,0x25,0x0,0x6b,0x55,0x95,0x59,0x7a,0x1c,0x37,0x41,0x6f,0xaf,0x10,0xa,0xe2,0x1d,0xd9,0x23,0xba,0x5a,0x79,0xa8,0xc7,0xdb,0xdd,0x44,0x1a,0xa7,0xb3,0xf8,0x68,0xef,0x11,0x21,0x78,0x78,0x6f,0x7,0x5,0xae,0x1b,0x67,0xb3,0x3c,0xef,0xce,0x45,0x34,0x1f,0x2a,0x1b,0x17,0xf8,0x2d,0xae,0xc1,0x5c,0x2b,0xb0,0x8e,0x68,0x7e,0x58,0xbe,0x75,0x97,0x78,0xd7,0x30,0xe7,0x21,0xe,0x58,0x2b,0xb0,0x4c,0x66,0x7d,0x62,0x6,0xb4,0x79,0x57,0x2d,0x99,0x1,0x2c,0xb5,0x1a,0xe,0x2f,0x87,0x55,0x75,0x61,0x77,0x34,0x31,0x77,0xcc,0xfd,0xff,0x77,0x33,0x86,0x55,0x75,0xb1,0xdd,0x6d,0x2e,0x55,0x80,0xf9,0xfc,0x74,0x31,0x1a,0x8f,0x57,0x37,0x29,0x91,0xcc,0x30,0xf7,0xde,0x64,0xda,0x66,0xc9,0x8c,0x9b,0x94,0x18,0x8d,0xc7,0xab,0xf9,0xfc,0x74,0x1,0x20,0x4f,0x1f,0x3f,0x83,0x8,0xae,0xbe,0x5d,0x8d,0xce,0xde,0x9c,0xbf,0xfc,0xf1,0xfd,0xe7,0xd9,0x7e,0xbf,0x7f,0x62,0x66,0xf7,0xe,0xdd,0x2e,0x8a,0xe2,0xf7,0x60,0x30,0xf8,0xfa,0xf0,0xd1,0x83,0xd5,0xea,0xe3,0x87,0xcf,0xc0,0x1f,0x80,0x7f,0x8a,0x82,0x28,0xc9,0xa8,0xf,0x19,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x27,0x0,0x27,0x0,0x27,0x12,0xaa,0xad,0x65,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x16,0x16,0x1b,0x8f,0x3,0x26,0x8d,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0x3b,0x4e,0x3,0x41,0x10,0x84,0xe1,0x6f,0x4c,0x4b,0x1e,0xaf,0x36,0x20,0xde,0x11,0x9c,0x80,0xc7,0xd9,0x38,0x9,0x67,0x33,0x76,0x4c,0x82,0xd6,0x31,0x1,0x82,0xb1,0x34,0xc8,0x4,0x6c,0xbc,0x6b,0xc9,0x9,0x1,0x1d,0xb6,0xba,0xfe,0x52,0x4b,0x55,0x9,0x1d,0xae,0xd1,0xe3,0xa,0xc9,0xfc,0x9c,0xf0,0x8d,0xf,0xbc,0xc7,0x24,0x7e,0xc0,0xd,0xf2,0x99,0x80,0x8a,0x37,0xbc,0xc4,0xe4,0x7c,0x7b,0x7f,0xf7,0xf8,0x5c,0x86,0xb2,0x89,0x88,0x59,0x40,0x6b,0xed,0x34,0x1e,0xc6,0xaf,0xdd,0x7e,0xfb,0x84,0xd7,0x40,0x60,0x5d,0x86,0xd2,0xd5,0x5a,0xd5,0x5a,0x67,0xed,0x73,0xce,0xa9,0xc,0xa5,0xdb,0xed,0xb7,0x6b,0xc4,0x6a,0xda,0xa7,0x88,0x58,0x14,0x43,0xad,0x55,0x44,0x30,0xbd,0xba,0x9a,0x3f,0x5f,0x9e,0x7f,0xc0,0x5f,0x2,0x9c,0x5a,0x6b,0x72,0xce,0x8b,0x82,0x9c,0xb3,0xd6,0x1a,0xbf,0x91,0x16,0x68,0x38,0x8e,0x87,0xf1,0xb3,0xc,0x65,0xd3,0xf7,0xfd,0x59,0x51,0xc6,0x11,0x2d,0x61,0x70,0x41,0x99,0x92,0xb,0xeb,0xfc,0x3,0x18,0xa7,0x44,0x3f,0xdc,0xad,0xd9,0x96,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char progress_fill_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xaf,0x0,0x9a,0x0,0xec,0x52,0xc,0x20,0x4d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0xe,0x28,0x33,0x4a,0xb9,0x4a,0xb0,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x9a,0x49,0x44,0x41,0x54,0x38,0xcb,0x75,0x93,0x4b,0x88,0x5c,0x45,0x14,0x86,0xbf,0x53,0x75,0x6b,0xa6,0x67,0x92,0xee,0x76,0x32,0xce,0x18,0x8c,0xc3,0xb4,0x4,0x62,0x30,0xf,0x41,0x41,0x8c,0xae,0x5d,0xb8,0x8,0x98,0x8c,0x90,0x85,0x44,0x70,0x2d,0x66,0xab,0xb,0x97,0x6e,0xdc,0xeb,0x5a,0x48,0x16,0x32,0x90,0xc9,0x80,0x2e,0x7c,0x80,0xd9,0x9,0x1a,0xc8,0x42,0xe3,0xa0,0x84,0x3c,0xe6,0x21,0x61,0x3a,0x9d,0x89,0xf6,0xed,0x3b,0xf7,0xd9,0x55,0xc7,0x45,0xdf,0x91,0x9e,0x80,0x3f,0x14,0x75,0xaa,0xea,0xd4,0x7f,0xfe,0xf3,0x53,0x25,0xaa,0xca,0x1e,0x3a,0xb3,0x67,0x3e,0xd1,0xe1,0xc4,0x7,0x61,0x18,0xcd,0x11,0x22,0xcb,0x38,0xcc,0xd0,0x9b,0x68,0xd8,0x93,0xa8,0xfc,0xa2,0x7b,0xb8,0xf9,0xe9,0xde,0xb6,0x0,0x74,0x9e,0x7e,0x75,0xc1,0x57,0xee,0xdb,0x93,0xc7,0x5f,0x3b,0x71,0xfe,0x9d,0xf3,0x2c,0x2e,0x1e,0xa5,0xd5,0x3a,0x44,0x91,0x7,0x0,0x26,0x1b,0x86,0x38,0x7e,0xcc,0xc6,0xc6,0x5d,0xae,0x5d,0xbd,0xc6,0xef,0x7f,0xfe,0xbc,0x66,0x5d,0xf5,0xd6,0xf6,0x7c,0x7b,0x4b,0x0,0x16,0xda,0x6f,0xfc,0x7a,0x61,0xe9,0xfd,0xd3,0xe7,0xce,0x5d,0xa4,0xbf,0xe3,0x49,0x63,0xc8,0xe3,0xb0,0x4f,0x40,0xa3,0x65,0x98,0x6e,0x41,0x7b,0xd6,0xb2,0xba,0x7a,0x85,0xe5,0x95,0x2f,0x7f,0xd3,0xe2,0xc0,0x4b,0xb6,0x33,0x73,0xe6,0xf3,0x53,0xc7,0x5e,0x3f,0x7b,0xf1,0xbd,0x4b,0x3c,0xdc,0x8,0xf4,0xbb,0x4a,0xdc,0xf3,0x94,0xb9,0xee,0x1b,0x69,0x3f,0x50,0xa6,0x90,0xa5,0xca,0xa9,0x97,0x4f,0x73,0xff,0xf6,0x9d,0x67,0x76,0xe2,0x3b,0x73,0xb6,0xed,0x8e,0x7e,0xf5,0xe1,0xa5,0x8f,0x27,0x7d,0x32,0x43,0xfc,0x48,0x49,0xfe,0xf1,0xa8,0x7,0xef,0x41,0xbd,0x12,0xbc,0xd6,0x31,0x14,0x59,0x40,0xbd,0x40,0x80,0x17,0x4e,0x2e,0x70,0xfd,0xc7,0x1f,0x8e,0x47,0xa1,0x72,0xcd,0xe6,0x81,0x23,0xf4,0x1f,0x4,0xe2,0xee,0x10,0x4,0x74,0xdc,0x20,0xf6,0xaf,0xe3,0x2c,0x60,0x5d,0x44,0xfb,0xd9,0x23,0x84,0xca,0x35,0x23,0x51,0x2b,0x45,0x1a,0x28,0xd3,0x40,0x59,0x84,0x3a,0x5b,0x41,0x64,0x3f,0x81,0xea,0x88,0x42,0xa0,0x4c,0x3,0x45,0x1a,0x10,0xb5,0x12,0x1,0x64,0x3,0x25,0x4f,0x3c,0x55,0x1e,0x46,0x89,0x22,0xf5,0x85,0xb1,0xda,0x2,0x68,0x0,0x11,0xf2,0xc4,0xe3,0x6,0xa3,0xb3,0x48,0x82,0x21,0x1f,0x78,0x8a,0x44,0xa8,0x32,0x5f,0xb,0xd5,0x7a,0xaa,0x9,0x64,0xac,0x2f,0x2,0x45,0x2,0x6e,0xe0,0x91,0x60,0xf8,0x4f,0x41,0xb1,0x5b,0x2b,0x18,0xc3,0x93,0x5e,0xec,0xa1,0xd8,0x5,0xbb,0xa7,0x0,0x51,0xcd,0x13,0x2f,0xc5,0x0,0xca,0x2c,0x8c,0xa,0xcb,0xff,0x98,0xa8,0xa3,0xd8,0x1a,0x30,0xd3,0x1e,0x44,0x35,0xc2,0x56,0xc9,0x76,0x6f,0xb3,0x79,0xb0,0xec,0x10,0xca,0x80,0xd7,0xb1,0x47,0x3a,0xde,0x42,0x4d,0x63,0x5,0xbc,0x13,0xb6,0x7b,0x9b,0x60,0xab,0xc4,0xe0,0x76,0x97,0x6f,0xdc,0x5a,0xc5,0xb6,0x2d,0x38,0x4b,0x28,0x95,0x2a,0xb,0x54,0xd9,0xa8,0xa5,0x2a,0xaf,0xe3,0x2c,0x10,0x4a,0x5,0x67,0xb1,0x6d,0xcb,0x8d,0x5b,0xab,0xe0,0x76,0x97,0x6d,0xbf,0xf8,0xeb,0xba,0x33,0x13,0x17,0xd4,0x4f,0x1e,0x9a,0x9f,0x7f,0x11,0x9,0x82,0x15,0xc1,0x88,0x60,0xc4,0x60,0x8c,0xc1,0x46,0x6,0x37,0x61,0xb1,0x53,0x11,0xd1,0x53,0x8e,0xb5,0xf5,0xaf,0xb9,0xf7,0xe8,0xfb,0xbb,0xeb,0xf1,0x4f,0x6f,0x5b,0x80,0xc5,0xce,0x73,0xbf,0x6c,0x3d,0x58,0x7b,0xf3,0x61,0x77,0xa3,0xdd,0x68,0xce,0x60,0xa7,0xe,0x62,0xa7,0xa6,0x89,0x1a,0x16,0xd3,0xb0,0x68,0x23,0xa2,0xb0,0x29,0x8f,0xcb,0x7b,0xdc,0xfc,0xe3,0x32,0xeb,0x7f,0x7f,0xb7,0xd9,0x3a,0x3c,0x7c,0xb7,0xbb,0xb3,0xb5,0x25,0xb5,0x57,0x53,0x4b,0x4b,0x4b,0xcf,0xdf,0xbe,0xb9,0xf3,0x51,0xdc,0x93,0xb3,0x54,0x93,0x2d,0x42,0x64,0x9e,0xf8,0xce,0x1,0x57,0xc4,0xad,0x39,0xfd,0xe6,0xd8,0x2b,0xb3,0x9f,0xad,0xac,0xac,0xdc,0x7,0xb2,0x7f,0x1,0x90,0xaf,0x58,0x10,0xf8,0xc7,0xe,0xbe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x15,0x1e,0x28,0xcd,0x92,0x83,0xf8,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x82,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd0,0x21,0xe,0xc3,0x30,0xc,0x5,0xd0,0xbf,0xc9,0x2c,0x3f,0xb4,0xbd,0xca,0x60,0x6e,0xd0,0xb3,0xe6,0x6,0x81,0x3b,0x4b,0x59,0x64,0x87,0x39,0xd2,0xc8,0x40,0xe7,0x4a,0x93,0xc6,0x6,0xfa,0xe1,0xb3,0xfd,0x81,0x81,0x2b,0xb7,0x8,0xa5,0x94,0x87,0xaa,0x56,0x33,0x5b,0x8e,0x4e,0x72,0xcf,0x39,0x6f,0xad,0xb5,0xe7,0xd1,0x25,0x16,0xa8,0x6a,0xed,0xbd,0x27,0x77,0xff,0xf0,0x39,0x67,0x2,0x50,0x1,0xac,0x5f,0xb,0xcc,0x6c,0x89,0xc7,0x0,0xe0,0xee,0xc9,0xcc,0x52,0xf4,0xfb,0x69,0xf3,0xc7,0xfc,0x61,0x1,0xc9,0x5d,0x44,0x46,0x74,0x11,0x19,0x24,0xf7,0x93,0x47,0xc8,0x39,0x6f,0x0,0x6a,0x7c,0x18,0xc9,0xf1,0x9e,0x5d,0x9,0x79,0x1,0x2e,0x56,0x2e,0xc3,0x70,0xd9,0xde,0xde,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char radio_checked_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x3,0x1,0x4,0x19,0x36,0x83,0x13,0x8d,0xb2,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x1,0x9d,0x49,0x44,0x41,0x54,0x38,0xcb,0xad,0x93,0x31,0x6b,0xdb,0x50,0x14,0x85,0x3f,0x59,0x8a,0x21,0xbb,0x17,0xd1,0x37,0xa4,0xa4,0xb5,0x10,0xb5,0x3,0xfa,0x7,0x5d,0x3a,0x74,0xf2,0x56,0x39,0x64,0x4d,0x97,0x42,0x9b,0xce,0x6d,0x7e,0x44,0xe3,0x8e,0xf5,0x60,0x4,0xc5,0x22,0x9b,0x27,0x63,0xe8,0xea,0xc5,0x43,0x4d,0x48,0x40,0x7a,0xe9,0xd0,0xe0,0xd4,0x68,0x32,0x18,0x3c,0x8,0x64,0xc3,0xed,0x50,0x59,0x34,0x71,0xa7,0x3a,0x7,0xde,0x72,0xef,0x79,0x87,0x7b,0xde,0x3d,0xf,0xb6,0x84,0x71,0xbf,0xe0,0x38,0xce,0x23,0xe0,0x2d,0xf0,0x12,0xa8,0xe6,0xe5,0x6b,0xa0,0xf,0x7c,0xd6,0x5a,0x4f,0xff,0x29,0x60,0x99,0x16,0xfb,0x4f,0xf6,0x8f,0x81,0x56,0xb3,0x79,0xb4,0x7b,0x78,0xf8,0xa,0xc3,0xf8,0xd3,0x16,0x11,0xba,0xdd,0x73,0xc2,0xf0,0x6b,0xa,0xbc,0x9b,0x4c,0x26,0xed,0x34,0x4d,0xef,0xa,0x38,0x8e,0x73,0xbc,0xb7,0xf7,0xf8,0xcb,0xd9,0xd9,0xa7,0xe2,0xe2,0x7d,0x88,0x8,0x27,0x27,0xef,0xb9,0xb9,0xf9,0xf9,0x5a,0x6b,0xdd,0x2e,0x4,0xf2,0xb1,0x7f,0xf4,0x7a,0xbd,0x5d,0xc3,0x30,0xc8,0xb2,0x8c,0xf1,0x78,0x4c,0x14,0x45,0x0,0xb8,0xae,0x8b,0xe7,0x79,0x94,0xcb,0x65,0x44,0x84,0x46,0xa3,0x91,0x2,0x4f,0xb5,0xd6,0x53,0x13,0xa0,0x52,0xa9,0x7c,0x6c,0x36,0x8f,0x9e,0x1f,0x1c,0xd4,0xc8,0xb2,0x8c,0x4e,0xa7,0x43,0xab,0xd5,0x62,0x30,0x18,0x30,0x1c,0xe,0x19,0x8d,0x46,0xac,0x56,0x2b,0xea,0xf5,0x3a,0x96,0x65,0x21,0x52,0xda,0xb9,0xba,0xba,0x5c,0xce,0x66,0xb3,0x6f,0xeb,0xf1,0x2f,0xe2,0x38,0x16,0xad,0xb5,0x4,0x41,0x20,0x4a,0x29,0x1,0xee,0x1c,0xa5,0x94,0x4,0x41,0x20,0x5a,0x6b,0x89,0xe3,0x58,0x1c,0xc7,0xb9,0x0,0x28,0xe5,0xf6,0xaa,0x6b,0xdf,0x51,0x14,0x91,0x24,0xc9,0x86,0xff,0x24,0x49,0xa,0x4b,0x39,0xb7,0xfa,0xb7,0xc0,0x7f,0x63,0x2d,0x70,0x2d,0x22,0xc5,0x83,0xd9,0xb6,0xbd,0x41,0xb4,0x6d,0x1b,0xd7,0x75,0x8b,0x6d,0xe4,0xd9,0x28,0x4,0xfa,0xdd,0xee,0x39,0x0,0x9e,0xe7,0xe1,0xfb,0x3e,0x4a,0x29,0x4c,0xd3,0xc4,0x34,0x4d,0x94,0x52,0xf8,0xbe,0x8f,0xe7,0x79,0x0,0xe4,0xdc,0xfe,0x83,0xac,0x71,0xeb,0x20,0x99,0xeb,0xe6,0x62,0xb1,0xf8,0x6e,0x18,0x4c,0xc3,0x30,0x7c,0x21,0x52,0xda,0xa9,0xd5,0x9e,0x6d,0x44,0xf9,0xf4,0xf4,0x43,0x3a,0x9f,0xcf,0xdf,0xdc,0xde,0xfe,0x6a,0x2f,0x97,0xcb,0x87,0xf9,0x4c,0x5b,0xe3,0x37,0x57,0xdf,0xd7,0x8,0xe6,0x62,0x7d,0xab,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char radio_unchecked_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x3,0x1,0x4,0x1b,0x6,0x97,0xfc,0xdf,0x9c,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x1,0x9,0x49,0x44,0x41,0x54,0x38,0xcb,0xad,0x93,0xbd,0x72,0x82,0x40,0x14,0x85,0xf,0x68,0xa,0x9e,0x21,0x8d,0x8e,0x9,0xdb,0xc4,0xc7,0x48,0x41,0x43,0x2b,0xa3,0xad,0x69,0x32,0xc3,0xda,0xc7,0xa7,0x8,0x94,0xa1,0xd,0x68,0x4b,0xc3,0x5b,0xd8,0x5f,0x2d,0xe2,0x60,0xe8,0x99,0xa1,0xd8,0x82,0xc2,0x34,0x17,0x67,0x35,0x19,0x43,0x34,0xa7,0xbc,0x7b,0xee,0x37,0xf7,0x6f,0x81,0x2b,0x65,0x9c,0x6,0x84,0x10,0xb7,0x0,0x7c,0x0,0xe,0x0,0x9b,0xc3,0x6b,0x0,0x19,0x80,0x90,0x88,0x8a,0x1f,0x1,0xdd,0x4e,0x17,0x83,0xbb,0xc1,0x14,0x40,0xe0,0x79,0x13,0x6b,0x3c,0x1e,0x1d,0x81,0xe3,0x78,0x89,0xc5,0xe2,0x5d,0x1,0x90,0x79,0x9e,0x47,0x4a,0xa9,0x63,0x80,0x10,0x62,0xda,0xeb,0xf5,0xdf,0x82,0xe0,0xf5,0x6c,0xc9,0x52,0xce,0xb0,0xdd,0x7e,0x3c,0x11,0x51,0x74,0x0,0x70,0xd9,0x9b,0x34,0x4d,0xad,0x36,0x7d,0xbb,0xae,0xab,0x0,0xdc,0x13,0x51,0x61,0x72,0xcc,0xf7,0xbc,0x89,0xd5,0x76,0x70,0xec,0xf5,0x1,0xa0,0x1,0x38,0xa7,0x3d,0x9f,0x13,0x7b,0x1d,0x1d,0x60,0x5f,0xb0,0x41,0x5b,0x7,0x5c,0x2c,0x53,0xdb,0xf3,0x5f,0xb5,0xd6,0x1,0x59,0x1c,0x2f,0x5b,0x67,0xb2,0x37,0xd3,0x1,0x21,0x1f,0x49,0x2b,0xb1,0x37,0x3c,0x0,0xf8,0x3c,0xa5,0x94,0xb3,0x5f,0x93,0xd9,0x23,0x9b,0x93,0xee,0x34,0xf,0x55,0x55,0xad,0xc,0x3,0x45,0x92,0x24,0x8f,0xfb,0xbd,0x79,0x33,0x1c,0x3e,0x7c,0x2b,0x7b,0x3e,0x7f,0x51,0x65,0x59,0x3e,0xef,0x76,0x9f,0x51,0x5d,0xd7,0xff,0xf3,0x99,0xae,0xd6,0x17,0xf,0x97,0x66,0x8b,0x3d,0xf1,0x64,0x47,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -274,53 +279,68 @@ static const unsigned char reference_border_png[]={ }; +static const unsigned char scroll_bg_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x17,0x37,0x2c,0x8d,0x3d,0xc,0x64,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x3f,0x49,0x44,0x41,0x54,0x18,0x95,0xad,0x8e,0x31,0xa,0x0,0x20,0xc,0x3,0xaf,0xda,0x47,0xf4,0xe5,0xf6,0xb3,0x4a,0x5d,0x1c,0x54,0x50,0x17,0xf,0x42,0x96,0x24,0x44,0xcc,0x8c,0x1b,0x69,0x78,0x1,0x62,0x53,0x1,0x90,0xb1,0x10,0xb5,0xb6,0xa5,0xa9,0x9a,0x1,0x24,0xf1,0xe0,0x5f,0xc0,0x55,0x33,0xb3,0x0,0x9f,0x4f,0x1e,0xe9,0xf,0x1d,0xb,0x68,0x95,0x6b,0x4f,0xeb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char scroll_button_down_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x11,0x20,0xd,0xba,0x4e,0x71,0x52,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x8d,0x49,0x44,0x41,0x54,0x38,0xcb,0x9d,0x93,0xcf,0x4a,0x5b,0x41,0x14,0xc6,0x7f,0x13,0xae,0x12,0x11,0xb,0x66,0x93,0x40,0x56,0xd2,0x7,0x28,0x5d,0x74,0xa3,0x48,0x4b,0x9f,0xc2,0x75,0xa0,0x8f,0x21,0x6e,0x4,0x11,0x5c,0x64,0x2b,0x5,0xd7,0x7d,0x8a,0xd2,0xae,0xbb,0x28,0x7d,0x80,0xe2,0xaa,0xa0,0x88,0x51,0x6a,0xee,0x9c,0x33,0x73,0xe7,0x8f,0x8b,0xa4,0xf7,0xde,0x68,0x5a,0x8b,0x7,0x86,0x19,0x66,0xbe,0xef,0x3b,0x33,0xe7,0x3b,0x63,0x80,0x3c,0xec,0xf,0x78,0x4e,0xfc,0xba,0xbc,0xa0,0x18,0xf6,0x7,0xbc,0xdc,0xda,0xe2,0xfd,0xdb,0x77,0xbc,0xd8,0xd8,0x0,0xc,0xe4,0xc,0xe6,0x1,0x3a,0x3,0xc6,0x0,0x99,0xdf,0x77,0x77,0x7c,0xfe,0xfa,0x5,0x80,0x2,0x60,0x77,0x7b,0x7,0x80,0xeb,0xab,0xeb,0x3f,0xc8,0xd6,0xcc,0xa3,0xbd,0x95,0xee,0x2a,0xbb,0xdb,0x3b,0xfc,0x3c,0x3f,0x9f,0x9,0xf4,0x36,0x37,0xb9,0x99,0x4c,0xf0,0xde,0x35,0xd9,0xf3,0x22,0xbd,0xe1,0x1b,0x4c,0x7,0x7a,0xbd,0x5e,0x73,0x83,0x18,0x13,0x29,0x26,0x52,0x4a,0x2d,0xc6,0x92,0x27,0x0,0xe4,0x4c,0x8a,0x89,0x18,0x53,0x23,0x10,0x42,0x45,0x88,0x91,0x14,0xe3,0x52,0x6e,0x3b,0xc,0x10,0x62,0x24,0x84,0xaa,0x11,0x70,0xea,0xa8,0xbc,0xc7,0x7b,0xcf,0xde,0x87,0xd1,0x3f,0x5,0x3e,0x7d,0x3c,0x3,0x63,0x70,0xea,0x1a,0x1,0x75,0x8a,0x73,0xe,0xef,0xfd,0x93,0xd6,0x39,0xef,0xc9,0x73,0xe,0x40,0x7,0xc0,0x8a,0x45,0x44,0x10,0x11,0x4e,0x4f,0xc6,0x7f,0x25,0x9f,0x9e,0x8c,0x6b,0x9c,0x15,0xdb,0x8,0xc8,0xd4,0x22,0x62,0x51,0x55,0x44,0x85,0xf1,0xe1,0xd1,0x23,0xf2,0xf8,0xf0,0x8,0x51,0x99,0x61,0xc4,0x22,0xd3,0x96,0x80,0x55,0x41,0xd5,0xa1,0x4e,0xeb,0x71,0xbc,0x7f,0x50,0x93,0x8f,0xf7,0xf,0x16,0xce,0x54,0x1d,0x56,0x65,0x56,0xd4,0x61,0x7f,0x90,0xdf,0xbc,0x7a,0x8d,0xaa,0x10,0xaa,0xb0,0x58,0xee,0x65,0x36,0x2,0xc5,0x4a,0x41,0xb7,0xbb,0xc6,0xb7,0x1f,0xdf,0xe7,0x45,0x14,0xc5,0x57,0x9e,0x18,0x22,0xff,0xe3,0x63,0xca,0x9,0xb2,0x69,0x5c,0x10,0xef,0x8,0x55,0xd5,0x34,0xd2,0x13,0xd1,0x49,0x89,0x38,0x4f,0x54,0x0,0x5c,0x5c,0x5d,0xb2,0xde,0x5d,0x23,0xb7,0xd3,0xe7,0x25,0x1d,0x54,0x2f,0xd,0xe5,0xed,0xa4,0x16,0x18,0x4d,0xcb,0xf2,0x6c,0x5a,0x96,0xcf,0xf9,0xd1,0xa3,0x7b,0xce,0xd7,0xea,0xb0,0xa,0xcf,0xbd,0x5b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x1f,0x9,0x3d,0x3c,0xb0,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xa3,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x93,0x31,0xa,0x2,0x31,0x10,0x45,0x7f,0xc2,0x14,0x3,0x6,0xab,0xad,0x32,0x57,0x50,0xbc,0x87,0x88,0x97,0x11,0xf1,0xc,0x22,0x1e,0x33,0x5b,0xa5,0xb1,0x59,0xa7,0x18,0x58,0x5b,0x89,0x9b,0x95,0x88,0xa0,0xbf,0x4c,0xfe,0xfb,0xf9,0x3,0x13,0xb7,0x5e,0x6d,0x58,0xa2,0xc,0x44,0xe4,0xd0,0x20,0x33,0x1b,0x53,0x9f,0x16,0x24,0x51,0xee,0xaa,0xa,0x55,0x6d,0xe1,0xc1,0xcc,0x4e,0xa2,0xc,0x9e,0x88,0x9a,0x61,0x0,0x50,0x55,0x10,0x11,0x7c,0x33,0x59,0xe8,0xf7,0x1,0x54,0x1e,0x5c,0xae,0xe7,0x59,0xe0,0x78,0x38,0x7d,0xb7,0xc1,0x4b,0x40,0xf9,0xc2,0xbb,0xbb,0xc9,0x6,0x53,0xc6,0x5a,0x70,0x75,0x84,0x67,0x60,0xae,0x95,0xdb,0x6d,0xf7,0x63,0xce,0xb9,0x6a,0x98,0x53,0xd7,0x75,0x7f,0xb0,0x7,0xde,0xcc,0xc0,0xcc,0xcd,0x20,0x33,0xc3,0xcc,0x40,0xa9,0x4f,0x4b,0x89,0x72,0xb,0x21,0x7c,0xf2,0x9d,0xe5,0x1,0xd1,0x91,0x38,0x2b,0x1d,0x55,0xcb,0xf6,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_down_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x11,0x1f,0x1f,0x11,0x29,0x2a,0x26,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x84,0x49,0x44,0x41,0x54,0x38,0xcb,0x9d,0x93,0xcf,0x4a,0x6b,0x31,0x10,0x87,0xbf,0x94,0xfa,0x7,0xa1,0x82,0xdd,0xea,0xc2,0x9d,0xfa,0x16,0x45,0x10,0x1f,0xc0,0xbd,0xa0,0x2f,0x71,0x71,0x23,0x72,0x17,0x82,0xb8,0x70,0xd1,0xb5,0xa,0xee,0x7d,0x0,0xf1,0x41,0xd4,0x9d,0xe0,0x15,0x17,0x52,0x2f,0x9c,0x43,0x32,0x49,0xce,0x49,0x72,0x17,0xad,0x4d,0x6b,0x7b,0x55,0x1c,0x8,0x9,0x99,0xf9,0x7d,0x33,0xc9,0x24,0xa,0x48,0xab,0xcb,0x2b,0xfc,0xc4,0x1e,0x9f,0xff,0xd0,0x5c,0x5d,0x5e,0x61,0x63,0x6d,0x9d,0xed,0xad,0x2d,0x16,0x5b,0x2d,0x40,0x41,0x4a,0xa0,0x3e,0x44,0x27,0x40,0x29,0x20,0x51,0x94,0x25,0x37,0xb7,0xb7,0x0,0x34,0x1,0x36,0x3b,0x1d,0x0,0x7a,0xaf,0xbd,0xf7,0xc8,0x91,0x99,0x89,0xbd,0x99,0xf9,0x59,0x36,0x3b,0x1d,0xee,0x1e,0xee,0xfb,0x80,0xf6,0xd2,0x12,0x7f,0xdf,0xde,0xf0,0xde,0xe5,0xec,0x69,0x5c,0x9e,0xf5,0xa,0xd5,0x80,0x76,0xbb,0x9d,0x2b,0x8,0x21,0x12,0x43,0x24,0xc6,0x38,0xa2,0x98,0x72,0x4,0x80,0x94,0x88,0x21,0x12,0x42,0xcc,0x80,0xba,0xae,0xa8,0x43,0x20,0x86,0x30,0x55,0x3b,0x6a,0xa,0xa8,0x43,0xa0,0xae,0xab,0xc,0x70,0xd6,0x51,0x79,0x8f,0x77,0x8e,0x9d,0xbd,0xdd,0x4f,0x1,0xd7,0x97,0x57,0xa0,0x14,0xce,0xba,0xc,0xb0,0xce,0xe2,0xac,0xc5,0x7b,0xff,0x65,0xeb,0x9c,0xf7,0x24,0xc0,0xce,0xcf,0x1,0xd0,0x0,0x30,0x62,0x30,0x46,0x30,0xc6,0x70,0x7e,0xd6,0xfd,0xaf,0xf8,0xfc,0xac,0x8b,0x31,0x83,0x58,0x31,0x19,0x20,0xa5,0x46,0x8c,0x46,0xa4,0xef,0xe8,0x1e,0x9f,0x4c,0x88,0xbb,0xc7,0x27,0x18,0x31,0x88,0x48,0x3f,0xb6,0xd4,0x19,0xa0,0xc5,0x20,0x62,0x11,0x2b,0xc3,0x71,0x7a,0x78,0x34,0x14,0x9f,0x1e,0x1e,0x8d,0xf9,0x44,0x2c,0x7a,0x50,0x41,0x13,0x40,0x6b,0x83,0x38,0x4b,0x55,0x55,0x63,0xd7,0xfd,0xfb,0xd7,0xc1,0x64,0x1b,0x81,0x30,0x13,0x41,0x37,0x32,0x40,0xb4,0xe0,0xbc,0x23,0xd4,0x35,0xdf,0xe9,0x63,0x8c,0x11,0x92,0xca,0x0,0xe3,0x2c,0x95,0xf7,0xf9,0x21,0x7d,0x61,0x8d,0x10,0x9,0x83,0x44,0x4d,0x80,0xa7,0x97,0x67,0x5a,0xb,0xb,0xa4,0xd1,0xf4,0x69,0xca,0xb,0x1a,0x2e,0x15,0x65,0xef,0x75,0x8,0xd8,0x2f,0xca,0xe2,0xa2,0x28,0x8b,0x9f,0xfc,0xe8,0xfd,0x7f,0xcd,0x23,0xeb,0x93,0x35,0xff,0xc7,0x89,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x1a,0x0,0xaf,0x18,0x62,0x86,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x9c,0x49,0x44,0x41,0x54,0x38,0x8d,0xc5,0x93,0x41,0xa,0x2,0x31,0xc,0x45,0x7f,0x87,0x6,0x21,0x5,0xe7,0x6,0x2e,0x9a,0x63,0x88,0x78,0x30,0x11,0x4,0xf1,0x98,0x9d,0x4b,0x48,0xa3,0x90,0x85,0x6e,0xb5,0xce,0x8c,0xad,0xa,0xfe,0x65,0xd2,0xf7,0xf3,0x53,0x88,0xdb,0xac,0xb7,0xb,0x89,0x72,0x21,0x22,0x87,0x6,0x99,0xd9,0x2d,0xd,0x69,0xe9,0x25,0xca,0x55,0x55,0x91,0x55,0x5b,0x78,0x4,0x66,0x27,0x51,0xce,0x1d,0x11,0x35,0xc3,0x0,0x90,0x55,0x41,0x44,0xe8,0x9a,0xc9,0x42,0xff,0x37,0xf0,0x65,0xe1,0x78,0x3a,0xcc,0x2,0xfb,0xdd,0x73,0xff,0xf7,0x2b,0x94,0x13,0xde,0xf5,0x46,0x13,0x8c,0x3d,0x9c,0x32,0x9e,0x5c,0xe1,0x11,0x98,0x4b,0xf5,0xf2,0x89,0x35,0x53,0xab,0x12,0xd4,0xea,0x7b,0x3,0x33,0x43,0x60,0x6e,0x6,0x3,0x33,0xcc,0xc,0x3e,0xd,0x89,0x25,0x4a,0xee,0xfb,0xfe,0x93,0x73,0x5e,0xdd,0x1,0xb6,0x6d,0x35,0xa4,0xf0,0x42,0xdf,0x17,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_left_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x2d,0x0,0x31,0x39,0x29,0xd6,0x70,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0xe,0x16,0x1f,0x39,0xa4,0x3d,0x2e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x47,0x49,0x44,0x41,0x54,0x38,0xcb,0x5d,0x93,0x51,0x4b,0x54,0x51,0x10,0xc7,0x7f,0x77,0x77,0x75,0x33,0xd7,0x5d,0x64,0xa3,0x56,0x83,0x50,0xb1,0xd0,0xd2,0x90,0xa,0xa1,0x97,0x9e,0xfb,0x8,0xe1,0x37,0xd8,0x87,0x90,0x1e,0x12,0xd3,0xd5,0xc2,0x82,0x88,0x5e,0x3,0x3f,0x41,0xdf,0xa1,0xcf,0x10,0x18,0x91,0x41,0x11,0xa2,0x66,0x65,0xab,0xbb,0xa6,0x5e,0x77,0xb5,0xbb,0x7b,0x66,0xa6,0x87,0x7b,0xf7,0xb6,0x3a,0x70,0x38,0x87,0x73,0x66,0xe6,0x3f,0xf3,0x9f,0xf3,0xf7,0x68,0xb3,0xa1,0x81,0xe1,0xfb,0x40,0x11,0xb8,0xd,0x5c,0xe6,0xb4,0xfd,0x2,0x56,0x80,0xe5,0xf5,0xcd,0xb5,0x77,0xad,0x4b,0x2f,0xa,0xcc,0x1,0x2f,0xb,0x85,0xfe,0xe2,0xd8,0xe8,0x38,0xbd,0xb9,0x5e,0x3a,0xd3,0x69,0x54,0xc,0x80,0x44,0xd2,0xa3,0x11,0x4,0xec,0x1f,0xee,0xf3,0xf9,0xcb,0x2a,0xe5,0xf2,0xf6,0x32,0xf0,0x64,0x7d,0x73,0xed,0x30,0x15,0x25,0x7a,0x31,0x71,0xf3,0x56,0x71,0xf0,0xca,0x35,0x2a,0x95,0xa,0x1b,0x7b,0x5b,0x4,0x41,0xf3,0x14,0x7c,0x3a,0xdd,0xc1,0xb9,0xae,0x2e,0xee,0xde,0xb9,0xc7,0xc6,0xd6,0xb7,0xe2,0xc7,0x4f,0x1f,0x4,0x78,0x98,0x1c,0x1a,0x18,0x9e,0xea,0x2b,0xf4,0xbf,0xba,0x3a,0x38,0xc2,0x8f,0xef,0x3f,0x39,0xae,0x1f,0xd3,0x14,0x87,0x61,0x98,0x81,0x99,0x1,0x86,0x6b,0xa,0x27,0x7f,0x4f,0xf0,0xf,0x7c,0xfa,0xfa,0xfa,0xa9,0xd5,0xfd,0xc9,0x8e,0x8e,0xce,0xaf,0x9,0xa0,0x78,0x7d,0x64,0x8c,0xdd,0x72,0x95,0xa0,0x11,0x20,0x26,0xa8,0x2a,0x2a,0x8a,0x9a,0x30,0x53,0x9a,0xe6,0xf1,0xfc,0x74,0x78,0x2f,0x4a,0xd0,0x8,0xd8,0x2d,0x57,0xb9,0x31,0x3a,0xe,0x50,0x4c,0x0,0xe3,0x22,0x42,0xad,0x5e,0x43,0x4d,0x50,0x15,0x54,0x4,0x35,0x65,0xb6,0xf4,0x88,0xa8,0xc,0x44,0x25,0x7a,0x57,0x6a,0xf5,0x23,0x44,0x4,0x60,0x22,0x5,0xe4,0x9c,0x38,0xd4,0x4,0xc2,0x6a,0xc1,0x33,0xe6,0x17,0x67,0xb0,0xe8,0xc,0x1e,0xa6,0x82,0xb5,0x78,0x37,0xc3,0x89,0x3,0xc8,0xa5,0x0,0xc4,0x35,0x11,0x15,0x3c,0xb,0xe3,0x17,0x96,0x66,0x23,0xe7,0x10,0x1d,0x40,0x55,0x63,0x42,0x2d,0x8a,0x1,0x48,0x1,0x34,0x9d,0x43,0x55,0xf0,0xa2,0x47,0x33,0x8b,0xcf,0x21,0x66,0xd8,0x42,0xbb,0x35,0x9d,0xb,0x47,0xc,0xe0,0x9c,0x43,0x4d,0x11,0x15,0x4c,0x95,0x67,0xa5,0xe7,0x58,0xdc,0x8f,0x61,0x18,0xaa,0x82,0xa9,0xc4,0xbb,0x6b,0x4b,0x70,0xe8,0x9c,0x43,0x45,0x30,0x8b,0x88,0x32,0x61,0x71,0x6e,0x9,0x33,0x8b,0x97,0xaa,0x22,0xaa,0xa8,0xa,0xa2,0xda,0x4a,0x50,0x4b,0x0,0xab,0xce,0x35,0x51,0x5c,0xec,0xa0,0x12,0xee,0xb,0x73,0x4f,0x23,0xfc,0xb0,0x82,0xd6,0x14,0x14,0x87,0xb,0x39,0x58,0xf1,0x86,0x6,0x86,0xa7,0x72,0xb9,0xdc,0xdb,0x8b,0xf9,0x4b,0xf8,0xbe,0x8f,0x47,0x22,0xfa,0xe0,0x6d,0x8c,0x79,0x5e,0x4c,0xa6,0xa1,0x64,0xb3,0x59,0x76,0xaa,0x65,0x7c,0xdf,0x7f,0x90,0xdc,0x3f,0xf8,0xb3,0x7a,0xbe,0xab,0xfb,0x42,0x3a,0x9d,0x9e,0xcc,0x74,0x67,0x68,0x48,0x23,0xea,0x33,0x42,0x8e,0x26,0x61,0x9e,0xe0,0x25,0x3d,0x7a,0x32,0x3d,0xd4,0x4f,0xea,0xec,0xed,0x55,0xdf,0xac,0x6f,0xae,0xbd,0x6e,0x69,0xa1,0xf4,0xbb,0xbc,0x9d,0xec,0xc9,0x64,0x8b,0xf9,0x7c,0x1e,0x2f,0x91,0xf8,0xaf,0xb4,0xb6,0x69,0x98,0x2a,0x3b,0x95,0x1d,0x8e,0x6a,0xfe,0x32,0x50,0x6a,0xf7,0x39,0x2b,0xe7,0x49,0xa0,0x70,0x46,0xce,0x65,0xe0,0xfd,0x59,0x39,0xff,0x3,0xf4,0x94,0x88,0x15,0xb6,0xb0,0x66,0x34,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x39,0xdb,0x30,0xb9,0x4d,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xbb,0x49,0x44,0x41,0x54,0x38,0x8d,0xad,0x93,0x3d,0xe,0x82,0x40,0x10,0x85,0x1f,0x64,0x8a,0x49,0x24,0x56,0x54,0x3b,0x57,0xd0,0x78,0xf,0x63,0x3c,0x8e,0xbf,0x7,0x50,0x44,0x8e,0x9,0x15,0x8d,0xd,0x4e,0x31,0xc9,0x5a,0x61,0xa1,0x22,0x2c,0xfa,0x92,0xa9,0x36,0xdf,0xb7,0x6f,0x93,0x9d,0x68,0x3e,0x5b,0xb0,0x38,0x69,0x88,0x28,0x42,0x40,0xcc,0xcc,0x97,0x55,0x39,0x21,0x71,0x72,0x57,0x55,0xa8,0x6a,0x8,0xf,0x66,0x8e,0xc4,0x49,0x13,0x13,0x51,0x30,0xc,0x0,0xaa,0xa,0x22,0x42,0x1c,0x4c,0xbe,0xa4,0x57,0x90,0x17,0x19,0xf2,0x22,0xeb,0x3c,0xa7,0x6f,0xf0,0xe5,0x7a,0x86,0xf7,0x7e,0x5c,0x83,0x2c,0x3f,0xf5,0x95,0xeb,0x6e,0xd0,0xc2,0x7d,0xb7,0x77,0xa,0x86,0x80,0x6d,0x3e,0x3e,0x61,0xb7,0x39,0xfc,0x26,0x68,0x25,0xde,0xfb,0xe7,0x4,0xb,0x0,0x60,0xbf,0x3d,0xf6,0xa,0xa2,0xd5,0x72,0xed,0xeb,0xba,0x1e,0xd2,0xf6,0x2d,0x69,0x9a,0xfe,0xe1,0x27,0x9a,0x19,0x98,0x39,0x18,0x64,0x66,0x98,0x19,0xa8,0xac,0xca,0xa9,0x38,0xb9,0x25,0x49,0x32,0x66,0x9d,0xe5,0x1,0x80,0xd0,0x51,0x2e,0x9,0x63,0x6e,0xe0,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_left_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x2d,0x0,0x31,0x39,0x29,0xd6,0x70,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0xe,0x16,0x30,0x92,0x75,0x0,0x77,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x5a,0x49,0x44,0x41,0x54,0x38,0xcb,0x5d,0x93,0x5d,0x4b,0x94,0x51,0x10,0xc7,0x7f,0xcf,0xb3,0x5b,0xbe,0x90,0xee,0x9a,0xa1,0xd5,0x96,0x18,0x44,0x96,0xac,0xf8,0x6,0x46,0x75,0x13,0x74,0xd3,0x47,0x8,0xaf,0x25,0xd8,0xc4,0xb,0x8d,0x2e,0xa,0xaf,0xca,0x30,0xa9,0xee,0x2,0x3f,0x41,0xdf,0xa1,0x2f,0x10,0x51,0xa0,0x10,0x8a,0x28,0x44,0xf8,0xd2,0xd2,0xea,0x52,0xeb,0xfa,0xa8,0xed,0xee,0x73,0x66,0xa6,0x8b,0x67,0x5d,0x57,0x7,0xe,0x7,0xe6,0xcc,0xfc,0x67,0xe6,0x3f,0xe7,0xef,0x51,0x67,0xbd,0x3d,0xe9,0x87,0x40,0x6,0x18,0x6,0x52,0x9c,0xb4,0x2c,0xb0,0x0,0xcc,0xaf,0xac,0x2d,0x7f,0x3a,0x72,0x7a,0xd5,0xc4,0x4,0x30,0x7b,0xb5,0xab,0x3b,0x33,0xd4,0x3f,0x44,0x5b,0xa2,0x8d,0xb3,0xd,0xd,0xa8,0x1a,0x0,0xbe,0xef,0x51,0x29,0x97,0x29,0x14,0xb,0x2c,0x7e,0x5f,0x64,0x6b,0x73,0x7d,0x1e,0x78,0xbe,0xb2,0xb6,0x5c,0x8c,0x57,0x81,0x66,0xee,0xdc,0xbe,0x97,0xb9,0x7e,0xed,0x26,0xdb,0xdb,0x79,0xfe,0xee,0x6c,0x50,0x2a,0x85,0x27,0xca,0x37,0x36,0x9e,0xa1,0xa9,0xb9,0x99,0xfb,0x77,0x1f,0xf0,0xe3,0xd2,0x6a,0xe6,0xcb,0xd7,0xcf,0x2,0x4c,0xc4,0x7a,0x7b,0xd2,0xa3,0x5d,0x5d,0xdd,0x73,0xb7,0x6e,0xa4,0xd9,0xf8,0xb9,0xc5,0xc1,0xfe,0x1,0xa1,0xb,0x31,0x14,0x33,0xc3,0xcc,0x0,0xc3,0x85,0x8e,0xc3,0x7f,0x87,0x14,0xb,0x7b,0xa4,0xae,0xa4,0x8,0xf6,0xf7,0x46,0x1a,0xce,0x36,0xac,0xfa,0x40,0x66,0xa0,0x6f,0x90,0x5c,0x36,0x4f,0xa9,0x5c,0x42,0x4c,0x50,0x55,0x54,0x14,0x35,0x61,0x7c,0x6a,0x8c,0x27,0x93,0x63,0x91,0x5f,0x94,0x52,0xb9,0x44,0x2e,0x9b,0x67,0xb0,0x7f,0x18,0x20,0xe3,0x3,0x7d,0x22,0x42,0x10,0x4,0xa8,0xa,0x2a,0x82,0xba,0x8,0x64,0x62,0xea,0x31,0x98,0x81,0x19,0x4e,0xa4,0xfa,0xae,0x4,0xc1,0x1e,0x22,0x2,0x30,0x10,0x7,0x12,0xa1,0x38,0xc4,0x1c,0x44,0xdd,0x82,0x67,0x4c,0x3e,0x1b,0xaf,0xb5,0xf,0x1e,0xa6,0xe,0x39,0xe2,0xdd,0x8c,0x50,0x1c,0x40,0x22,0xe,0x20,0x61,0x5,0x51,0xc1,0xd3,0x28,0xfc,0xe9,0x8b,0x9,0x22,0xfe,0xa3,0xea,0x0,0xaa,0x5a,0x23,0xd4,0xaa,0x39,0x0,0x71,0x80,0x8a,0x73,0x88,0x8,0x3e,0xa0,0x80,0x99,0xe1,0x55,0x3,0xa3,0x9a,0xd1,0x8,0xf5,0x56,0x71,0x2e,0x5a,0x31,0x80,0xb,0x43,0xd4,0x4,0xa7,0xe,0x53,0x61,0x6e,0xe6,0xfd,0xf1,0x6,0xcc,0x50,0x33,0x54,0x1d,0xa6,0xae,0x76,0xbb,0x30,0xac,0x1,0x14,0x43,0xe7,0x50,0x11,0xcc,0x4,0xad,0x9e,0xd9,0x57,0xef,0xa0,0x6e,0x8d,0xaa,0x8a,0xa8,0xa2,0x2a,0x88,0x2a,0x61,0xd4,0xc1,0xbe,0xf,0x2c,0xb9,0xb0,0x82,0x10,0xe2,0x44,0x10,0x71,0x88,0x8b,0xee,0xd7,0x2f,0xdf,0x60,0x44,0x20,0x22,0xe,0xd1,0x68,0x54,0x21,0xc4,0x45,0x1c,0x2c,0x78,0xbd,0x3d,0xe9,0xd1,0xf3,0xed,0xed,0x1f,0x2f,0x77,0xa4,0xd8,0xdd,0x2d,0xe0,0x11,0xab,0x7e,0xf0,0x3a,0xc6,0x3c,0xaf,0x46,0xa6,0x21,0x24,0x93,0x6d,0x64,0x73,0x5b,0x14,0xa,0x85,0x47,0xb1,0xfc,0x9f,0x9d,0xa5,0x73,0xcd,0x2d,0x17,0x1a,0x9b,0x9b,0x46,0x5a,0x5b,0x12,0x94,0x5d,0x29,0x9a,0x53,0xc,0x43,0x11,0x34,0x1a,0xc5,0x13,0xbc,0x98,0x47,0xa2,0x35,0x49,0x70,0x18,0xb0,0xbd,0x9d,0xfb,0xb0,0xb2,0xb6,0xfc,0xf6,0x48,0xb,0xd3,0x9b,0x9b,0xeb,0xb1,0x64,0xa2,0x2d,0xd3,0xd1,0xd9,0x89,0xef,0xfb,0xc7,0x4a,0xab,0xdb,0x86,0xaa,0x92,0xfd,0xfd,0x8b,0xdd,0x62,0x61,0x1e,0x98,0xae,0x8f,0x39,0x2d,0xe7,0x11,0xe0,0xe2,0x29,0x39,0xe7,0x80,0x6f,0xa7,0xe5,0xfc,0x1f,0xa8,0xd,0x8b,0xe8,0xd0,0x6f,0x71,0x8b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x35,0xd2,0x86,0xf5,0x66,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc3,0x49,0x44,0x41,0x54,0x38,0x8d,0x9d,0x93,0x4d,0xa,0x83,0x30,0x10,0x85,0x5f,0xc4,0xa1,0x10,0xa1,0xde,0xa0,0xb,0x73,0x8c,0x52,0x7a,0x2d,0xa9,0x68,0x5d,0xb4,0xf6,0xef,0x8c,0xf1,0x12,0xc5,0xb4,0x30,0x8b,0xe9,0x4e,0x8a,0x68,0x34,0xbe,0x6d,0x78,0xdf,0xbc,0x99,0x47,0xd4,0x61,0x7f,0xdc,0x98,0xcc,0x7c,0x88,0x48,0x21,0x40,0xcc,0x2c,0xb6,0xb5,0xdb,0xd8,0x64,0xe6,0xeb,0x9c,0x43,0xe7,0x5c,0x88,0x1f,0x89,0xd6,0xca,0x64,0xe6,0x1d,0x11,0x51,0xb0,0x19,0x0,0x3a,0xe7,0x40,0x44,0x88,0x82,0x9d,0x3,0xcd,0x2,0xaa,0xba,0x40,0x55,0x17,0x93,0xef,0xb1,0xcf,0x5c,0x9e,0x4f,0x10,0x11,0xef,0x80,0x49,0x40,0x51,0xe6,0x10,0x11,0x88,0x8,0x94,0x9a,0x2e,0x68,0x14,0x50,0x94,0x39,0x0,0xf4,0x80,0xe0,0x4,0x43,0x93,0xf,0x32,0x7a,0xc4,0xe6,0xf2,0xe8,0xa7,0xcf,0xa5,0x98,0x6c,0xe1,0x76,0x7d,0x2e,0x5a,0xc1,0x5b,0xe3,0xbd,0x79,0x1,0xf0,0xaf,0xe0,0xad,0xf1,0x1f,0xb2,0x2a,0xc1,0x12,0x45,0xcc,0x8c,0x44,0xeb,0x60,0x63,0xa2,0x35,0x98,0x19,0xb1,0x6d,0xad,0x36,0x99,0xe9,0xd2,0x34,0x5d,0xf3,0x9d,0x77,0x3f,0xd3,0x69,0x5f,0xde,0x59,0x55,0x4f,0x95,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_right_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x2d,0x0,0x31,0x39,0x29,0xd6,0x70,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0xe,0x16,0x14,0xae,0x76,0xe4,0xa6,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x43,0x49,0x44,0x41,0x54,0x38,0xcb,0x5d,0x93,0xdf,0x4a,0x54,0x51,0x14,0x87,0xbf,0x73,0x46,0x9d,0xcc,0xd1,0x41,0x26,0x6a,0x34,0x8,0x15,0xb,0x2d,0xd,0xa9,0x10,0xba,0xe9,0xba,0x47,0x8,0xdf,0x60,0x2e,0xa2,0x82,0x90,0xb4,0x29,0x85,0x84,0x88,0x6e,0x3,0x9f,0xa0,0x77,0xe8,0x19,0x2,0x23,0x32,0x28,0x42,0xd4,0xac,0x6c,0x74,0xc6,0xd4,0xe3,0x8c,0x36,0x33,0x7b,0xad,0xd5,0xc5,0x3e,0xf3,0x27,0x37,0x1c,0x38,0xac,0xb3,0xd7,0xf7,0xfb,0xad,0xb5,0xce,0xa,0x68,0x3b,0x23,0x43,0xa3,0x77,0x81,0x1c,0x70,0x13,0xb8,0xc8,0xff,0xe7,0x17,0xb0,0x2,0x2c,0xaf,0x6f,0xae,0xbd,0x6b,0x4,0x83,0x38,0x31,0xd,0xbc,0xcc,0x66,0x7,0x73,0x13,0xe3,0x93,0xf4,0xa7,0xfb,0xe9,0x4a,0x26,0x51,0x31,0x0,0xc2,0x44,0x40,0xad,0x5a,0x65,0xff,0x70,0x9f,0xcf,0x5f,0x56,0x29,0x14,0xb6,0x97,0x81,0xb9,0xf5,0xcd,0xb5,0xc3,0x8e,0x18,0xb4,0x34,0x75,0xfd,0x46,0x6e,0xf8,0xd2,0x15,0x8a,0xc5,0x22,0x1b,0x7b,0x5b,0x54,0xab,0xf5,0xff,0xe4,0x93,0xc9,0x4e,0xce,0x74,0x77,0x73,0xfb,0xd6,0x1d,0x36,0xb6,0xbe,0xe5,0x3e,0x7e,0xfa,0x20,0xc0,0xfd,0xc4,0xc8,0xd0,0xe8,0xcc,0x40,0x76,0xf0,0xd5,0xe5,0xe1,0x31,0x7e,0x7c,0xff,0xc9,0x71,0xe5,0x98,0xba,0x38,0xc,0xc3,0xc,0xcc,0xc,0x30,0x5c,0x5d,0x38,0xf9,0x7b,0x42,0x74,0x10,0x31,0x30,0x30,0x48,0xb9,0x12,0x4d,0x77,0x76,0x76,0x7d,0xd,0x81,0xdc,0xd5,0xb1,0x9,0x76,0xb,0x25,0xaa,0xb5,0x2a,0x62,0x82,0xaa,0x32,0xfb,0xf4,0x21,0xb3,0xf9,0x7,0xa8,0x9,0xa2,0xe2,0xe3,0xa2,0x54,0x6b,0x55,0x76,0xb,0x25,0xae,0x8d,0x4f,0x2,0xe4,0x42,0x60,0x52,0x44,0x28,0x57,0xca,0xa8,0x9,0xaa,0x82,0x8a,0x80,0x1,0x66,0x3c,0xc9,0x3f,0x42,0xd5,0x43,0x34,0x86,0x97,0x2b,0x47,0x88,0x8,0xc0,0x54,0x8,0xa4,0x9d,0xb8,0xe6,0x47,0x15,0x45,0x4d,0x30,0x53,0x5f,0x2,0xc6,0xdc,0xf3,0xc7,0x98,0xc6,0xf0,0x58,0xc4,0x89,0x3,0x48,0x87,0x0,0xe2,0xea,0x5e,0x41,0x62,0x25,0x55,0x6f,0x0,0xc3,0xcc,0x3f,0xf3,0xb,0xb3,0x5e,0x40,0x5,0x31,0x45,0x9c,0x6f,0x72,0x7,0x40,0xdd,0x39,0x54,0x85,0x0,0xef,0xbc,0x61,0xdf,0x9a,0xb3,0xf6,0xef,0xa2,0xd2,0x9c,0x4a,0xdd,0xb9,0x16,0xc0,0x39,0x87,0x9a,0x82,0x19,0x41,0x7c,0xbd,0x95,0xee,0x79,0x8b,0xf9,0xa5,0xa6,0x40,0x10,0xe7,0x34,0x0,0x87,0xce,0xb9,0xb4,0x8a,0x10,0x4,0x86,0x35,0x0,0xd6,0x2,0x2c,0xe4,0x5f,0xd0,0xe2,0x79,0x44,0xc,0x28,0x87,0xc0,0xaa,0x73,0x75,0x14,0x87,0xc4,0x35,0xaa,0xa8,0xaf,0x1d,0xe3,0xd9,0xfc,0xa2,0x8f,0xb5,0x4d,0x41,0x71,0x38,0xdf,0x83,0x95,0x60,0x64,0x68,0x74,0x26,0x9d,0x4e,0xbf,0x3d,0x9f,0xb9,0x40,0x14,0x45,0x4,0x84,0xf1,0xf,0xde,0x2e,0x18,0x40,0xec,0xc8,0x50,0xfa,0xfa,0xfa,0xd8,0x29,0x15,0x88,0xa2,0xe8,0x5e,0x62,0xff,0xe0,0xcf,0xea,0xd9,0xee,0x9e,0x73,0xc9,0x64,0x72,0x3a,0xd5,0x93,0xa2,0x26,0x35,0x54,0x5,0x53,0xef,0x40,0x31,0xdf,0xd0,0x40,0x8,0x12,0x1,0xbd,0xa9,0x5e,0x2a,0x27,0x15,0xf6,0xf6,0x4a,0x6f,0xd6,0x37,0xd7,0x5e,0x37,0x76,0x21,0xff,0xbb,0xb0,0x9d,0xe8,0x4d,0xf5,0xe5,0x32,0x99,0xc,0x41,0x18,0xb6,0x36,0x8d,0x56,0xf9,0xa6,0xca,0x4e,0x71,0x87,0xa3,0x72,0xb4,0xc,0xe4,0xdb,0xef,0x9c,0x5e,0xe7,0x69,0x20,0x7b,0x6a,0x9d,0xb,0xc0,0xfb,0xd3,0xeb,0xfc,0xf,0xed,0x2d,0x85,0x24,0xfc,0x1,0xe2,0x46,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x31,0xd5,0xeb,0x31,0x7f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xbb,0x49,0x44,0x41,0x54,0x38,0x8d,0xad,0x93,0x3d,0xe,0x82,0x40,0x10,0x85,0x1f,0x64,0x8a,0x49,0x24,0x56,0x54,0x3b,0x57,0xd0,0x78,0xf,0x63,0x3c,0x8e,0xbf,0x7,0x50,0x44,0x8e,0x9,0x15,0x8d,0xd,0x4e,0x31,0x61,0xad,0xb0,0x30,0x82,0x2c,0xf1,0x25,0x9b,0x6c,0xf1,0xbe,0x97,0x37,0x99,0xdd,0x68,0xb9,0x58,0xb1,0x38,0x69,0x88,0x28,0x42,0x80,0xcc,0xcc,0x97,0x55,0x39,0x23,0x71,0xf2,0x54,0x55,0xa8,0x6a,0x8,0xf,0x66,0x8e,0xc4,0x49,0x13,0x13,0x51,0x30,0xc,0x0,0xaa,0xa,0x22,0x42,0x1c,0x4c,0x7e,0xa8,0x37,0x20,0x2f,0x32,0xe4,0x45,0x36,0x3d,0x0,0x0,0xbc,0xf7,0xb8,0xdd,0xaf,0xd3,0x2,0xda,0xb6,0x7d,0xdf,0x87,0x42,0x7e,0x36,0xe8,0x4e,0x96,0x5f,0xbe,0x7a,0x68,0x8,0x1e,0xa3,0xd1,0x5b,0x38,0xec,0x4e,0xd3,0x1b,0x1c,0xf7,0xe7,0xf0,0x6,0xdd,0xec,0x43,0x30,0x0,0x44,0x9b,0xf5,0xd6,0xd7,0x75,0x3d,0x68,0xea,0x53,0x9a,0xa6,0x7f,0x78,0x89,0x66,0x6,0x66,0xe,0x6,0x99,0x19,0x66,0x6,0x2a,0xab,0x72,0x2e,0x4e,0x1e,0x49,0x92,0x4c,0xf9,0xce,0xf2,0x2,0x3d,0xd2,0x54,0x2c,0x85,0x2c,0xaa,0x56,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_right_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x2d,0x0,0x31,0x39,0x29,0xd6,0x70,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0xe,0x17,0x3,0x34,0xbe,0x50,0x20,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x58,0x49,0x44,0x41,0x54,0x38,0xcb,0x5d,0x93,0x5d,0x4b,0x54,0x51,0x14,0x86,0x9f,0x73,0xc6,0x1c,0x1d,0xd2,0xd1,0xc,0xad,0x2c,0x31,0x88,0x2c,0x51,0xfc,0x2,0xa3,0x8f,0x8b,0xa0,0x9b,0x7e,0x42,0x78,0x5d,0xd1,0x20,0x46,0x49,0x4,0x81,0x57,0x91,0x7d,0x49,0x5d,0x5,0xfe,0x82,0xfe,0x43,0x7f,0x20,0xa2,0x40,0x21,0x14,0x51,0x88,0xf0,0xa3,0xa1,0xd1,0xa1,0xc6,0xf1,0xa8,0xcd,0xcc,0xd9,0x6b,0xad,0x2e,0xce,0xcc,0x38,0xba,0x6f,0x36,0xac,0xbd,0xde,0xf7,0x5d,0x6b,0xed,0xf5,0x7a,0xd4,0x9c,0xde,0x9e,0xbe,0xdb,0x40,0xa,0x18,0x1,0x3a,0x39,0x7c,0xd2,0xc0,0x1c,0x30,0xbb,0xb4,0xb2,0xf8,0xa9,0x12,0xf4,0xca,0xc0,0x24,0xf0,0xea,0x5c,0x57,0x77,0x6a,0x78,0x60,0x98,0xd6,0x64,0x2b,0xf5,0xf1,0x38,0xaa,0x6,0x80,0xef,0x7b,0x94,0x8a,0x45,0x72,0xf9,0x1c,0xf3,0xdf,0xe7,0xd9,0x58,0x5f,0x9d,0x5,0x9e,0x2d,0xad,0x2c,0xe6,0xeb,0xca,0x44,0x2f,0xae,0x5e,0xb9,0x9e,0xba,0x70,0xfe,0x12,0x9b,0x9b,0x59,0xfe,0x6e,0xad,0x51,0x28,0x84,0x87,0xe4,0x1b,0x1a,0x8e,0xd1,0x98,0x48,0x70,0xf3,0xda,0x2d,0x7e,0x9c,0x5e,0x4e,0x7d,0xf9,0xfa,0x59,0x80,0x89,0x58,0x6f,0x4f,0xdf,0x58,0x57,0x57,0xf7,0x9b,0xcb,0x17,0xfb,0x58,0xfb,0xb9,0xc1,0xde,0xee,0x1e,0xa1,0xb,0x31,0x14,0x33,0xc3,0xcc,0x0,0xc3,0x85,0x8e,0xfd,0x7f,0xfb,0xe4,0x73,0x3b,0x74,0x9e,0xed,0x24,0xd8,0xdd,0x19,0x8d,0xd7,0xc7,0x97,0x7d,0x20,0x35,0xd8,0x3f,0x44,0x26,0x9d,0xa5,0x50,0x2c,0x20,0x26,0xa8,0x2a,0xe3,0x8f,0xef,0x31,0x3e,0x79,0x17,0x35,0x41,0x54,0xa2,0xb8,0x28,0x85,0x62,0x81,0x4c,0x3a,0xcb,0xd0,0xc0,0x8,0x40,0xca,0x7,0xfa,0x45,0x84,0x20,0x8,0x50,0x15,0x54,0x4,0x75,0x2,0x66,0x60,0xc6,0xc4,0xe4,0x7d,0x54,0x4,0x27,0x52,0x7e,0x57,0x82,0x60,0x7,0x11,0x1,0x18,0xf4,0x81,0x64,0x28,0xe,0x31,0x17,0x29,0x89,0x20,0xe6,0x30,0xab,0xb4,0xa0,0x3c,0x7c,0xf2,0x0,0x53,0x87,0x68,0x25,0xcf,0x11,0x8a,0x3,0x48,0xfa,0x0,0x12,0x96,0x10,0x8d,0x94,0x45,0xa2,0x16,0xa2,0xce,0xad,0x3a,0x87,0x47,0x4f,0xc7,0x51,0x55,0x54,0x5,0x31,0x45,0xc2,0x12,0x0,0x75,0x0,0x25,0xe7,0x10,0x11,0x7c,0x40,0x1,0x4,0x30,0xc3,0xaa,0x7f,0x6d,0x98,0x81,0x8b,0xca,0xa6,0x82,0xa9,0x12,0xb8,0x30,0x44,0x4d,0x50,0x33,0xbc,0x28,0x3d,0x52,0x2e,0x2f,0x8a,0x2,0x6f,0xa7,0xdf,0xe3,0x41,0x35,0xe6,0xc2,0xb0,0x4a,0x90,0xf,0x9d,0x4b,0xaa,0x8,0x9e,0x67,0x58,0xd,0x1,0x65,0xc0,0xeb,0xe9,0x77,0x54,0xcb,0x29,0x53,0x84,0x51,0x5,0xbb,0x75,0xc0,0x82,0xb,0x4b,0x37,0x84,0x10,0xc4,0x8b,0x54,0x8c,0x88,0xc0,0x33,0x5e,0x3e,0x9f,0xa9,0xc5,0x45,0x77,0xcc,0x70,0xd1,0xc,0xe6,0xbc,0xde,0x9e,0xbe,0xb1,0x13,0x6d,0x6d,0x1f,0xcf,0xb4,0x77,0xb2,0xbd,0x9d,0xc3,0x23,0x56,0x5e,0xf0,0x5a,0x41,0x2f,0x62,0x5,0xc,0xa1,0xa5,0xa5,0x95,0x74,0x66,0x83,0x5c,0x2e,0x77,0x27,0x96,0xfd,0xb3,0xb5,0x70,0x3c,0xd1,0x74,0xb2,0x21,0xd1,0x38,0xda,0xdc,0x94,0xa4,0xe8,0xa,0xa8,0x3a,0x4c,0xc,0x43,0x11,0x34,0x1a,0xa8,0x27,0x78,0x31,0x8f,0x64,0x73,0xb,0xc1,0x7e,0xc0,0xe6,0x66,0xe6,0xc3,0xd2,0xca,0xe2,0x4c,0xc5,0xb,0x53,0xeb,0xeb,0xab,0xb1,0x96,0x64,0x6b,0xaa,0xbd,0xa3,0x3,0xdf,0xf7,0xf,0x9c,0xc6,0x41,0xfb,0xaa,0x4a,0xfa,0xf7,0x2f,0xb6,0xf3,0xb9,0x59,0x60,0xaa,0x36,0xe7,0xa8,0x9d,0x47,0x81,0x53,0x47,0xec,0x9c,0x1,0xbe,0x1d,0xb5,0xf3,0x7f,0xe9,0x95,0x7b,0x78,0x8a,0x5f,0xe7,0x67,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x2c,0xb6,0xed,0x5d,0xa6,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xa5,0x93,0x4d,0xa,0xc2,0x30,0x10,0x85,0x5f,0xa5,0x83,0x90,0x82,0xbd,0x81,0x8b,0xe4,0x18,0x22,0x5e,0x4b,0xad,0xad,0xdd,0x68,0xfd,0xbb,0x62,0x7a,0x9,0x69,0x14,0x6,0x32,0xae,0x4,0x91,0xb6,0x92,0xf8,0x56,0xb3,0x98,0xef,0xe3,0x2d,0x66,0x92,0xe5,0x62,0x35,0x35,0xda,0x3c,0x88,0x28,0x41,0x40,0x98,0x59,0x6c,0x6b,0x67,0xa9,0xd1,0xe6,0xe9,0x9c,0x43,0xe7,0x5c,0x8,0x8f,0x4c,0xa9,0xc4,0x68,0x73,0x9f,0x10,0x51,0x30,0xc,0x0,0x9d,0x73,0x20,0x22,0x4c,0x82,0xc9,0xaf,0xc,0xa,0xaa,0xba,0x40,0x55,0x17,0xf1,0x2,0x11,0x81,0x88,0xa0,0xdc,0x6f,0xe3,0x4,0xde,0x7b,0x88,0x8,0xbc,0xf7,0xd8,0x55,0x9b,0x70,0xc1,0x67,0xb,0x11,0x41,0x51,0xae,0x7b,0x77,0xd2,0x31,0xb8,0x6f,0x8e,0x12,0x0,0x40,0x73,0xb8,0xc4,0xb,0x4e,0xc7,0x6b,0x7c,0x83,0x73,0x73,0x1b,0x84,0x47,0x5,0xbf,0xc0,0x77,0xfe,0xbf,0x44,0x66,0x46,0xa6,0x54,0x30,0x98,0x29,0x5,0x66,0x46,0x6a,0x5b,0xab,0x8c,0x36,0x5d,0x9e,0xe7,0x31,0xef,0x3c,0x7f,0x1,0x85,0xa9,0x5c,0xe7,0x16,0x3f,0x9a,0xd3,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_up_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x11,0x1f,0x28,0xa9,0x94,0x8f,0x29,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x86,0x49,0x44,0x41,0x54,0x38,0xcb,0x9d,0x93,0x4d,0x4a,0x9c,0x41,0x10,0x86,0x9f,0xfe,0x66,0x14,0x25,0x28,0x38,0x9b,0x19,0x98,0x95,0xe4,0xe,0x9,0x28,0x62,0xc8,0x15,0xb2,0x71,0x21,0xc,0x82,0xb,0x17,0x5e,0x41,0xb2,0xcd,0x35,0x2,0x6e,0x73,0x85,0x10,0x97,0x1e,0x42,0x5c,0x9,0x8a,0x38,0x9,0x51,0xfb,0xaf,0xba,0xba,0x5d,0x38,0x33,0xfd,0xe9,0x28,0x82,0xb5,0xe9,0xa6,0xba,0xde,0xa7,0xba,0xab,0xaa,0xcd,0xb0,0x3f,0xf8,0x4,0x9c,0xf2,0x3e,0xfb,0x6c,0x86,0xfd,0x41,0xf9,0xb8,0xbe,0xce,0xd7,0xed,0x2f,0xac,0xae,0xac,0x0,0x6,0x4a,0x1,0xf3,0x2c,0xb4,0x0,0xc6,0x0,0x85,0xff,0xb7,0xb7,0xfc,0x3e,0xf9,0xc3,0xd9,0xf9,0x39,0x5d,0x80,0xad,0x8d,0x4d,0x0,0x6e,0xae,0x6f,0xa6,0x91,0xad,0x95,0x39,0xdf,0xc2,0xd2,0x22,0x5b,0x1b,0x9b,0x15,0xd0,0x5b,0x5b,0xe3,0xef,0x78,0x4c,0x8c,0xa1,0x66,0x2f,0x4f,0xe5,0x55,0x6f,0x30,0xd,0xf4,0x7a,0x3d,0x80,0x47,0x80,0x6a,0x26,0x6b,0x26,0xe7,0xdc,0x52,0xbc,0xf0,0x4,0x80,0x52,0xc8,0x9a,0x51,0xcd,0x15,0x90,0x92,0x90,0x54,0xc9,0xaa,0x4f,0xb4,0xdf,0x46,0xbb,0x0,0xfc,0xfa,0x79,0x3c,0xf3,0x19,0x20,0xa9,0x92,0x92,0x0,0xd0,0x0,0x4,0x1f,0x90,0x18,0x89,0x31,0x22,0x22,0x88,0xc8,0x4c,0x3c,0x5,0x4d,0xfd,0x31,0x46,0x24,0x46,0x82,0xf,0x15,0xe0,0x83,0x27,0x84,0x40,0x98,0x1c,0xec,0xec,0xef,0xcd,0xbd,0x60,0x67,0x7f,0x8f,0xe0,0x27,0x31,0x21,0xe0,0x83,0xaf,0x0,0xeb,0x2c,0xce,0x39,0x9c,0x73,0x8c,0xe,0xf,0x5e,0x6d,0xfa,0xe8,0xf0,0x60,0x16,0x67,0x9d,0xad,0x35,0x70,0x77,0x16,0xe7,0x2c,0x22,0xe9,0xcd,0xc9,0xf1,0xde,0xa3,0x9a,0xe8,0x74,0x3a,0x15,0x60,0xbd,0xc3,0xfb,0x80,0x24,0xe1,0xc7,0xd1,0x77,0xda,0x5d,0x7b,0xbe,0x7f,0xec,0xda,0x2,0x4d,0xb7,0xdb,0x2,0x58,0x87,0x8f,0x81,0xd4,0xbe,0x81,0x79,0xa5,0x8d,0x80,0xe6,0xc,0xb6,0xa9,0x0,0xef,0x3c,0x51,0x22,0x9a,0xf4,0xe5,0x19,0x68,0x9b,0x81,0x5c,0x32,0x14,0xd3,0xaa,0x41,0xc,0x24,0x91,0x3a,0x48,0x6f,0x58,0x93,0x33,0x3a,0x49,0xd4,0x5,0xb8,0xbc,0xbe,0xe2,0xc3,0xd2,0x32,0xa5,0x9d,0xbe,0xcc,0x67,0xae,0x5b,0xc3,0xfd,0xbf,0x71,0xad,0xcf,0xb0,0x3f,0x78,0xd7,0x5f,0xbe,0xb8,0xba,0xe4,0x1,0xf0,0xd2,0xea,0x35,0xc0,0x6a,0x26,0xd2,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x26,0x56,0x38,0xb4,0xb8,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x9a,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x93,0x31,0xa,0xc3,0x30,0xc,0x45,0xbf,0x83,0x6,0x41,0x4d,0x27,0x4f,0xd6,0x15,0x5a,0x7a,0x8f,0x52,0x7a,0xaf,0x10,0x72,0x4c,0x67,0xf2,0xd2,0x25,0xd5,0x20,0x48,0xd7,0x92,0xba,0xa1,0x76,0x29,0xf4,0xaf,0xe2,0x3d,0x81,0xd0,0x77,0xc7,0xc3,0x89,0x25,0xca,0x4c,0x44,0xe,0x15,0x31,0xb3,0x25,0x4d,0x69,0x47,0x12,0xe5,0xae,0xaa,0x50,0xd5,0x1a,0x1e,0xcc,0xec,0x24,0xca,0xdc,0x11,0x51,0x35,0xc,0x0,0xaa,0xa,0x22,0x42,0x57,0x4d,0xae,0xf2,0x5b,0xc1,0x30,0xf6,0x18,0xc6,0xbe,0x4d,0xf0,0xc,0x6e,0x49,0x8a,0x82,0x12,0xf0,0x4e,0xf2,0x22,0xd8,0xda,0x56,0x9a,0x7d,0x7d,0x44,0x77,0x39,0x5f,0x97,0x9c,0x73,0x13,0x1c,0x42,0xf8,0xf7,0x3f,0xf8,0x48,0x60,0x66,0x60,0xe6,0x6a,0x90,0x99,0x61,0x66,0xa0,0x34,0xa5,0xbd,0x44,0xb9,0x79,0xef,0x5b,0xea,0x2c,0xf,0x4,0x76,0x39,0xf7,0xc5,0x49,0xf5,0x9f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char scroll_button_up_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x11,0x20,0x2,0x2a,0xf1,0x6c,0xc3,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x86,0x49,0x44,0x41,0x54,0x38,0xcb,0x9d,0x93,0xbf,0x4e,0x1b,0x41,0x10,0x87,0xbf,0xbd,0x9c,0x51,0x64,0xc9,0x91,0x70,0x6b,0x17,0xee,0x20,0x2f,0x40,0x5a,0xb,0x9,0xa5,0x4b,0x43,0x81,0x64,0x51,0x50,0x50,0xf0,0x14,0x88,0x3a,0xf,0x82,0x94,0x36,0x1d,0xf2,0x13,0xe4,0x9,0x12,0x3a,0xa4,0x80,0x28,0x90,0x89,0x14,0xeb,0xf6,0xff,0xec,0x52,0x18,0xb3,0x67,0xc,0x42,0x62,0x9a,0x5b,0x8d,0x7e,0xbf,0x6f,0x76,0x76,0xe6,0xd4,0x68,0x30,0xdc,0x1,0x7e,0xf1,0xbe,0xf8,0xa2,0x46,0x83,0x61,0xfe,0xbc,0xb5,0xcd,0xd7,0xbd,0x3d,0x3e,0xf5,0x7a,0x80,0x82,0x9c,0x41,0x3d,0x93,0x66,0x40,0x29,0x20,0xf3,0x7f,0x3e,0xe7,0x62,0x3a,0xe5,0xf7,0xe5,0x1f,0x6a,0x80,0xdd,0xf1,0x18,0x80,0xd9,0xdd,0x6c,0xa9,0x6c,0x7d,0x59,0xcb,0x75,0x3e,0x6e,0xb0,0x3b,0x1e,0x17,0x40,0x7f,0x73,0x93,0x7f,0xf7,0xf7,0x78,0xef,0x4a,0xf5,0xbc,0x6a,0x2f,0x7e,0x85,0xaa,0xa0,0xdf,0xef,0x3,0x2c,0x0,0x22,0x89,0x24,0x89,0x94,0x52,0xcb,0xf1,0x42,0xb,0x0,0x39,0x93,0x24,0x21,0x92,0xa,0x20,0xc6,0x40,0x14,0x21,0x89,0xac,0x78,0xbf,0x4d,0xe,0x0,0xf8,0x79,0xfe,0xe3,0x29,0xa7,0x80,0x28,0x42,0x8c,0x1,0x80,0xa,0xc0,0x59,0x47,0xf0,0x1e,0xef,0x1c,0xc1,0x7,0x82,0xf,0x4f,0xe6,0x25,0x68,0x99,0x5f,0x68,0x3c,0xce,0xba,0x2,0xb0,0xce,0xe2,0xac,0xc5,0x79,0x8f,0xb3,0x96,0xfd,0xa3,0xc3,0xb5,0xe,0xf6,0x8f,0xe,0x57,0x34,0xd6,0xd9,0x2,0xd0,0x46,0xa3,0xb5,0x41,0x6b,0xcd,0xe4,0xe4,0xf8,0xd5,0xa1,0x4f,0x4e,0x8e,0xd1,0xfa,0x51,0x6b,0x74,0x79,0x3,0x33,0x6f,0x30,0xba,0xc1,0x87,0xf0,0xe6,0xe6,0x18,0x63,0x90,0x18,0xa9,0xeb,0xf,0x5,0xd0,0x18,0x8d,0x31,0x16,0x1f,0x3d,0xdf,0x4f,0xcf,0x68,0x4f,0xed,0xf9,0x19,0x40,0xa2,0x50,0x75,0xea,0x16,0xa0,0xd1,0x18,0x67,0x9,0xed,0x1b,0xa8,0x57,0xc6,0x8,0x48,0x27,0x41,0x53,0xb5,0x5a,0x68,0xc,0xce,0x3b,0x24,0xc6,0x97,0x77,0xa0,0x1d,0x8a,0xc5,0xbe,0x64,0x55,0x0,0xda,0x59,0x82,0xf7,0x65,0x91,0xde,0x88,0x4a,0x12,0xf2,0x58,0xa8,0x6,0xf8,0x7b,0x7b,0x43,0xaf,0xdb,0x25,0xb7,0xcb,0xe7,0xf5,0xca,0xe5,0xa8,0x98,0xcf,0xee,0xca,0xfb,0x8c,0x6,0xc3,0x77,0xfd,0xcb,0x57,0x37,0xd7,0x3c,0x0,0xb0,0x7,0xe9,0xba,0xfd,0xb,0xce,0x5b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x59,0x0,0x59,0x0,0x59,0xbd,0x9a,0xea,0xaa,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x13,0x19,0x21,0xc8,0x5c,0x21,0x1b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x9a,0x49,0x44,0x41,0x54,0x38,0x8d,0xcd,0x93,0x51,0xa,0xc2,0x30,0xc,0x86,0xff,0x8d,0x6,0x21,0x5,0x7b,0x3,0x1f,0x9a,0x63,0x88,0x78,0x30,0x11,0x6,0x63,0xc7,0xec,0x2e,0x21,0x8d,0x42,0x1e,0xf4,0x75,0xcc,0x6e,0xd8,0x89,0xe0,0xff,0x98,0xf2,0x7d,0x29,0x21,0x69,0x4e,0xc7,0xf3,0x4e,0xa2,0xdc,0x89,0xa8,0x41,0x45,0xcc,0xec,0x99,0xc6,0xb4,0x77,0x12,0xe5,0xa1,0xaa,0xc8,0xaa,0x35,0x3c,0x3c,0x73,0x23,0x51,0x6e,0x2d,0x11,0x55,0xc3,0x0,0x90,0x55,0x41,0x44,0x68,0xab,0xc9,0x59,0x7e,0x2b,0xe8,0x87,0xe,0xfd,0xd0,0x6d,0x13,0x4c,0xc1,0x35,0x49,0x51,0x50,0x2,0x96,0x24,0x6f,0x82,0xb5,0x6e,0xa5,0xb7,0xaf,0x87,0xe8,0xe6,0x85,0xeb,0x65,0xf9,0x7,0xa5,0xfc,0xf9,0x1e,0x7c,0x24,0x30,0x33,0x78,0xe6,0x6a,0xd0,0x33,0xc3,0xcc,0xe0,0xd2,0x98,0x58,0xa2,0xe4,0x10,0xc2,0x96,0x73,0x3e,0xbc,0x0,0x5f,0x36,0x36,0x12,0x78,0xeb,0xb3,0xc5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char scroll_grabber_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x17,0x25,0x29,0x85,0xa3,0x88,0x38,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x72,0x49,0x44,0x41,0x54,0x18,0x95,0x7d,0xcd,0xb1,0x9,0xc3,0x30,0x0,0x44,0xd1,0x17,0x21,0x91,0x42,0x10,0xdc,0x4,0x34,0x80,0x77,0xc8,0x4,0x6e,0x32,0xb0,0x1b,0xf,0xe2,0x26,0x4d,0x6a,0x37,0xc2,0x5d,0x40,0x45,0x1a,0x1b,0x4c,0x20,0xfe,0xe5,0xbf,0x3b,0xee,0x52,0x4a,0x71,0x46,0x8c,0x31,0x1a,0x86,0x67,0x87,0x19,0x7b,0x7b,0x41,0x3f,0x4d,0xe3,0x1a,0x36,0x31,0xa3,0x3b,0xc,0x6f,0x78,0x41,0x6c,0xad,0x39,0x2c,0x77,0xae,0xb8,0xb7,0xd6,0x84,0x94,0xd2,0xdf,0xff,0x94,0x92,0x90,0x73,0x86,0xf7,0x4f,0xf6,0xc1,0x92,0x73,0x16,0x6a,0xad,0xf0,0xd8,0xe4,0xce,0x8a,0x7e,0xcb,0xce,0xf9,0x2,0x99,0xd9,0x19,0x5e,0xac,0x65,0x2e,0x22,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char scroll_grabber_hl_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x17,0x25,0x15,0xaa,0xcc,0xf4,0xbf,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x86,0x49,0x44,0x41,0x54,0x18,0x95,0x7d,0x8e,0xb1,0xa,0x83,0x30,0x18,0x84,0xbf,0x36,0x81,0x6e,0xe5,0xf,0xad,0x6e,0xe,0x11,0x97,0x2e,0xfa,0xae,0x6e,0x7d,0x29,0xa1,0xce,0xa5,0xae,0x5,0x7,0x83,0x53,0xb,0xf9,0xa1,0x4b,0x94,0xe,0xe2,0x8d,0x77,0xdf,0x71,0x77,0x68,0xdb,0x3b,0x7b,0xb2,0x0,0xc3,0xf0,0xba,0x86,0x30,0x75,0x40,0x91,0xfc,0x51,0xc4,0x55,0xde,0x97,0xb3,0x5,0x8,0x61,0xea,0xea,0xba,0xb9,0x18,0x63,0x1,0x50,0x8d,0xe7,0xbe,0x7f,0x3c,0x81,0xdc,0xa6,0x46,0xb1,0x84,0x0,0xc6,0xd8,0x13,0x90,0x1,0x1c,0x77,0xf,0xfc,0x1,0xa3,0x6a,0xfc,0x2e,0xa6,0x6a,0xfc,0x0,0xef,0xf5,0xa4,0x88,0xab,0xd2,0x66,0x96,0x98,0x20,0xe2,0x6e,0x2b,0xe0,0x7d,0x39,0x3,0xf9,0xd6,0xc4,0xf,0x70,0x6e,0x25,0xf5,0x5c,0xbc,0xd7,0xd3,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char selection_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4e,0x0,0x41,0x0,0x56,0xed,0xd0,0x4e,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x13,0x25,0x36,0xd1,0x55,0x4f,0xe9,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x76,0x49,0x44,0x41,0x54,0x38,0xcb,0x95,0x92,0xb1,0x6e,0x13,0x41,0x10,0x86,0xbf,0x59,0xd9,0xb2,0x4c,0x68,0x63,0xc2,0x21,0x39,0xb2,0x29,0xa9,0x52,0xb8,0x4b,0x93,0x2,0xa5,0xe,0xd,0x3d,0x1d,0xf,0x0,0x2d,0xa2,0xe5,0x5,0xdc,0xa5,0x4f,0x3,0x35,0xca,0x23,0xa4,0x48,0x95,0x32,0x41,0x58,0xf2,0x81,0x9d,0x22,0x42,0x22,0x36,0xf6,0xed,0xce,0x50,0x9c,0xef,0x6e,0x2f,0x2e,0x38,0x46,0x5a,0x8d,0x76,0x77,0xfe,0x4f,0xb3,0xff,0xac,0x98,0x19,0xfb,0xcf,0x9e,0x9f,0x0,0x6f,0x81,0x97,0x34,0x8b,0x73,0x60,0xfc,0x7d,0x7a,0xfd,0x45,0xfa,0xc9,0xf0,0xdd,0xd3,0x5e,0xf2,0xe9,0xe0,0xc5,0x88,0x64,0x2f,0x69,0xa4,0x4e,0x7f,0xa6,0x5c,0x5e,0x5d,0xf0,0x63,0x9e,0xbe,0x97,0x7e,0x32,0xbc,0x79,0x75,0xfc,0x7a,0xb0,0x5c,0x2d,0x59,0x2e,0xef,0x1b,0x1,0xba,0xdd,0x1d,0xba,0x9d,0x2e,0x9f,0xbf,0x9e,0x7d,0x6b,0x1,0x83,0x5f,0xf7,0x77,0xf8,0xb5,0xa7,0x69,0x2c,0x16,0xbf,0x59,0xfb,0x3f,0x0,0x3,0x7,0xfc,0x97,0xb8,0x88,0x42,0xd3,0x2,0x50,0x55,0x70,0x80,0x92,0xe7,0x22,0x14,0x10,0x1,0xb1,0xea,0x4e,0xeb,0xa0,0x16,0x40,0x50,0x8f,0x98,0x60,0x0,0x59,0x1d,0x62,0x6a,0x88,0x48,0xbe,0x9,0xd1,0xb9,0x59,0xd4,0x81,0x19,0x98,0x61,0xb6,0x29,0xd6,0xaa,0x48,0x44,0xca,0xe2,0x22,0x97,0xc0,0xb2,0x83,0x50,0xa1,0x63,0xc1,0x43,0x71,0x21,0x54,0xd5,0x6d,0x80,0x38,0x87,0x15,0x17,0xb1,0x1f,0x51,0x16,0x1c,0xe6,0xb4,0xf2,0xa7,0x0,0x18,0x8a,0x7a,0x45,0x1c,0x18,0x20,0x9a,0x67,0x7c,0xdd,0x50,0x71,0x5a,0x3d,0x2f,0x6,0x68,0xc8,0xdb,0xd4,0x0,0x52,0x98,0xf,0x28,0x8a,0xc3,0x95,0xe6,0x59,0x6c,0xa2,0x58,0xfc,0x84,0x8d,0xf5,0xe5,0x98,0x14,0x5c,0x3e,0xa,0xbf,0x51,0x9b,0x2a,0x82,0x43,0x6a,0x33,0xce,0x1,0x93,0x2c,0x64,0x7d,0xe7,0x5a,0xb5,0x31,0x11,0xc2,0xd6,0xe7,0xb1,0xa8,0x40,0xd5,0x3,0x4c,0x1c,0x30,0x4e,0x67,0x53,0x7c,0xc8,0x36,0xd4,0x7f,0x2f,0x1f,0x32,0xd2,0xd9,0x14,0x60,0x2c,0x66,0xc6,0xe1,0xe8,0xe8,0xc3,0xfc,0x76,0xf6,0x66,0x95,0xad,0xfa,0x4d,0xbe,0x71,0xa7,0xdd,0x99,0xf4,0x76,0x9f,0x9c,0x3e,0x6a,0x3f,0xfe,0xf8,0x17,0xda,0x44,0xc8,0x77,0x97,0xc9,0xd6,0x18,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x12,0x2a,0x16,0x85,0x48,0x8b,0x13,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x93,0x31,0xa,0xc2,0x50,0x10,0x44,0xdf,0x97,0xbf,0x8a,0x3f,0x45,0xd0,0x52,0xbb,0xfc,0x63,0x88,0x88,0xa7,0xd0,0x23,0x9a,0x63,0x84,0x90,0x63,0x24,0x9d,0x9d,0x60,0x95,0x2f,0xb2,0x21,0x5a,0x18,0xb4,0x52,0x3,0x69,0x2c,0x9c,0x6e,0x8b,0x99,0xd9,0x59,0x76,0xc,0x30,0x6,0xa6,0xc0,0x4,0x18,0xd1,0xf,0x2d,0x70,0x5,0x2e,0xb6,0x23,0x2f,0x81,0x19,0x20,0x3d,0x5,0x14,0x38,0x3,0x47,0xdb,0x39,0xcf,0xd7,0xab,0xcd,0xc2,0x27,0xfe,0x20,0x22,0xe6,0x23,0x53,0xf5,0x56,0x56,0xe5,0x3e,0x2f,0x32,0x3,0x9c,0x6c,0xb7,0xb6,0xf5,0x89,0x4f,0x43,0x8,0xd4,0x21,0x7c,0xb4,0x8e,0x9c,0x33,0x3e,0xf1,0x69,0x5e,0x64,0x5b,0x60,0xf4,0xcc,0x2c,0x22,0x5f,0xc9,0x0,0x75,0x8,0x88,0xbc,0x92,0xf6,0x3d,0xda,0x5b,0xfc,0x5,0x7e,0x4a,0x40,0x55,0x89,0x9c,0xfb,0x4a,0x88,0x9c,0x43,0x55,0x9f,0xb3,0xe5,0x51,0x8c,0xa6,0xac,0xca,0x9d,0x4f,0xfc,0x21,0x8e,0xe3,0x5e,0xaf,0xc,0x34,0x40,0x6b,0x80,0x98,0x1,0x65,0x32,0xc,0xac,0xf3,0x1d,0x55,0xc6,0x3e,0x2,0xe2,0x2e,0xc9,0xc8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char selection_oof_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4e,0x0,0x41,0x0,0x56,0xed,0xd0,0x4e,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x13,0x1d,0x6,0xe0,0x13,0xc3,0xbe,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x6a,0x49,0x44,0x41,0x54,0x38,0xcb,0x95,0x92,0xcf,0x2e,0x3,0x51,0x14,0xc6,0xbf,0xd3,0x4e,0x6a,0x4a,0x48,0xd1,0x96,0x52,0x4d,0xba,0xb0,0x61,0x21,0xb1,0xb1,0xb0,0x25,0x56,0x16,0x5e,0xc1,0xce,0x3,0xb0,0x15,0x3b,0xf1,0x2,0x76,0x5e,0xc1,0xc2,0x4a,0xac,0x3d,0x80,0x85,0x95,0x84,0xa4,0x42,0x94,0x52,0x24,0xfd,0x63,0xfe,0xdc,0xcf,0xe2,0xce,0x9d,0xce,0xb4,0x8d,0x8c,0x93,0x4c,0x4e,0x72,0xee,0x77,0x7e,0xf7,0x3b,0x67,0xae,0x90,0xc4,0x5c,0x71,0x61,0x7,0xc0,0x1e,0x80,0x4d,0x24,0x8b,0x2b,0x0,0xa7,0xcf,0xaf,0x8f,0xe7,0x52,0x2a,0x94,0xf7,0xb,0x93,0x33,0x27,0xcb,0x8b,0x2b,0x98,0x9d,0x9e,0x4f,0xd4,0xfd,0xf2,0xfe,0x84,0xdb,0xbb,0x1b,0xbc,0x35,0xeb,0x7,0x52,0x2a,0x94,0xef,0xb7,0xd6,0xb7,0xab,0x5d,0xa7,0x8b,0x4e,0xb7,0x9d,0x8,0x90,0xb5,0x47,0x61,0x67,0x6c,0x5c,0x5e,0x5f,0x3c,0x58,0x0,0xaa,0xdf,0xad,0x2f,0x78,0x9e,0x87,0xa4,0xd1,0xee,0xb4,0xe0,0xb8,0x3f,0x0,0x50,0x4d,0x1,0xf8,0x57,0xb3,0x9,0xd3,0x63,0x1,0x80,0x52,0xa,0x10,0x0,0x84,0xce,0x26,0x8,0x5d,0x10,0xf6,0xce,0x18,0x7,0x5,0x0,0x1f,0x22,0xa2,0xcf,0x54,0x1f,0x4,0x4,0x28,0x11,0x60,0x8c,0x1e,0x0,0x48,0x80,0xec,0x59,0x60,0x54,0x14,0xbd,0xd6,0x64,0x19,0x74,0x10,0x86,0x48,0x0,0x33,0x3a,0x3,0x64,0x7c,0x9c,0x38,0x40,0x85,0x8d,0xc,0x18,0xc6,0xb9,0xc4,0x4c,0x98,0x42,0xcf,0x4c,0x30,0x82,0xa,0x67,0x27,0x22,0x3b,0x53,0x3a,0xf,0x82,0xfa,0x1,0x4a,0xe9,0x1a,0xb5,0xc6,0xec,0x51,0x81,0x90,0x80,0xca,0xfe,0x25,0xca,0xc0,0xe,0x44,0x3b,0x8,0x94,0x14,0xad,0x50,0xa6,0x8b,0xda,0x82,0xc,0xf9,0xb,0x35,0xd7,0x77,0x2b,0xe9,0x94,0x15,0xbf,0x81,0x1c,0xf2,0x7c,0x18,0x4a,0x7c,0xe5,0x1,0x40,0x2d,0x3d,0x3e,0x36,0x61,0xbb,0x9e,0xb3,0x61,0x8f,0x64,0x21,0x29,0x33,0xe4,0xdf,0x9f,0xef,0x7b,0x68,0x34,0xeb,0x70,0x3d,0xf7,0x58,0x48,0x62,0x75,0x69,0xed,0xf0,0xe3,0xb3,0xb1,0xeb,0x78,0x4e,0x25,0xc9,0x33,0xce,0x58,0x99,0xda,0x54,0x2e,0x7f,0x96,0xcf,0x15,0x8f,0x7e,0x1,0x52,0xd8,0xb3,0xdb,0x19,0xc1,0x3b,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x15,0x32,0x22,0x9b,0x14,0x96,0x1f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0xb1,0x4e,0xc3,0x40,0x10,0x84,0xe1,0xef,0xc2,0x4a,0x9c,0x90,0xb,0x6a,0x9f,0xe0,0x9,0x2,0xbc,0x58,0xc2,0xcb,0xc0,0x8b,0x85,0xa4,0xa6,0x41,0x4e,0x4d,0x41,0x71,0x91,0xe,0x99,0x2,0xd7,0x76,0xa4,0x34,0x14,0x6c,0xb9,0xda,0xf9,0x47,0x2b,0xcd,0x24,0xdc,0xe0,0x16,0x1d,0xae,0x90,0xcc,0xcf,0x88,0x6f,0x7c,0xe1,0x33,0x26,0xf1,0x23,0xee,0x90,0xcf,0x4,0x54,0x7c,0xe0,0x2d,0x26,0xe7,0xfb,0x87,0xf5,0xd3,0xba,0xf4,0x65,0x13,0x11,0xb3,0x80,0xd6,0xda,0x38,0x1c,0x87,0xd7,0xfd,0x61,0x97,0xf0,0x1e,0x8,0x5c,0x97,0xbe,0x6c,0x6b,0xad,0x6a,0xad,0xb3,0xf6,0x39,0xe7,0x54,0xfa,0xb2,0xdd,0x1f,0x76,0xcf,0x88,0xd5,0xb4,0x4f,0x11,0xb1,0x28,0x86,0x5a,0xab,0x88,0x60,0x7a,0x75,0x35,0x7f,0xbe,0x3c,0xff,0x80,0xbf,0x4,0x18,0x5b,0x6b,0x72,0xce,0x8b,0x82,0x9c,0xb3,0xd6,0x1a,0xbf,0x91,0x16,0x68,0x38,0xd,0xc7,0xe1,0xa5,0xf4,0x65,0xd3,0x75,0xdd,0x59,0x51,0xc6,0x9,0x2d,0xa1,0x77,0x41,0x99,0x92,0xb,0xeb,0xfc,0x3,0xd0,0xc5,0x44,0x36,0x1d,0x79,0x84,0xde,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -330,7 +350,7 @@ static const unsigned char spinbox_updown_png[]={ static const unsigned char submenu_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0x4,0x1b,0x16,0x1b,0x32,0xbf,0xff,0x75,0xca,0x0,0x0,0x0,0x3a,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x80,0x82,0x73,0x2f,0x5e,0xdd,0x3b,0xf7,0xe2,0xd5,0x3d,0x6,0x34,0xc0,0x84,0x2e,0x80,0xae,0x8,0x43,0x1,0xba,0x22,0xac,0xa,0x90,0x15,0xe1,0x54,0x40,0xd0,0x4,0x23,0x9,0x31,0x25,0x9c,0xa,0x60,0x92,0x58,0x15,0x20,0x4b,0x32,0x30,0x30,0x30,0x0,0x0,0x56,0x5a,0x13,0xb,0xf,0x58,0x99,0x10,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x12,0x38,0x2b,0x92,0xa,0x47,0xe3,0x0,0x0,0x0,0x3a,0x49,0x44,0x41,0x54,0x18,0x95,0x63,0x60,0x80,0x82,0x3b,0x77,0xee,0xdc,0xbb,0x73,0xe7,0xce,0x3d,0x6,0x34,0xc0,0x84,0x2e,0x80,0xae,0x8,0x43,0x1,0xba,0x22,0xac,0xa,0x90,0x15,0xe1,0x54,0x40,0xd0,0x4,0x15,0x15,0x15,0x25,0x9c,0xa,0x60,0x92,0x58,0x15,0x20,0x4b,0x32,0x30,0x30,0x30,0x0,0x0,0x2c,0x62,0x12,0xf3,0xa8,0xc4,0xd,0xa6,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -340,27 +360,27 @@ static const unsigned char tab_png[]={ static const unsigned char tab_behind_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4f,0x0,0x42,0x0,0x57,0xa5,0xf1,0xe9,0x1e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x10,0x25,0x6,0xf5,0xca,0xc1,0x1c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x30,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x90,0x31,0x4e,0xc3,0x40,0x14,0x44,0xdf,0x97,0x82,0x2,0x45,0x64,0xc7,0xc8,0x29,0x28,0x90,0x2c,0x51,0xd0,0xd1,0xd3,0x50,0x71,0x0,0x8e,0xc1,0x1,0xe0,0x10,0x5c,0x80,0x63,0x70,0x0,0x2a,0x1a,0x7a,0x3a,0xa,0x4,0x12,0x5,0x45,0x24,0x14,0x4b,0xa0,0x4,0xb,0xb1,0x43,0xb1,0xbb,0x5e,0x3b,0x69,0x42,0xf8,0xc5,0xea,0xef,0xff,0x3b,0xb3,0x33,0x63,0x92,0xd8,0xcd,0x27,0x6c,0x52,0xef,0xf5,0x14,0x2b,0xb2,0x92,0x7c,0x34,0xe6,0x60,0xff,0x90,0x49,0xbe,0xb7,0x16,0x70,0x5a,0xbf,0xf1,0xf4,0xfa,0x48,0xfd,0x31,0xf3,0x4,0xc0,0x19,0x70,0xe,0x9c,0xae,0xf9,0xf9,0x2d,0x70,0xd,0xdc,0x58,0x91,0x95,0x17,0xf9,0x68,0x7c,0xb5,0xa1,0x82,0x4b,0x2b,0xb2,0xf2,0xf9,0xf8,0xe8,0xa4,0x6a,0xbe,0x1b,0xbe,0x9a,0xc5,0x5a,0x4,0xdb,0xc3,0x1d,0x86,0x5b,0x43,0xee,0x1f,0xee,0x5e,0x6,0x40,0x55,0x7f,0xce,0xfe,0x14,0xde,0xa2,0x99,0xb3,0x68,0xe6,0x0,0xd5,0x0,0x40,0xa,0x87,0x1,0x18,0x26,0x21,0x0,0x33,0x8f,0x90,0x30,0x40,0x66,0x80,0x40,0x69,0x37,0x0,0x70,0xee,0xc7,0x63,0x5,0x58,0x20,0x8c,0xf7,0xe5,0x56,0x2d,0x67,0x22,0x0,0xe1,0xc2,0xd2,0xd4,0xc3,0xf5,0xaa,0xdd,0x59,0x10,0x9b,0x14,0x4,0x64,0x64,0x8e,0x52,0xfb,0x70,0x14,0x6d,0xa,0xa4,0x8e,0x5,0xe1,0xda,0xdf,0xbd,0x5,0xd1,0xa5,0xf0,0xbd,0x9f,0xe1,0x40,0x96,0xbc,0x78,0x5,0xd2,0x8a,0x74,0x61,0xc9,0x6f,0x0,0x28,0xe2,0x14,0x67,0x51,0x81,0x53,0xfb,0xd0,0x5c,0x90,0xb1,0xca,0xe8,0x49,0xcc,0xfc,0xaa,0x1b,0xa2,0x70,0xed,0x40,0xf1,0x8c,0x69,0x75,0x23,0xf,0xbd,0x94,0x56,0x3d,0x5,0xcb,0xd1,0x99,0xd4,0xb1,0xd0,0xc9,0x43,0xe9,0xa1,0x15,0x59,0x29,0xfe,0x51,0xbf,0xb4,0x87,0x9c,0x22,0x50,0x2e,0x97,0xaa,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x13,0x3a,0x0,0x82,0x20,0x21,0x41,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x92,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x8f,0x3b,0xe,0xc2,0x30,0x10,0x5,0xc7,0x89,0xa5,0x80,0x45,0x81,0xb,0x6f,0x7,0x27,0xe0,0x73,0x36,0x4e,0xc2,0xd9,0xf8,0xd4,0x34,0x74,0xa1,0x30,0x5,0x12,0x34,0xab,0xa5,0x31,0xad,0x83,0x4,0x65,0xa6,0x7c,0xda,0x37,0x4f,0xb,0x3f,0xe2,0x80,0x0,0xcc,0x81,0x19,0xd0,0x96,0xac,0x86,0x1,0xa,0x3c,0x80,0xbb,0x2f,0xe5,0xd,0xb0,0x0,0x26,0x5f,0xa,0x5e,0xc0,0x15,0x38,0xfa,0xb2,0xbc,0x5c,0xaf,0xb6,0x7b,0x49,0x32,0x35,0xb5,0xaa,0xc0,0xb5,0xce,0xfa,0x5b,0xff,0x3c,0x9d,0xf,0x3b,0xe0,0xe2,0x1,0xf,0x74,0x92,0x24,0xa8,0x2a,0x39,0xe7,0xea,0x7c,0x8c,0xd1,0x49,0x92,0x0,0x74,0x80,0x6f,0x3e,0x62,0x53,0x1b,0x2c,0x3,0xe4,0x9c,0x31,0x35,0x28,0xaf,0x36,0xf5,0xf3,0x61,0x46,0xc1,0x28,0xf8,0x8b,0xe0,0xd,0xec,0x2e,0x27,0x7c,0x4,0xc2,0x7d,0x9a,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char tab_container_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x1b,0x89,0xf8,0xcc,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x10,0x1b,0x28,0x68,0xd9,0xd7,0xae,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xf3,0x49,0x44,0x41,0x54,0x48,0xc7,0xcd,0x95,0xbf,0x6e,0xd4,0x40,0x10,0xc6,0x7f,0x63,0xfb,0xfe,0x8,0x44,0x4,0x97,0x44,0xd0,0x50,0x20,0xa,0xd2,0x10,0xf2,0x4,0xe4,0x29,0x28,0x52,0xf1,0x24,0x5c,0x3,0x2f,0x42,0x1b,0xde,0x82,0x37,0x40,0x54,0x14,0x88,0x2,0x9,0xe,0x2e,0x98,0x88,0xd3,0x29,0x77,0x67,0xef,0xc,0x45,0x76,0xcd,0xda,0xb1,0x7d,0xa0,0x34,0x8c,0xb4,0xb2,0xc7,0x9e,0xef,0x9b,0x6f,0x67,0xd6,0x1e,0x1,0xc4,0xaf,0x4,0x48,0xfd,0x12,0x2e,0x2d,0x5c,0x2d,0xba,0x3a,0xbf,0x14,0xb0,0xcc,0x7,0xa5,0xc0,0x10,0x18,0x1,0x83,0x88,0x24,0x26,0x8,0xe0,0x2,0x58,0x3,0x1b,0xc0,0x65,0x3e,0xf3,0x10,0xb8,0xf1,0xe0,0xfe,0xc3,0x37,0xab,0xf5,0xfa,0x69,0x4,0x6c,0x9a,0x8d,0x47,0xa3,0xb7,0x9f,0x3e,0x7f,0x7c,0xe6,0xfd,0x75,0x16,0xb2,0xef,0x4f,0xee,0x4d,0x6f,0xef,0x4c,0x8e,0x1f,0x3f,0x7a,0xc2,0xce,0xad,0x3b,0xad,0xe8,0x5f,0x8b,0x9f,0xf2,0xfe,0xc3,0xbb,0xe3,0xfd,0xc9,0x72,0x3a,0xcf,0x67,0x53,0xa0,0xc,0xa,0x6,0x69,0x9a,0x9e,0x1c,0x1e,0x1c,0xb1,0x58,0x2e,0xf8,0x71,0x7e,0xd6,0x4a,0x30,0x1a,0x8e,0x39,0x3c,0x38,0xe2,0xeb,0xf7,0x2f,0x27,0xc0,0x2b,0x60,0x15,0x6a,0x90,0x89,0xc8,0x6e,0x7e,0x9e,0xe3,0xb4,0xa4,0xcb,0x56,0xeb,0xb,0x8a,0xa2,0x40,0x44,0x76,0xbd,0xf2,0x24,0x8b,0x8b,0x55,0xb8,0xa2,0xb6,0x79,0x6b,0xb4,0x22,0xc4,0xc4,0x8f,0x6b,0x4,0x98,0x55,0x20,0x5a,0x88,0x1a,0x26,0x80,0x64,0xb5,0x40,0xf3,0xa1,0x22,0xe1,0x41,0xbb,0x1f,0x59,0x76,0x25,0x93,0x59,0x15,0x28,0x1e,0x68,0xaa,0x51,0x5e,0xe9,0x21,0x8,0xe0,0x0,0x44,0xeb,0x55,0xd8,0xaa,0x40,0x15,0x11,0xf9,0x93,0xb1,0x92,0xae,0x95,0xa2,0x9a,0x9a,0x26,0x41,0x50,0x61,0xe2,0xb7,0xe0,0x13,0x5a,0x75,0x43,0xbf,0x2,0xd,0x12,0xd5,0xea,0xca,0xbd,0x6f,0xb2,0x85,0x20,0x74,0x41,0x9a,0x5d,0xe9,0xf0,0x5b,0xb6,0xa0,0x98,0x49,0x24,0xd9,0x53,0x45,0xbe,0x88,0xf5,0x15,0x11,0x10,0x5,0xd,0x5d,0xa8,0xd7,0x2,0x51,0x4c,0xb7,0xb5,0x51,0x62,0x44,0x4b,0xed,0xac,0x4f,0x1,0x5a,0xaf,0x54,0xe8,0x58,0xd2,0x7d,0xb0,0xdb,0x4f,0x22,0x1d,0x3f,0x34,0xfe,0xb2,0xb,0xff,0x62,0x9,0xd7,0xb4,0xff,0x83,0xc0,0xfa,0xcb,0xd4,0x69,0x6,0xd8,0x75,0x9,0x2a,0x5,0xa5,0x99,0xcd,0x9d,0x73,0x5b,0x51,0xce,0x39,0xcc,0x6c,0xe,0x94,0x80,0x26,0xfe,0xb8,0x14,0x65,0x59,0x9e,0xce,0xf3,0x19,0x7d,0x24,0xce,0x39,0xe6,0xf9,0x8c,0xb2,0x2c,0x4f,0xfd,0x84,0x52,0xf1,0x67,0x61,0x8,0xdc,0xdc,0x9b,0xdc,0x7d,0x99,0x26,0xe9,0xf3,0x24,0x49,0xc6,0x6d,0x4,0xaa,0xba,0x72,0xea,0x5e,0x9f,0xe5,0xdf,0x5e,0x0,0x4b,0x60,0x13,0xf,0xd5,0x81,0x9f,0x8d,0xc3,0x2d,0xb3,0x71,0xe3,0x67,0x63,0x1,0x38,0xe9,0x99,0xce,0x6d,0x23,0x42,0xfd,0xba,0x32,0x9d,0xe3,0xcf,0xc7,0x1a,0x59,0x9b,0x5f,0x83,0xc5,0xef,0x7e,0x3,0xcb,0x7b,0xfd,0x30,0x11,0x50,0x3,0x75,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xd,0xd7,0x0,0x0,0xd,0xd7,0x1,0x42,0x28,0x9b,0x78,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x13,0x37,0x38,0x1f,0x8c,0xe7,0x92,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0x3b,0x4e,0x3,0x41,0x10,0x84,0xe1,0x6f,0x4c,0x4b,0x1e,0xaf,0x36,0x20,0xde,0x11,0x9c,0x80,0xc7,0xd9,0x38,0x9,0x67,0x33,0x76,0x4c,0x82,0xd6,0x31,0x1,0x82,0xb1,0x34,0xc8,0x4,0x6c,0xbc,0x6b,0xc9,0x9,0x1,0x1d,0xb6,0xba,0xfe,0x52,0x4b,0x55,0x9,0x1d,0xae,0xd1,0xe3,0xa,0xc9,0xfc,0x9c,0xf0,0x8d,0xf,0xbc,0xc7,0x24,0x7e,0xc0,0xd,0xf2,0x99,0x80,0x8a,0x37,0xbc,0xc4,0xe4,0x7c,0x7b,0x7f,0xf7,0xf8,0x5c,0x86,0xb2,0x89,0x88,0x59,0x40,0x6b,0xed,0x34,0x1e,0xc6,0xaf,0xdd,0x7e,0xfb,0x84,0xd7,0x40,0x60,0x5d,0x86,0xd2,0xd5,0x5a,0xd5,0x5a,0x67,0xed,0x73,0xce,0xa9,0xc,0xa5,0xdb,0xed,0xb7,0x6b,0xc4,0x6a,0xda,0xa7,0x88,0x58,0x14,0x43,0xad,0x55,0x44,0x30,0xbd,0xba,0x9a,0x3f,0x5f,0x9e,0x7f,0xc0,0x5f,0x2,0x9c,0x5a,0x6b,0x72,0xce,0x8b,0x82,0x9c,0xb3,0xd6,0x1a,0xbf,0x91,0x16,0x68,0x38,0x8e,0x87,0xf1,0xb3,0xc,0x65,0xd3,0xf7,0xfd,0x59,0x51,0xc6,0x11,0x2d,0x61,0x70,0x41,0x99,0x92,0xb,0xeb,0xfc,0x3,0x18,0xa7,0x44,0x3f,0xdc,0xad,0xd9,0x96,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char tab_current_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4f,0x0,0x42,0x0,0x57,0xa5,0xf1,0xe9,0x1e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x10,0x28,0x1b,0x23,0x62,0xd3,0x88,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x4a,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x92,0x31,0x4a,0x3,0x51,0x14,0x45,0xcf,0x1b,0x82,0x4,0x5b,0x65,0x24,0x24,0x44,0x52,0xd9,0x9,0xae,0xc0,0xca,0xca,0x2a,0xcb,0x70,0x1,0xba,0x8,0x37,0xe0,0x32,0x52,0x59,0x59,0xb9,0x2,0xc1,0xce,0x46,0x11,0x2,0x41,0x31,0x85,0xc5,0x24,0x41,0x98,0x77,0x2d,0xfe,0x9f,0x9f,0x2f,0x93,0x62,0xc0,0xc7,0x14,0x7f,0xe6,0xde,0x77,0xdf,0xbd,0x6f,0xbe,0x49,0x62,0x74,0x74,0x3c,0x5,0xae,0x80,0xb,0xba,0xd5,0x3,0x70,0x37,0xff,0x78,0x9f,0xd9,0xb0,0x1c,0x5f,0x97,0x7,0x83,0xdb,0xd3,0x93,0x33,0x6,0x87,0xa3,0x4e,0xdd,0x8b,0xaf,0x39,0xcf,0x2f,0x4f,0x7c,0x2e,0x17,0x37,0x36,0x2c,0xc7,0xaf,0x97,0xe7,0xd3,0xc9,0xe6,0x67,0xc3,0x6a,0xb3,0xea,0x24,0xb0,0xdf,0xdf,0xa7,0xbf,0xd7,0xe7,0xfe,0x71,0xf6,0xd6,0x3,0x26,0xcb,0xef,0xe5,0xe,0x9a,0x10,0x6,0x80,0x21,0x88,0x67,0x80,0x6a,0x5d,0x51,0xad,0x2b,0x80,0x49,0xf,0xc0,0x25,0x70,0x41,0x11,0xe8,0xe6,0x42,0x10,0xdf,0x41,0x2e,0xc,0xa1,0xc2,0x0,0x81,0x3,0x45,0x10,0xc,0x2,0x75,0x1d,0xf4,0xeb,0x30,0x48,0x8a,0xa3,0xea,0xdc,0xf,0xa1,0x31,0x62,0x8a,0x58,0xaf,0x81,0x3d,0xb2,0x4c,0x89,0xd3,0xaa,0x84,0xd9,0x36,0x50,0x74,0xe0,0x1,0x25,0x24,0xc1,0x2c,0xe6,0xce,0x1d,0x4,0x6b,0x16,0x53,0x48,0x79,0x4,0x3c,0x4d,0xf,0x3c,0x6d,0x6d,0xc7,0xf5,0x35,0x2b,0x95,0x43,0xe8,0x55,0x26,0x20,0x6f,0x59,0xf,0x13,0xe3,0xd9,0x9a,0xbf,0x12,0xfb,0xd4,0x7c,0x8b,0x2,0x72,0x25,0xa2,0x79,0xb4,0xd1,0x56,0xc,0x22,0x66,0x1,0x52,0x2e,0x20,0xc7,0x5,0x96,0x86,0x2a,0x3e,0xf1,0x1e,0x28,0x53,0x92,0x12,0x77,0x1b,0xc1,0x95,0x5d,0x9e,0xb4,0xf3,0xd4,0xe8,0x59,0x66,0x23,0x2c,0xf0,0x8f,0x3,0xc7,0x91,0xda,0x37,0x71,0xd7,0xb1,0x71,0xd1,0x38,0x28,0x12,0x6e,0x74,0x2f,0xcb,0xfe,0xd0,0xb0,0x1c,0x8b,0x7f,0xd4,0x2f,0xdd,0x10,0xa9,0xd4,0xe9,0xbe,0xe5,0x86,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x13,0x39,0x1d,0xca,0xb,0x1e,0x5b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x8e,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x8f,0x3d,0xe,0xc2,0x30,0x18,0x43,0x5f,0x8a,0xa5,0x86,0x88,0x81,0xb9,0x11,0x9c,0x80,0x9f,0xb3,0x71,0x12,0xce,0x56,0xda,0x99,0x5,0x95,0x99,0x1,0xa9,0xdf,0x10,0x54,0x96,0xcc,0x29,0x23,0x43,0x3d,0x5a,0xf6,0xb3,0xec,0x80,0x0,0x6c,0x81,0xd,0xb0,0x2,0x1c,0x65,0x4d,0xc0,0x7,0x78,0x3,0x2f,0xe5,0xf2,0x9,0xd8,0x1,0xfe,0x47,0x80,0x1,0xf,0xe0,0xa6,0xbc,0xbc,0x3f,0x1e,0xce,0xd7,0xd8,0xc4,0xb5,0xa4,0x22,0x20,0xa5,0x34,0xd,0xcf,0x61,0xec,0xfa,0xf6,0x2,0xdc,0x5,0x8,0xa8,0x63,0x13,0x83,0x99,0x61,0x66,0xc5,0x79,0xef,0xbd,0x8b,0x4d,0xc,0x5d,0xdf,0xd6,0x80,0xaa,0xec,0x3b,0x49,0xb3,0x65,0x0,0x33,0x43,0x12,0xe4,0xab,0x55,0x39,0x3e,0xaf,0x5,0xb0,0x0,0xfe,0x3,0xf0,0x5,0xd9,0x71,0x24,0x5d,0x58,0x1b,0x63,0x82,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char toggle_off_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0xa2,0x9d,0x7e,0x84,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0x5,0xb,0x18,0x54,0xf9,0x2b,0x70,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x6,0xd4,0x49,0x44,0x41,0x54,0x68,0xde,0xed,0x98,0x5d,0x8c,0x55,0x67,0x15,0x86,0x9f,0xf5,0xed,0xbd,0xcf,0xef,0x9c,0x33,0xce,0x3f,0xc3,0x88,0x14,0xa1,0x88,0x5a,0x63,0x8d,0xe5,0xce,0x26,0x6a,0x1a,0xef,0x1a,0xb5,0xa,0x5c,0x18,0xf4,0xc2,0x68,0x6c,0x2a,0xc4,0xc4,0x14,0xe4,0xaa,0x29,0x51,0xd3,0xb,0xb5,0x4d,0x40,0xaa,0x16,0x2f,0x8c,0x97,0xd4,0x68,0x62,0x62,0xac,0x26,0x46,0x6d,0xc7,0x26,0x25,0x1,0x2b,0x43,0xab,0x29,0xc8,0xcc,0x0,0x33,0x40,0x99,0x99,0xce,0xdf,0x39,0x67,0xe6,0xec,0x6f,0x2d,0x2f,0xf6,0x3e,0x87,0x19,0x60,0x60,0xfe,0xee,0x9c,0x95,0xec,0xe4,0x64,0xef,0x9c,0x6f,0x7f,0xfb,0x5d,0xef,0xfb,0xae,0xb5,0x3e,0xd8,0x88,0x8d,0xd8,0x88,0x8d,0xf8,0x3f,0xe,0x59,0xea,0x41,0x67,0x67,0x57,0x6b,0x47,0x5b,0xd7,0xd1,0x6c,0x36,0xfb,0x94,0x13,0x9,0x40,0xb0,0x35,0xbc,0xc8,0x1,0x5e,0x3d,0xd5,0x5a,0x15,0xef,0x3d,0x22,0xe9,0xab,0xcd,0xd6,0xe9,0x4b,0x24,0x5d,0xce,0x10,0xc0,0x4,0xf,0x5c,0xc0,0x78,0x1e,0xb3,0x5f,0xfd,0x77,0xe8,0x62,0x6d,0xd9,0x0,0x74,0x77,0x76,0xb7,0xf7,0xf4,0x6c,0x7e,0xe3,0xa1,0xf,0x7f,0x7c,0x7b,0xdf,0xa6,0x2d,0x1a,0x4,0x81,0x53,0x5d,0xe3,0xfe,0x9c,0xa0,0xbe,0xce,0xb5,0x9b,0xd7,0x38,0x37,0x70,0x86,0xb8,0x3e,0x7f,0xb,0x84,0x75,0x8,0x4b,0x3f,0x46,0x53,0x40,0xcd,0x14,0x33,0xc3,0xab,0xa2,0x5e,0x7f,0xaf,0x6a,0xfb,0x2e,0xd,0x5f,0xac,0xde,0xfe,0xbf,0xf0,0x6e,0x8b,0xb5,0xb5,0x75,0xbc,0xf0,0x91,0x5d,0x1f,0xdb,0x5e,0x88,0xca,0xb3,0x3,0x3,0x3,0x45,0x1f,0x2b,0x26,0xc6,0x6a,0x29,0x20,0x92,0x24,0x3a,0xc,0x43,0x36,0xf7,0x6e,0x66,0xd7,0xce,0x87,0x18,0x78,0xeb,0x2c,0xe2,0x1c,0xd6,0xdc,0xfa,0x1a,0x69,0x6c,0xa,0x6,0x4e,0x4,0x35,0x43,0x10,0x10,0xd1,0x30,0x90,0x99,0x18,0x1e,0x37,0xf4,0x49,0xe0,0x27,0xcb,0x2,0x20,0x8a,0xb2,0xfb,0x3b,0xca,0x5d,0x7a,0xe1,0x9d,0xb,0xc5,0x42,0xb1,0x8,0xd9,0xf5,0x4b,0xd3,0x95,0x2b,0x57,0xf8,0xe0,0xf6,0x6d,0xb8,0x20,0x24,0x10,0x41,0x4d,0xd7,0x85,0x9,0x66,0x1,0x90,0x80,0x80,0x25,0x74,0x55,0x55,0x67,0x4a,0x29,0x8,0x2,0xf3,0x5e,0xbf,0xbb,0x6c,0x0,0x4c,0xd5,0x2a,0x95,0xaa,0x73,0xa1,0x43,0x53,0x2a,0xb1,0x26,0x7,0x90,0x26,0x13,0x5c,0x20,0xd4,0xaa,0x35,0x7c,0xec,0x9,0x73,0x11,0xe2,0xa5,0x9,0x80,0x99,0x21,0x69,0x6,0x4d,0x93,0xf7,0x3a,0xe7,0x70,0xce,0x61,0x66,0xcd,0x2b,0x11,0x39,0xcd,0xfb,0x89,0x8f,0x24,0x60,0x3a,0xe7,0x70,0x12,0x60,0xd,0x60,0x1d,0x22,0xc9,0xd6,0x7b,0xef,0xb6,0xb3,0xbb,0x3,0x80,0x89,0x6a,0x8c,0xaa,0xa2,0xea,0xd3,0xcd,0xaf,0x3e,0x4b,0x6a,0x1e,0x2c,0x59,0xc3,0xcc,0x50,0xef,0x31,0x8c,0x40,0x1c,0x38,0x43,0x24,0x91,0x42,0x80,0xc3,0x7b,0x4f,0x4b,0xa1,0x40,0xa9,0x54,0x42,0x44,0x98,0x9d,0x9d,0x65,0x6a,0x7a,0x8a,0x28,0x8a,0x28,0x16,0x8a,0x4,0x41,0xd8,0x4,0x6a,0x72,0xf2,0x3d,0xf2,0xf9,0x2,0xb9,0x6c,0x86,0x58,0xd,0x11,0xa8,0x54,0x66,0xa9,0x56,0x6b,0x38,0x9,0x20,0x0,0xf5,0xda,0x10,0x99,0x2c,0x1b,0x80,0x84,0x3e,0xb6,0x8,0x75,0xf5,0xa9,0xf,0xac,0x82,0xf6,0x41,0x10,0x34,0x7f,0xab,0x6a,0x6a,0x54,0x86,0x10,0x20,0x2,0x92,0x28,0x16,0x55,0x25,0x9f,0x2f,0x72,0xe3,0xdd,0x1b,0xfc,0xe3,0x8d,0xd7,0x1,0xe3,0xfd,0xbd,0x5b,0xd8,0xfa,0x81,0xad,0x4c,0x4f,0x4d,0x33,0x3c,0xf4,0x36,0x95,0x6a,0x25,0x65,0x89,0xf2,0xe0,0xf6,0xf,0x31,0x38,0x3c,0xc8,0xf8,0xf8,0x18,0x61,0x18,0x52,0xaf,0x7b,0x7a,0x37,0x6d,0xa2,0xad,0xad,0x8d,0x7a,0xbd,0x9e,0xac,0x9b,0xae,0x7f,0xaf,0xea,0xb4,0x64,0xd6,0x14,0x8f,0x99,0x7,0x31,0xca,0xad,0x65,0x5a,0xcb,0xad,0x2b,0xbe,0xda,0xda,0xde,0x87,0xb,0x4,0xc3,0x63,0x28,0x8a,0x4f,0x19,0x91,0x50,0xdf,0x89,0x43,0x24,0xf9,0x5d,0xc8,0x17,0x18,0xbd,0x36,0xc2,0x93,0xdf,0xfe,0x56,0xd3,0xc5,0x8f,0xbf,0x78,0x8c,0xab,0x23,0x57,0xd9,0xd4,0xbb,0x89,0x53,0xbf,0x3d,0xc5,0x9b,0xe7,0xdf,0xe4,0xf4,0x99,0xd3,0x9c,0x3b,0x7f,0x8e,0x72,0x6b,0x89,0x67,0x9e,0x7d,0x86,0xc1,0xcb,0x83,0xbc,0xda,0xff,0x2a,0x6f,0xfd,0x7b,0x80,0x2f,0x7c,0xf1,0xf3,0xcc,0xcc,0xcc,0x90,0xcd,0x64,0x52,0xf1,0xb9,0x44,0x7b,0x4b,0x30,0x38,0x5c,0xc2,0x51,0x1a,0xe5,0x3,0x1f,0x18,0xaa,0x31,0x97,0xaf,0xe,0xae,0xd8,0x5,0x4,0x41,0x55,0x29,0x16,0x5b,0x88,0xc2,0x8,0xcc,0xa3,0xaa,0xc4,0xea,0x53,0x11,0x3,0xde,0x40,0x84,0x28,0x8a,0x18,0x1a,0x1e,0xe4,0xc0,0x77,0xe,0x70,0xf0,0xe0,0x41,0xbe,0xf4,0xc4,0x1e,0xa6,0xa7,0xa6,0x78,0xe9,0xe4,0x2f,0x78,0xe1,0xd8,0xf3,0x1c,0x39,0x74,0x84,0x47,0x3e,0xf9,0x8,0x47,0x9f,0x3d,0xca,0xc4,0xc4,0x4,0xce,0x39,0xe6,0xe7,0xe6,0xd9,0xdc,0xbb,0x99,0xf3,0xe7,0x6,0xf8,0xf9,0xcf,0x5e,0x22,0x97,0xcf,0x31,0x3e,0x36,0x41,0x14,0x45,0x78,0x6b,0x10,0xdf,0xb8,0x17,0x71,0xc3,0xa5,0x68,0xab,0xaa,0x49,0xc6,0xcc,0x23,0xe,0xba,0xba,0x7a,0x56,0x45,0x7f,0x71,0xc2,0x5c,0xad,0x86,0xf7,0x9a,0x96,0xc3,0x86,0xc1,0xa5,0x89,0x71,0x49,0xf6,0xe7,0xe7,0xe7,0x68,0x29,0xb5,0xb0,0x77,0xef,0x1e,0x8e,0x1f,0xfb,0x29,0xff,0x3a,0xfb,0x4f,0xa,0xc5,0x22,0x87,0x9e,0x3e,0xcc,0x89,0x17,0x8f,0xb3,0x63,0xc7,0xe,0x26,0xa7,0x26,0xc9,0x44,0x11,0xf9,0x7c,0x9e,0xa1,0xa1,0x61,0xe6,0xe6,0xe7,0x10,0xc0,0xb9,0x80,0x28,0xc,0x29,0x95,0x5a,0x78,0xed,0xaf,0xfd,0x74,0x75,0x77,0x50,0xad,0xd5,0x8,0xc4,0x11,0x37,0x4c,0x73,0x25,0x0,0x58,0x43,0x2,0x9a,0x6c,0x56,0x81,0x5a,0xad,0xb2,0xea,0x7a,0xad,0x3e,0xad,0x24,0x22,0xa9,0x7,0xf8,0xe6,0x8b,0x9a,0xd,0x8c,0x2a,0xb9,0x5c,0x8e,0x28,0x13,0x31,0x72,0x75,0x84,0xee,0x9e,0x1e,0x9c,0x73,0x54,0xab,0x35,0xf2,0x85,0x3c,0x85,0x62,0x91,0xd9,0xd9,0xa,0x7b,0xf6,0xed,0x23,0x8e,0x63,0xce,0x9c,0x39,0xc3,0x89,0x63,0x27,0xf0,0xde,0xf3,0xf0,0x27,0x1e,0x66,0xff,0xd7,0xbe,0x4a,0x5f,0x5f,0x1f,0xaf,0xfc,0xe1,0xcf,0x4,0x41,0x98,0x76,0x83,0xd6,0x64,0x80,0xac,0x18,0x0,0x55,0xcc,0x14,0x4d,0xaf,0xd9,0x4a,0x6d,0x55,0xc5,0x4f,0x4d,0xc9,0x65,0xf3,0x38,0xe7,0x10,0x24,0x59,0x53,0xd,0x93,0x85,0x8a,0x33,0x32,0x99,0xc,0xa3,0xa3,0xa3,0x5c,0xb9,0x7c,0x85,0xc7,0x3e,0xf7,0x18,0x27,0x4f,0x9e,0x24,0x74,0x21,0x87,0x8e,0x3c,0xcd,0xf5,0xeb,0x37,0x18,0x1e,0x1e,0xa2,0xbd,0xbd,0x8d,0xaf,0x3c,0x75,0x80,0x9b,0xef,0xde,0x24,0xf6,0x31,0x81,0xb,0x70,0xce,0xf1,0xf2,0xa9,0xdf,0xf0,0xdc,0xf,0x9f,0x23,0x9b,0xc9,0x52,0x2e,0x97,0xa9,0x54,0x2a,0xcd,0x8a,0x73,0xbf,0x8,0x97,0xe2,0xae,0xa9,0xc7,0xab,0xc7,0xa9,0xc3,0x89,0xd0,0xdd,0xd9,0x85,0x89,0xac,0xa0,0x1f,0x48,0xda,0xbf,0x20,0x70,0x4c,0x4f,0x4f,0x13,0xc7,0x1e,0x91,0x64,0x1e,0xb0,0x86,0x7,0xdc,0xe6,0x17,0xad,0xad,0xad,0x7c,0xff,0xe8,0xf,0x78,0xf9,0x77,0xa7,0xf8,0x7b,0xff,0xdf,0x98,0x18,0x1b,0xe7,0x53,0x8f,0x3e,0xca,0x37,0xbe,0xfe,0x4d,0xcc,0x1b,0xed,0xed,0xed,0xe4,0xb2,0x39,0x72,0xb9,0x1c,0xd5,0x6a,0x15,0xe7,0x1c,0x3d,0x3d,0x3d,0x89,0x87,0x64,0x32,0x64,0x32,0xd9,0x66,0xc9,0x36,0x6b,0x34,0x45,0xf7,0xde,0xf3,0x5d,0x99,0xb1,0x6b,0xe7,0x47,0x6d,0xe7,0xb6,0x5d,0xdc,0x18,0xbb,0x41,0x26,0xca,0x60,0x6a,0xcc,0xc5,0xb5,0x55,0xf5,0x42,0x66,0x46,0x36,0xca,0x25,0x5a,0x47,0x98,0xaf,0xcf,0xd3,0xd3,0xd9,0xcd,0x7f,0x2e,0xbd,0x4d,0x6b,0xa9,0x8c,0xda,0xad,0x21,0xc3,0x39,0xa1,0x5e,0x8f,0xe9,0xec,0xec,0x64,0xf7,0xee,0xdd,0xb4,0xb4,0xb4,0xd0,0xdf,0xff,0x1a,0x23,0x23,0xa3,0x44,0x99,0x88,0xbe,0xbe,0x3e,0x46,0x47,0x46,0x51,0x4d,0xe4,0x99,0xc,0x6d,0x1d,0x78,0xaf,0x8c,0xdd,0x1c,0x6f,0x66,0xdd,0x50,0x4c,0xd,0x53,0xf0,0x16,0x83,0x41,0xa5,0x56,0xe5,0xe2,0xa5,0x77,0x64,0xd9,0xc,0x50,0x8b,0x11,0x34,0x69,0x2f,0xc5,0xc8,0x65,0xb2,0xf7,0xac,0xa7,0xf7,0x82,0x58,0x55,0x13,0x56,0x25,0x8e,0x80,0x27,0x4e,0x8d,0xd6,0x50,0xbd,0x55,0xa1,0xbc,0x1a,0x4e,0x2,0xa6,0xa7,0x66,0x78,0xe5,0x8f,0x7f,0x6a,0x4a,0x23,0x70,0x21,0xbe,0xae,0x8c,0x5e,0xbd,0x4e,0x1c,0xfb,0x45,0xd4,0x9e,0x18,0x9f,0x4c,0xd,0x75,0x21,0xe5,0xd,0x4b,0x8b,0xee,0x2d,0x51,0xaf,0x48,0x2,0xe0,0x4d,0xf1,0xb1,0xe1,0x5c,0x82,0xe6,0x7a,0xc,0xdd,0x22,0x92,0x7e,0xb4,0x2d,0xd8,0xd2,0x9d,0xc3,0x50,0xbd,0x5e,0x4f,0x3c,0x43,0x84,0x7a,0xbd,0xbe,0xe0,0xfe,0xfc,0x1d,0x4b,0xc7,0x71,0xdc,0x64,0x5a,0xca,0xf9,0x45,0x13,0xb6,0xe9,0xaa,0x3c,0x0,0x53,0x53,0xf1,0x96,0x78,0x80,0xb1,0x46,0x0,0xec,0x96,0xce,0xbd,0x25,0x8d,0x90,0x60,0x69,0xb3,0xe3,0xb1,0xbb,0x30,0x4b,0xbd,0x5f,0x11,0xbe,0xd6,0x4,0x21,0x61,0x16,0x8d,0x2e,0x56,0x34,0x99,0x15,0x96,0x30,0xc4,0x70,0xc9,0x9,0x56,0x9c,0x9a,0x99,0x5b,0xaf,0xf3,0x8a,0x46,0x96,0x4c,0x9b,0xd,0x40,0x5a,0x61,0x6c,0x71,0x3d,0xbc,0x9d,0x14,0xf7,0x99,0x96,0xc5,0x1a,0x7e,0x2b,0x69,0xa2,0x52,0x6,0x34,0x86,0x38,0xc3,0x2c,0x61,0xdc,0xb5,0x65,0x3,0xe0,0x55,0x7f,0x5d,0xa9,0xcc,0xec,0x2f,0x97,0xca,0xb3,0xd3,0xd3,0x93,0xc5,0xb5,0xce,0xeb,0xb,0xa9,0x50,0x2a,0x95,0x99,0x9d,0x9d,0x21,0x70,0x82,0xf7,0x7e,0xb1,0x44,0xed,0x4e,0xd6,0xdc,0x47,0xc2,0xc9,0xa3,0x14,0x43,0x5d,0x30,0xe,0xa7,0x8c,0x30,0x60,0x26,0xf6,0xbe,0x24,0x22,0x3f,0x5e,0x76,0x15,0xd8,0xb1,0xed,0xc1,0x8e,0x42,0xb1,0x78,0xb6,0xa5,0x50,0xda,0x52,0x2c,0x16,0x54,0xd5,0xdc,0x7a,0x7c,0x7e,0xd2,0xbe,0xce,0x31,0xf6,0xde,0x38,0x4e,0x58,0xdf,0x13,0xa1,0xc6,0x51,0x98,0xa5,0x16,0xa8,0x4a,0xec,0x3d,0xf5,0xf9,0x79,0x4a,0xe5,0xf2,0x5f,0xa2,0x5c,0xee,0xf1,0xd3,0xa7,0x5f,0xaf,0x2c,0xfb,0x4c,0xf0,0xcb,0x4f,0xec,0xed,0x1c,0x19,0x19,0xf9,0xd1,0xd8,0xd8,0xf8,0x7e,0xc0,0x9,0xeb,0x61,0x3,0x86,0xf7,0xbe,0x39,0xce,0xb2,0x8e,0xfa,0xb2,0x5,0x5e,0xd0,0xb0,0x91,0x28,0x8a,0x86,0x1e,0x78,0x60,0xeb,0x2f,0x3f,0xf3,0xd9,0x4f,0x1f,0x3f,0xfc,0xbd,0xc3,0x93,0x1b,0x47,0xc0,0x1b,0xb1,0x11,0x1b,0xb1,0x11,0x1b,0xb1,0x38,0xfe,0x7,0x2f,0xf4,0xda,0xd3,0xbb,0x47,0x75,0xc1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0xa2,0x9d,0x7e,0x84,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x17,0x2,0x16,0xe9,0x0,0x17,0x60,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x45,0x49,0x44,0x41,0x54,0x68,0x81,0xed,0x99,0x5f,0x4f,0xd3,0x50,0x18,0x87,0x9f,0xb3,0x96,0xb5,0xcc,0x3a,0xa6,0xac,0x6d,0xa,0x91,0x84,0x5b,0x8d,0x7e,0x21,0x60,0x2c,0x5c,0x1a,0x63,0xe2,0x27,0x31,0x31,0xc6,0x4b,0x32,0xa7,0x7e,0x20,0x84,0x6b,0x6f,0xc,0x90,0x6d,0x32,0xca,0x6c,0xb0,0x24,0x75,0xc7,0x8b,0xba,0xb9,0x35,0xdd,0x84,0xec,0xe0,0x26,0xed,0x73,0xd7,0xf7,0xed,0xce,0x7b,0x7e,0xbf,0xbe,0x67,0x7f,0xde,0x41,0x4e,0x4e,0xa6,0x11,0x89,0xeb,0x12,0x50,0x1,0x2c,0x40,0x4b,0xc9,0xff,0xaf,0x48,0xe0,0x27,0x10,0x0,0x3e,0x70,0x39,0x48,0xe8,0x89,0x1b,0x2b,0xc0,0x33,0xe0,0x11,0x60,0x72,0xb7,0xc,0x8,0x81,0xaf,0xc0,0x67,0xa6,0x18,0x60,0x1,0x1b,0x4f,0x1e,0x3f,0x7d,0x6d,0x57,0xed,0x65,0x40,0x48,0x64,0xfc,0x72,0x95,0x8,0x10,0x8,0x74,0x5d,0x67,0x69,0x49,0x47,0xd3,0x92,0xdb,0x50,0x4b,0x14,0x45,0xf2,0xf8,0xe4,0xf8,0xc7,0xe1,0xd1,0xc1,0x2b,0xe0,0xcb,0x68,0x2e,0x59,0x59,0x7,0xc,0xbb,0x6a,0x97,0xce,0xba,0x67,0x4,0x41,0x80,0xec,0xf7,0x91,0x8a,0x1d,0x10,0x8,0x44,0xa1,0x80,0x51,0x2c,0x52,0x2a,0xdd,0xa3,0x58,0x2c,0x2a,0x5d,0x3f,0x89,0x69,0x9a,0x62,0x7d,0x6d,0xbd,0x74,0x78,0x74,0x60,0x90,0xd0,0x9c,0x66,0xbd,0x0,0x8,0x82,0xef,0x54,0x2a,0xf,0x70,0x6c,0x7,0xa1,0xf8,0x24,0x48,0x24,0xed,0x4e,0x1b,0xdf,0x3f,0xc7,0x30,0x4c,0xa5,0x6b,0xa7,0x11,0x86,0x21,0x96,0x65,0x41,0xca,0x91,0x4e,0xed,0x3d,0x29,0x25,0xb2,0x2f,0x71,0x1d,0x97,0x30,0xc,0x39,0x6d,0x9d,0x2a,0xdd,0x90,0xe7,0x7a,0xb8,0x8e,0xcb,0x79,0xb7,0xab,0xbc,0xbb,0x6e,0x4a,0x61,0x52,0x62,0x70,0xf6,0x55,0x8b,0x87,0xdf,0x6b,0x4a,0xe6,0x2e,0x1e,0xa6,0x18,0x90,0x15,0x32,0x6f,0xc0,0xed,0x7e,0xfe,0xcc,0x80,0x65,0x59,0xd4,0xf7,0x6a,0x63,0xb1,0xc6,0x7e,0x93,0x20,0x8,0x78,0xf1,0xf2,0xf9,0x58,0xfc,0xed,0x9b,0x77,0xa9,0xb1,0xeb,0xb0,0xb0,0x6,0xc,0xc4,0x7f,0x78,0xff,0x9,0x80,0x9d,0xdd,0x2d,0xea,0x7b,0xb5,0xa1,0xb0,0x34,0x81,0xd7,0x15,0x3d,0xca,0xc2,0x1a,0x0,0xd0,0x6c,0x7c,0xa4,0xd7,0xeb,0x1,0xb1,0x11,0x3b,0xbb,0x5b,0xc3,0xdc,0xe8,0x13,0x1f,0x8,0x4f,0x8b,0xfd,0x8d,0x85,0x36,0x60,0x1a,0xaa,0x3a,0x60,0xa1,0xdf,0x4,0x6b,0xf5,0x6d,0xca,0xe5,0x32,0xe5,0x72,0x79,0xec,0xe9,0xab,0x24,0x69,0x80,0x9,0xac,0xdc,0x4a,0xa5,0x1b,0xd2,0xd8,0x6f,0x2,0xb1,0x9,0xb5,0xfa,0xf6,0x58,0x6c,0x6,0x56,0x88,0x35,0xe,0x49,0x1e,0x81,0x10,0xb8,0x98,0xb5,0x8a,0xa,0x82,0x20,0x98,0xd8,0xd2,0x33,0xb4,0xff,0x5,0xb1,0xc6,0x21,0xb,0x7d,0x4,0xfe,0x5,0xb9,0x1,0xf3,0xde,0xc0,0xbc,0x99,0x68,0x80,0x88,0xa7,0x16,0x78,0xae,0xa7,0xbc,0xa8,0xe7,0x7a,0xc3,0xa1,0xc8,0xbc,0x49,0xfd,0x1e,0x20,0x84,0x40,0x14,0x4,0xad,0x76,0xb,0xc7,0x76,0xd8,0xdc,0xd8,0x54,0x5a,0x54,0x22,0x69,0xb5,0x5b,0x88,0x82,0x98,0xbb,0x9,0x69,0x6,0x48,0x0,0xcb,0xba,0x8f,0xef,0xfb,0xb7,0xf2,0x9b,0xfd,0xcf,0x44,0xc8,0x40,0xd3,0x34,0xa5,0x6b,0xa7,0x61,0x9a,0x26,0x51,0x14,0x41,0xca,0x70,0x2f,0x69,0x40,0x4,0x5c,0x75,0xbe,0x75,0x2e,0xed,0xaa,0xbd,0xbc,0xfa,0x70,0xf5,0x4e,0xcd,0x4,0x81,0x2b,0x62,0x8d,0xa3,0x5b,0x19,0x63,0x8d,0x6c,0x4c,0x85,0x4f,0x6,0x89,0xcc,0xff,0x2f,0x90,0x93,0x93,0x93,0x6d,0x7e,0x1,0x6b,0xe,0xc1,0xdb,0xd6,0xe0,0xc4,0xba,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char toggle_on_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0xa2,0x9d,0x7e,0x84,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x17,0x5,0xb,0x2,0xa9,0x9b,0xd2,0xa,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x6,0xd6,0x49,0x44,0x41,0x54,0x68,0xde,0xed,0x98,0x5d,0x8c,0x5d,0x55,0x15,0xc7,0x7f,0x6b,0x9d,0x73,0x3f,0x66,0xe6,0xce,0x74,0x7a,0x67,0x86,0x34,0xb6,0xb5,0x2d,0x23,0x6d,0xd1,0xe8,0x60,0x6a,0xa9,0x50,0x3e,0xd4,0x18,0xe3,0xb,0x49,0x1f,0x68,0xc5,0x7,0xe3,0x77,0x20,0x1,0x63,0x1a,0x51,0xf1,0x85,0xc4,0x68,0x22,0x98,0x9a,0xbe,0x88,0xa,0x8d,0x40,0xf4,0xa1,0x32,0xb5,0x4a,0xa8,0x81,0x4,0xc4,0x92,0x34,0xb1,0x26,0x90,0x48,0xa1,0xcd,0x50,0x4b,0x9,0x76,0xda,0x32,0xd5,0x69,0x99,0x99,0x76,0xee,0xbd,0xe7,0x63,0xef,0xe5,0xc3,0x39,0x77,0xa6,0xa5,0x33,0x30,0x77,0x66,0xde,0x9c,0x95,0xec,0x87,0xc9,0xb9,0xe7,0xcc,0xde,0x6b,0xfd,0xff,0xff,0xf5,0x5f,0x1b,0x96,0x62,0x29,0x96,0x62,0x29,0xfe,0x8f,0x43,0x66,0x7b,0x70,0xed,0x9a,0xfe,0x32,0x22,0x5f,0x45,0xd8,0x9,0x7c,0x44,0x8c,0xc0,0x0,0x91,0xfc,0x15,0xb3,0x45,0xdd,0x81,0x77,0x1e,0xf5,0x55,0xba,0x8b,0xeb,0x50,0x3a,0x0,0xcb,0x1f,0xce,0xff,0xff,0x38,0x6a,0xee,0x52,0xed,0xc2,0x23,0x27,0x46,0x8e,0x3e,0x68,0x9c,0x1b,0x9f,0x73,0x2,0xd6,0x7d,0xb8,0xbf,0x4d,0x55,0x9e,0xd2,0x40,0xef,0x8,0x54,0x11,0x11,0x44,0x14,0x0,0x15,0x99,0xda,0xda,0x62,0x65,0xc0,0xb9,0x94,0x36,0xeb,0xe7,0x2b,0x5f,0x7a,0x80,0x9b,0x6f,0xda,0x4a,0x67,0xe7,0x82,0xce,0xd,0x92,0xd5,0x67,0x72,0x12,0x7f,0xf0,0xd0,0xf3,0xba,0x77,0xf0,0xd7,0x27,0x5f,0x7f,0xeb,0x1f,0x37,0x3a,0x46,0x2e,0xbc,0xf7,0xa7,0xe1,0x8c,0xef,0xab,0xdc,0xa7,0x81,0xde,0x11,0x6,0xc1,0x4,0x48,0x45,0x40,0x9b,0x87,0x47,0x40,0x10,0x24,0x4f,0xc4,0x42,0xa,0x6f,0x1e,0x54,0x8d,0xb4,0xd6,0xcb,0x97,0xef,0xba,0x9f,0x4d,0x9f,0xd8,0xca,0xab,0x87,0xc6,0x68,0xd4,0xd3,0x45,0x41,0x56,0xb1,0xa8,0xfa,0xd9,0x9b,0xbe,0x70,0x9,0xa7,0xfd,0xf5,0xdf,0x4d,0xfc,0xe2,0xf8,0xb9,0x91,0xaf,0xcf,0x29,0x1,0xc0,0xce,0x20,0x8,0xc,0x93,0x4e,0x51,0x11,0x55,0xcd,0x2a,0x9e,0xa3,0x20,0x43,0xc4,0xc2,0x71,0x60,0x18,0x41,0x41,0xa9,0xc8,0x6a,0xb6,0x6c,0xbe,0x9d,0xd7,0xfe,0x3e,0x4a,0xb1,0x58,0xa2,0xa3,0x23,0x5c,0x14,0x6c,0x79,0x6f,0x1c,0x7e,0xe9,0x3f,0x95,0xdb,0x3f,0xf3,0x79,0x3f,0xb8,0xef,0xb7,0x5f,0x3,0xe6,0x9c,0x80,0x15,0x8a,0x8,0x2a,0xf9,0x61,0xa7,0x17,0x48,0x4e,0x3,0x8f,0xf7,0x86,0xf7,0x1e,0x11,0x41,0x73,0xaa,0x98,0x19,0x66,0x36,0xf5,0xfb,0xe6,0x73,0x11,0x99,0x86,0x75,0x33,0x6f,0x2a,0x88,0x82,0x4f,0x3,0x48,0x20,0x8d,0x3c,0x81,0xa,0x8e,0xc5,0xd1,0x17,0x11,0xc1,0x25,0xe0,0x62,0x54,0x5c,0x69,0xc6,0x8f,0x86,0xb3,0xa0,0x47,0xc8,0x37,0xad,0x81,0xa2,0x28,0x48,0x93,0x2,0x92,0xef,0x5d,0xe9,0x5e,0xd6,0x45,0xb9,0xdc,0x86,0x73,0x29,0xef,0x8e,0xbd,0x8b,0xf3,0x9e,0x72,0xb1,0x44,0xa9,0x54,0xe6,0xd2,0xc5,0x8b,0x78,0xef,0x59,0xbe,0x7c,0x39,0x8d,0x7a,0x9d,0x38,0x8d,0x91,0x8c,0x49,0xd3,0x8,0xf0,0x10,0xa8,0x91,0x9a,0x90,0x46,0xe0,0x12,0xc3,0x7,0x1e,0xb0,0x5,0x61,0xcb,0x2e,0x4f,0x40,0x6c,0xa4,0x11,0x98,0x89,0xcc,0x39,0x1,0x57,0xf0,0xdd,0x32,0x5,0x10,0x11,0x44,0x73,0x21,0x54,0x45,0x9,0x78,0xed,0xf5,0xa3,0x5c,0x18,0x1f,0x25,0x20,0x64,0x60,0x60,0x0,0x45,0x19,0x1d,0x3d,0xcf,0xf8,0xf8,0x18,0xab,0x57,0xad,0x21,0xc,0x4b,0x1c,0x3b,0x76,0x94,0xde,0xde,0x6b,0xe8,0x68,0xef,0x98,0xbd,0x9,0x18,0xb8,0x18,0x5c,0x6c,0xb8,0x20,0x43,0x90,0x79,0x9b,0x1f,0xc3,0x2c,0xef,0x54,0x59,0xcd,0xf0,0x89,0xc7,0x45,0xb3,0x77,0x2d,0x9d,0x5,0x3b,0x20,0x82,0xa0,0x48,0x4e,0x83,0xa6,0xe,0xa8,0x4,0x34,0xea,0x11,0xc5,0xb6,0x2,0x7f,0x3d,0xf8,0x3c,0x66,0x46,0x2d,0x9a,0xe4,0xba,0xf5,0xfd,0x24,0x49,0xc2,0xf6,0x1d,0xdb,0x39,0xf0,0xdc,0x1,0x96,0x75,0x77,0x31,0x31,0x3e,0xce,0xfe,0x3f,0xef,0xe7,0x96,0x5b,0xb6,0x92,0xa6,0x29,0x41,0x10,0x5c,0x45,0xa9,0x26,0x6d,0xe2,0x8,0x92,0xd8,0xe7,0xcb,0x8,0xca,0x9,0x41,0x21,0x21,0x28,0xb6,0xb8,0xca,0x9,0x9e,0x94,0xa4,0x6e,0xa4,0xb1,0x91,0x44,0x9e,0x38,0x9a,0xbd,0x6b,0x87,0xef,0xdb,0x9e,0x5,0xb0,0x26,0xec,0xd,0x8,0x48,0x5d,0x4a,0x7b,0x47,0x3b,0x8f,0xee,0xf9,0xd,0x67,0x4f,0x9f,0x65,0xcb,0xa7,0x3e,0xcd,0xad,0xb7,0xdd,0xca,0x1f,0x6,0x9f,0x62,0xeb,0xcd,0x5b,0x11,0x84,0x2d,0x37,0x6e,0x61,0xc7,0x5d,0xdb,0xf9,0xd9,0x4f,0x1f,0xa2,0xda,0x53,0xa5,0xb3,0xb3,0x13,0xc3,0x32,0xd,0xbd,0x5c,0x7,0xac,0xd9,0xb2,0x84,0x24,0x6,0x8b,0x3d,0x5e,0x1c,0x22,0x1,0xa7,0x4f,0x9e,0x41,0x35,0xc4,0xcc,0xb7,0x24,0xfd,0x86,0x51,0x69,0xeb,0xa6,0xbd,0x6d,0x19,0x3e,0x75,0x58,0x6c,0xd9,0xb7,0x69,0x31,0x1,0xe4,0x82,0x97,0x55,0xe9,0x32,0xb0,0x78,0x18,0xf8,0xe4,0x0,0xd5,0x6a,0xf,0xf,0x7c,0xff,0x47,0x44,0x51,0xc4,0x9e,0x47,0xf7,0xf0,0xed,0xbb,0xbf,0xc5,0xdd,0xf7,0xdc,0xc3,0x8b,0x2f,0xbc,0xc8,0xd9,0x77,0xce,0xb2,0x6d,0xdb,0x36,0x9e,0x78,0xfc,0xc9,0x4c,0x28,0xcd,0xa3,0x3a,0x5,0xac,0x2b,0xc5,0x46,0xb3,0xea,0xa4,0x11,0x44,0xb1,0x47,0xd5,0xf0,0x96,0xf0,0xa1,0xbe,0x8f,0xe6,0x87,0x97,0x16,0xd9,0x2f,0xc4,0x71,0x83,0x5a,0x2d,0x22,0x50,0x25,0x8a,0x1d,0x49,0x3,0xcc,0xb,0xad,0x88,0x60,0x5e,0x7c,0x3,0xf1,0x19,0x15,0xb0,0xcc,0xc,0x9,0x74,0xb4,0xb7,0x33,0x31,0x31,0x4e,0xea,0x52,0xfa,0xfa,0xfa,0x38,0x75,0x6a,0x98,0x7a,0x3d,0x62,0x79,0x77,0x37,0x95,0x4a,0x85,0xc3,0x87,0xf,0x23,0xa6,0xdc,0xff,0x83,0xef,0x91,0x24,0x31,0x61,0x18,0x62,0x36,0xbb,0xb4,0x99,0x81,0x6b,0x80,0x8f,0x3c,0x29,0x1e,0x1,0xce,0x25,0xff,0x42,0x9,0xb0,0x16,0x3b,0x82,0x89,0x51,0xf0,0x15,0x42,0xab,0xe0,0xc4,0xe1,0xa2,0x4c,0x3,0x5a,0xa6,0xc0,0xd5,0x66,0x71,0x7a,0xf3,0xc3,0xc3,0xc3,0xf4,0xf5,0xf6,0xb1,0x6a,0xf5,0x4a,0xf6,0xfe,0x7e,0x2f,0xdd,0x3d,0x55,0x36,0x6c,0x5c,0xcf,0x1f,0x7,0xf7,0x51,0x6e,0x2b,0x53,0x2a,0x96,0xf8,0xf1,0x83,0x3f,0xe1,0xe9,0x3,0x7f,0xa2,0x5a,0xad,0x52,0xab,0xd5,0x50,0xd5,0x99,0x77,0x61,0xd9,0x8a,0x1a,0xe0,0x22,0x48,0xbd,0xa1,0x2a,0x44,0xb5,0x2,0x22,0x8a,0xb5,0x64,0xb9,0x33,0x5e,0x59,0x41,0xd0,0x82,0xc7,0x0,0x1f,0x43,0x5c,0xcf,0xa9,0xdc,0x72,0x2,0x2c,0xef,0xdd,0x32,0xbd,0x89,0x20,0x8,0x38,0xfe,0xc6,0x71,0x6,0x7,0xf7,0xf1,0xd8,0x9e,0xc7,0xb8,0x73,0xfb,0x9d,0x6c,0xda,0xb4,0x89,0x93,0x27,0x4e,0xf2,0xcc,0xd3,0xcf,0xf0,0x9d,0xef,0xde,0xcb,0xc6,0x8d,0x1b,0x19,0x1f,0x1f,0x67,0xf7,0xae,0xdd,0xec,0xda,0xbd,0x8b,0x72,0xb9,0x3c,0xe5,0x7,0x66,0x3a,0xbf,0x9a,0x10,0x37,0x20,0x8e,0x3d,0x8a,0x61,0xe6,0xe8,0xad,0xae,0xc1,0xcc,0xb5,0x6c,0xb6,0x4,0xa1,0x51,0xaf,0x51,0xaf,0x37,0x50,0xd,0x89,0x23,0x4f,0xd4,0xb8,0xe2,0x8,0x1f,0x3c,0xb,0xf4,0xaf,0xbb,0xce,0xda,0xcb,0x6d,0x20,0x10,0x48,0x88,0x28,0x59,0x37,0x60,0xda,0xec,0xa8,0xc2,0x86,0x8d,0x1b,0x18,0xb8,0xe1,0x6,0x4e,0xf,0xf,0xf3,0xf2,0xcb,0xaf,0x10,0xc7,0x31,0x5d,0x5d,0x5d,0x94,0xca,0x25,0x46,0xff,0x3b,0x8a,0xf7,0x9e,0xb5,0xeb,0xd6,0x72,0x6e,0xe4,0x1c,0x51,0x14,0x5d,0x7d,0x78,0xf,0x61,0x11,0x26,0x4f,0x5c,0xcf,0xbd,0x3b,0x9e,0xe4,0x8d,0x57,0xde,0x24,0xc,0x4b,0xa8,0x28,0xa3,0xd1,0x71,0x54,0xa,0x2d,0xf,0x5,0x66,0x9e,0xf6,0x42,0x2f,0xed,0x41,0x2f,0x8e,0x94,0xb8,0x51,0xe3,0xe3,0x9b,0xd7,0xf3,0xcb,0xfd,0xdf,0xe0,0xc8,0xf9,0x27,0xa4,0x5,0x4,0x64,0x82,0xe2,0x71,0x28,0x3a,0x95,0xa9,0x69,0x97,0xa7,0xbc,0x79,0xe2,0x2d,0x8e,0x1d,0x1d,0xa2,0x58,0x2c,0xe6,0x4e,0x4f,0x98,0xbc,0x54,0xa3,0x36,0x59,0xcf,0x7c,0xbe,0x4,0xbc,0x73,0x66,0x84,0x24,0x49,0x66,0x46,0xbf,0xcf,0x16,0x40,0x52,0x87,0x38,0xf2,0x39,0x54,0x1d,0xcb,0xf5,0x63,0xf3,0x9b,0x88,0x4,0x7c,0xea,0x88,0x72,0xe3,0x95,0x46,0x46,0xdc,0x98,0xdd,0x7,0x84,0xb3,0x67,0x32,0x37,0x15,0xc1,0xf4,0xdf,0x22,0x99,0x2a,0x9b,0x81,0xf7,0x1e,0x6f,0x9e,0x62,0xb1,0x84,0xf7,0x6e,0x8a,0xab,0xce,0xb9,0xcb,0xbe,0x61,0xc4,0x71,0xfc,0xbe,0x29,0x36,0x33,0xf0,0x99,0x8,0x92,0x1a,0x2a,0xd9,0xfb,0xce,0x26,0x17,0x60,0x81,0x9b,0x25,0xf3,0x58,0xea,0x71,0x8d,0xac,0xd5,0xce,0x3d,0x1,0x66,0x66,0x78,0x41,0x4,0x33,0x9d,0x72,0x65,0x5e,0xb3,0x4e,0x4b,0xd3,0xd7,0x1b,0x24,0xce,0xcd,0x7f,0x26,0xb2,0xbc,0x3,0x18,0x44,0x89,0xc7,0xc5,0x46,0x6c,0x96,0x2b,0xbf,0x2e,0x74,0x14,0x42,0xc8,0xac,0x70,0x23,0x6,0x6f,0x32,0xf7,0x59,0xc0,0x60,0xc4,0xbc,0xad,0x10,0x15,0xc,0x13,0xc3,0x63,0x28,0x6a,0x86,0x21,0x99,0xa0,0x88,0x65,0xad,0x6d,0xa6,0x3b,0x8b,0x19,0xcc,0xce,0x7b,0x9f,0x49,0x3e,0xb3,0x8b,0x1,0x41,0x4c,0x94,0x34,0xc0,0x84,0x24,0xb2,0xcb,0x66,0x86,0xf9,0xd,0x45,0x42,0x66,0x38,0x3c,0x1e,0xf3,0x42,0x9c,0x3a,0x6f,0x12,0xe9,0xdc,0x7d,0x80,0xc8,0xee,0xd4,0xb9,0x9f,0x17,0x54,0x2f,0x9a,0x59,0xc5,0x83,0x88,0x39,0x9c,0x29,0x88,0xe5,0xc3,0x91,0x7d,0xf0,0x1e,0x6d,0xf6,0x73,0x34,0x29,0xe6,0x52,0xf0,0xed,0x67,0x18,0x3a,0x75,0x88,0xb5,0xd7,0xdc,0xc6,0xe8,0x99,0x61,0x92,0x34,0x61,0x41,0xb7,0x2e,0xd9,0xd5,0x15,0x61,0x10,0xb0,0x62,0xd5,0xf5,0xf5,0x63,0xa7,0x9f,0x6d,0xab,0xdb,0xc8,0xde,0x39,0x27,0xa0,0xda,0xd3,0xf3,0x48,0x12,0x45,0x5f,0xbc,0x38,0x31,0xf1,0xb9,0x42,0xb1,0x48,0x18,0x4,0x90,0xcf,0x2,0x59,0x51,0x33,0x78,0x2d,0xc6,0xa5,0x85,0x79,0x8,0x2a,0x17,0x38,0x32,0xf2,0x2b,0x5c,0xb5,0xc8,0xca,0x95,0x9b,0x29,0x51,0xc9,0x4,0x72,0x9e,0x9f,0x55,0xc0,0x14,0x62,0x9b,0xb4,0xa1,0xb1,0x67,0xdb,0x86,0x2e,0x3c,0x7e,0x7e,0x2c,0x19,0xda,0xd9,0xd2,0x9d,0xe0,0xc3,0xf,0x3d,0xbc,0xec,0xe0,0xdf,0x5e,0xba,0xef,0xed,0xb7,0xff,0xfd,0xcd,0x24,0x49,0xd6,0x34,0x49,0x39,0x13,0xaa,0x17,0x9a,0x5,0x13,0x23,0x4d,0x12,0xa8,0xf5,0x50,0x4e,0xae,0x25,0xf0,0x5d,0xb,0xbc,0x13,0x3,0x10,0x73,0xc1,0x24,0x85,0xce,0xb1,0xbf,0x14,0x7a,0x46,0x7e,0xf8,0xcf,0x23,0xaf,0xe,0x2d,0x5d,0x1,0x2f,0xc5,0x52,0x2c,0xc5,0x52,0x2c,0xc5,0x95,0xf1,0x3f,0x3d,0xec,0x5e,0x6b,0xe4,0x4d,0x1e,0xfb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0xa2,0x9d,0x7e,0x84,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x17,0x2,0x12,0xee,0x6d,0xd3,0x79,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0xa7,0x49,0x44,0x41,0x54,0x68,0x81,0xed,0x99,0x4d,0x4f,0x13,0x51,0x14,0x86,0x9f,0x99,0x4e,0x6c,0x4b,0xc6,0x52,0xc5,0xb6,0x49,0x1b,0x5d,0xb1,0xf4,0x63,0x69,0x28,0x89,0xfc,0x7,0x63,0x42,0x8,0xff,0x40,0x11,0xc4,0x8d,0x51,0x2,0xb,0x5,0x56,0x86,0x8f,0xb8,0x51,0xff,0x0,0x69,0x20,0x24,0x6,0x24,0xfc,0x1,0x68,0x58,0x82,0x11,0x77,0x6e,0xc,0x24,0x2d,0x6,0x3a,0x49,0xad,0xd3,0x32,0xe5,0xba,0x18,0xdb,0x94,0x71,0x2,0xb1,0xb9,0x63,0x23,0x9d,0x67,0xd5,0xde,0x73,0xe6,0xcc,0x7b,0xde,0xe9,0x9d,0xcc,0x9c,0x82,0x8f,0x4f,0x5b,0xa3,0x38,0xbe,0x77,0x0,0x51,0x40,0x7,0x2,0x2e,0xf1,0xff,0x15,0x1,0x54,0x81,0x22,0x50,0x0,0x4a,0xb5,0x80,0xe6,0x48,0x8c,0x2,0xb7,0x81,0xeb,0x40,0x88,0x8b,0x65,0x80,0x9,0x7c,0x3,0x76,0x38,0xc3,0x0,0x1d,0xb8,0x71,0xeb,0xe6,0x9d,0xd9,0x54,0x32,0x15,0xd6,0x34,0xcd,0x53,0x3,0xaa,0x55,0x8b,0xe3,0x63,0xb,0xcb,0xb2,0x10,0x8,0x5b,0xa6,0x4c,0x14,0x50,0xec,0x6b,0x28,0xe,0xbe,0x1f,0xfc,0xfc,0xbc,0xfb,0x69,0x14,0xf8,0xda,0x98,0xe2,0x34,0x40,0x3,0x82,0xa9,0x64,0xaa,0xc3,0x34,0x4d,0x4c,0xd3,0x94,0xac,0xe8,0x34,0x95,0x4a,0x85,0x52,0xe9,0x7,0xe5,0x4a,0x5,0x71,0x72,0x62,0x9b,0x20,0x11,0x5,0x5,0x45,0x55,0xd1,0x75,0x5d,0x89,0x5d,0x8b,0x75,0x0,0x41,0x1c,0x3d,0x3b,0xd,0x0,0x50,0x34,0x4d,0xf3,0xbc,0x79,0x80,0x6a,0xb5,0x4a,0xb9,0x52,0x26,0x1a,0xbd,0x42,0x3c,0x16,0xaf,0x5d,0x2d,0x69,0x8,0x4,0xf9,0x83,0x3c,0x85,0xc2,0x11,0x5d,0x57,0xbb,0xc0,0x65,0x4b,0xbb,0x19,0xf0,0xcf,0x10,0x8,0xc4,0x89,0x20,0x11,0x4f,0x60,0x9a,0x26,0xf7,0x1f,0xf4,0x4b,0xad,0xbf,0xbc,0x94,0x21,0x11,0x4f,0x70,0x74,0x78,0x88,0x10,0xee,0xbf,0x2e,0x55,0xea,0x19,0x9b,0xa0,0xb6,0xf7,0x65,0x37,0xf,0xbf,0x6b,0xa,0xce,0xdc,0x5a,0x2d,0x37,0xa0,0xd5,0xf8,0x6,0x34,0x73,0x90,0xae,0xeb,0x8c,0x4f,0x8c,0xb1,0xb6,0xbe,0xca,0xda,0xfa,0x2a,0xe3,0x13,0x63,0xe8,0xba,0xe,0x40,0x76,0x6b,0x83,0xe7,0x2f,0x9e,0xd5,0x73,0xb3,0x5b,0x1b,0x72,0x94,0x7a,0x44,0x53,0x6,0x8c,0x3e,0x1d,0x1,0x60,0xa0,0x7f,0x90,0x81,0xfe,0x41,0x54,0x35,0x50,0x5f,0x3,0x48,0xf7,0xa6,0xe9,0xee,0xee,0x96,0xa3,0xd0,0x63,0x9a,0x32,0x20,0xdd,0x9b,0x66,0x7e,0xee,0xd,0x86,0x61,0x60,0x18,0x6,0x73,0xb3,0xf3,0xf4,0xa4,0x7b,0xea,0xf1,0x77,0x6f,0xdf,0xf3,0x64,0x74,0x58,0x9a,0x48,0x2f,0xf1,0xe4,0x1e,0xb0,0xba,0xf2,0x91,0x50,0x38,0x4c,0x5f,0xdf,0x3d,0x2f,0xca,0x4b,0xa5,0x29,0x3,0x36,0x37,0x36,0x79,0x3c,0x3c,0x44,0x24,0x12,0x21,0x12,0x89,0x30,0x3c,0x32,0x44,0x76,0x33,0x7b,0x2a,0x67,0xe6,0xf5,0xc,0x8f,0x86,0x1e,0x4a,0x11,0xe9,0x25,0x4e,0x3,0x42,0x40,0xe7,0x79,0x7,0xcd,0xce,0xcc,0xa3,0xaa,0xa,0x99,0xc5,0x5,0x32,0x8b,0xb,0xf5,0xb5,0x46,0x76,0x77,0xbf,0xb0,0xbd,0xbd,0x23,0x4b,0xa7,0x2c,0x3a,0xb1,0x7b,0xac,0xe3,0x7c,0x12,0x34,0x1,0xe3,0xbc,0x2a,0xc5,0x62,0x91,0x57,0x2f,0xa7,0x5c,0x63,0x3d,0x77,0x7b,0xeb,0x9f,0xa7,0x26,0xa7,0x99,0x9a,0x9c,0xfe,0x6b,0x95,0x1e,0x62,0x60,0xf7,0x58,0xc7,0x7f,0xe,0x68,0xb5,0x80,0x56,0xe3,0x1b,0xd0,0x6a,0x1,0x8a,0x3d,0xb5,0x60,0x79,0x29,0x23,0xbd,0xf6,0xf2,0x52,0xa6,0x71,0x28,0xe2,0x4a,0x4b,0x5f,0x87,0xed,0x81,0x85,0x42,0x2e,0x9f,0x23,0x1e,0x8b,0xb3,0xb6,0xf2,0x41,0x6a,0xfd,0x60,0x30,0x48,0x2e,0x9f,0x43,0x51,0x15,0x14,0xc5,0xdd,0x4,0x37,0x3,0x84,0x65,0x59,0x84,0x42,0x21,0xcf,0x87,0x22,0x81,0x40,0x80,0xe0,0xa5,0x20,0x85,0x42,0xc1,0x7e,0x67,0xf7,0x6c,0x22,0x74,0xb9,0xb6,0xf4,0xc7,0x9,0x9c,0x6,0x58,0x40,0x79,0x6f,0x7f,0xaf,0x94,0x4a,0xa6,0xc2,0xba,0xae,0x5f,0xa8,0x99,0x20,0x50,0xc6,0xee,0xb1,0x31,0xe5,0x14,0x49,0xda,0x63,0x2a,0xbc,0x5f,0xb,0xb4,0xfd,0xff,0x2,0x3e,0x3e,0x3e,0xed,0xcd,0x2f,0xbd,0x80,0xe4,0x2f,0x1f,0x1c,0x6a,0x6c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -370,12 +390,12 @@ static const unsigned char tool_button_pressed_png[]={ static const unsigned char tooltip_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0x73,0x7a,0x7a,0xf4,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xda,0xc,0x3,0x2,0x34,0x35,0x46,0x29,0x34,0xbc,0x0,0x0,0x3,0xda,0x49,0x44,0x41,0x54,0x58,0xc3,0xc5,0x97,0x3d,0x8e,0x65,0x49,0x11,0x85,0xbf,0x73,0x22,0xdf,0xeb,0x1e,0x69,0x24,0xd8,0x5,0x5e,0x2f,0x60,0xc,0xec,0xf1,0x86,0x2d,0x20,0xd8,0x7,0x62,0x1f,0x20,0xb6,0x0,0x1e,0x12,0xe,0x1a,0x1,0xfe,0xb4,0xc7,0xe,0x0,0xb,0x83,0x11,0x53,0xf7,0xde,0x88,0xc0,0xc8,0xbc,0xd5,0xd5,0xa5,0x87,0xd4,0xf,0xaa,0x20,0xa5,0x54,0x4a,0xf7,0x27,0xe3,0xc4,0x89,0x13,0x11,0x99,0x2,0x78,0xf7,0xee,0x9d,0x98,0x43,0x4f,0xe6,0x6b,0x8c,0x7e,0x32,0x79,0xff,0xfe,0x7d,0x6b,0x19,0x17,0x10,0xc0,0x0,0xbc,0xe6,0x6b,0x8c,0x5a,0xf3,0x0,0x12,0xe8,0xb1,0x5e,0x4,0xf0,0x6,0x78,0xbb,0xd6,0xf1,0xa,0x2c,0xf4,0x32,0xfc,0x0,0x7c,0xb7,0xd6,0xe3,0x34,0x34,0x96,0xf1,0xef,0x1,0x9f,0x3,0xd7,0xc5,0x82,0x5e,0xd0,0x78,0x1,0x1b,0xf0,0x8f,0xf5,0x2c,0x81,0x3c,0x1,0x78,0x79,0xfe,0x39,0xf0,0xfd,0x5,0x26,0x5e,0x18,0x40,0x2e,0xcf,0x59,0xeb,0x3f,0x1,0x9d,0x21,0xf0,0x62,0xe1,0xa,0xbc,0xfd,0xe5,0x2f,0x7e,0xfe,0xdb,0xd7,0x10,0xc0,0x4f,0x7e,0xfa,0xb3,0x2f,0x97,0x8d,0x53,0x6b,0x7a,0x1a,0xeb,0x93,0x89,0xd8,0x73,0xe3,0xd7,0xbf,0xf9,0xd5,0x8b,0x1a,0xff,0xd1,0x57,0x3f,0x3e,0xb5,0xf6,0x51,0x68,0xc7,0xb3,0xef,0x4,0x68,0xdf,0x77,0x46,0x4,0x5f,0xfc,0xf0,0x7,0xb7,0x14,0x5c,0x4f,0x53,0x69,0xad,0xcf,0xd3,0xd8,0x4f,0xb3,0xe9,0x4f,0x5f,0xff,0x99,0x7d,0xdf,0xb9,0x95,0xe2,0xe3,0x16,0xda,0xe3,0x38,0x3e,0x4,0xe7,0x83,0x60,0x6e,0x1,0xe8,0xe7,0xe0,0xd7,0x7c,0xfa,0x3e,0x34,0xe6,0x9e,0xb7,0xc6,0x6d,0x0,0xdb,0x3,0x97,0x88,0x99,0x9f,0x41,0x76,0x29,0xe5,0x2e,0x72,0x2,0x68,0xa9,0xb2,0xdd,0x8a,0xec,0xce,0x20,0x40,0x15,0x9,0x39,0xbd,0xb7,0xd4,0xb4,0x3b,0xa1,0x43,0xc5,0x25,0x22,0x8e,0xed,0xe1,0xd3,0x1,0x6c,0xc7,0xe,0x36,0x96,0xaa,0x6b,0x19,0x2d,0x25,0xfa,0xc0,0x42,0xa8,0x9a,0x52,0xa3,0x82,0x99,0x36,0xda,0x3,0xa1,0x6a,0x67,0x74,0xaa,0x3a,0x4e,0x66,0xec,0xd8,0x8e,0xfd,0xe,0x6,0x8e,0x83,0xeb,0x30,0xe5,0xae,0x80,0xea,0x8c,0x52,0x64,0x9d,0x4c,0x24,0xcc,0xe7,0xa5,0xa9,0x81,0xb6,0xb2,0x8a,0xa3,0xed,0xab,0xd4,0xb9,0xd4,0x96,0x2b,0x24,0xd7,0xe1,0xfb,0x42,0xb0,0xef,0x3b,0xb2,0x71,0xa9,0x1a,0x6a,0x44,0xd6,0x51,0x7a,0x64,0xc2,0x50,0xd,0x55,0x76,0x5f,0xaa,0x50,0x24,0x47,0x49,0x57,0x55,0xe7,0xd2,0xc5,0x6e,0xe3,0x2a,0x5,0x48,0xf6,0x29,0xc2,0x4f,0x7,0x70,0x19,0x46,0x76,0x1b,0xba,0xa1,0xc2,0x93,0xfa,0x82,0xca,0x19,0x86,0xbc,0x54,0x35,0x76,0x37,0x28,0x3c,0xc5,0x17,0x55,0x60,0x2b,0x96,0xf7,0x65,0xfb,0x32,0xee,0x4,0x90,0xc7,0x6,0x36,0x40,0x57,0xd0,0x91,0x53,0xd1,0xcb,0xbb,0x7a,0xb,0x49,0x64,0xee,0x44,0x9d,0x5c,0x47,0x10,0x99,0x53,0x82,0x6,0x9,0x9c,0x97,0xee,0x80,0xc6,0x9e,0x7b,0x7e,0xb2,0x6,0x6a,0xe3,0xcd,0xa5,0x59,0x89,0xd0,0xc4,0x4,0x10,0x2b,0xb5,0xa,0x1a,0xa2,0x22,0x96,0x28,0x63,0x16,0x97,0x88,0xc7,0x14,0xa4,0x33,0x1e,0xbf,0x7f,0x73,0x69,0x8e,0xba,0xd,0xe0,0x66,0xdb,0xdd,0xf3,0x1,0x7b,0x10,0xd3,0x28,0x31,0x37,0xc4,0x19,0x6d,0x89,0x96,0xda,0x19,0xf4,0x14,0x68,0xb6,0x54,0xce,0x68,0x66,0xb8,0xa6,0xf1,0x51,0xb3,0x8,0x0,0xf6,0x60,0xcf,0x3b,0xd2,0xb0,0x6b,0xe3,0x12,0xa2,0x25,0x9d,0xf5,0x33,0x46,0x11,0xa0,0x74,0x13,0x20,0x46,0x11,0xc8,0x8c,0x9a,0x8e,0x8c,0xc2,0xcc,0xef,0x19,0x33,0x3d,0x42,0xa2,0x81,0x4b,0x88,0xba,0x87,0x81,0x3c,0x36,0x62,0x18,0x11,0x84,0x5b,0xb8,0x15,0x6e,0x55,0x6,0x51,0x52,0x80,0x2a,0x23,0x2,0x8c,0x7b,0x28,0xc3,0x22,0x22,0x40,0xca,0x50,0xb8,0x11,0xa1,0xc7,0x7f,0xc7,0x9d,0x1a,0xd8,0x8e,0x83,0xcf,0x3e,0xf3,0xf4,0x94,0x10,0x25,0x1d,0x6e,0x29,0x30,0x83,0xae,0x63,0xb4,0x2f,0x8d,0xb0,0x54,0xea,0xbe,0xb4,0x54,0x52,0x11,0x41,0xe0,0xb0,0x5c,0x85,0xaa,0x86,0xc6,0x4a,0xc3,0xed,0x9e,0x3a,0x90,0xc7,0x86,0xe2,0xca,0xe1,0xd6,0x0,0xe1,0xf6,0x80,0x3e,0xa0,0x55,0x26,0xdc,0x1c,0x25,0x3d,0x40,0x47,0x9b,0x41,0x82,0x5b,0x47,0xc9,0x40,0x6c,0x65,0xf,0xf7,0xd9,0x8c,0xa4,0x88,0x3b,0xb3,0x60,0x4f,0x86,0x4d,0x94,0xcc,0xc8,0x6e,0x68,0xca,0x1d,0x23,0x9b,0x32,0x47,0x89,0x31,0xd2,0x71,0x44,0xa3,0x6a,0x5c,0x72,0x19,0xdc,0xa6,0x64,0x4a,0x81,0xdb,0x7,0x38,0xc0,0xc3,0xe6,0xd8,0xf3,0x1e,0x0,0x3b,0xad,0xb,0x65,0x9b,0x72,0x9b,0x9c,0x9d,0xad,0x4c,0x4f,0x4a,0x95,0xe5,0xb6,0x73,0xa6,0x5c,0x99,0x84,0xa9,0xd,0xdb,0x26,0xdd,0x10,0x22,0xc,0xe9,0xd6,0x85,0xe3,0xae,0x4a,0x98,0x3b,0xc3,0x10,0x2e,0x27,0xb4,0x2a,0xc0,0x85,0xd5,0xaa,0x96,0xa2,0x10,0xae,0xf6,0x1,0xbb,0xa3,0xc3,0x53,0xf5,0x13,0x44,0x39,0x91,0x29,0x1b,0x70,0x11,0x1e,0x9e,0x7b,0xde,0x55,0x8a,0xed,0xeb,0x79,0x5c,0xe,0x3c,0x3b,0x5e,0xb5,0x66,0xbf,0x77,0x19,0xe8,0x1a,0xea,0x59,0x8b,0x66,0xd7,0x3b,0xcb,0xef,0xcc,0x8e,0x3a,0x35,0x10,0xf6,0xf5,0x93,0x4b,0x71,0x3,0xbd,0x6d,0x85,0x6d,0xfe,0xf6,0x97,0xc7,0xe2,0x71,0xd6,0xa3,0xff,0x68,0xd8,0x66,0xdb,0x8a,0x1b,0x87,0x18,0xc6,0xb3,0xa3,0x55,0x1,0xb9,0x1d,0x7,0x7f,0xf8,0xe3,0x37,0x2f,0x7b,0x22,0x9d,0xbd,0x25,0x9f,0x9c,0xa8,0x3e,0x62,0xe0,0xbc,0xad,0x6c,0xc0,0x77,0xbf,0xff,0xdd,0x5f,0xbf,0x7c,0xc5,0x63,0xf9,0xb6,0x6c,0xd5,0x79,0x33,0x3a,0x3d,0x7f,0x0,0xbe,0x5d,0x3f,0x5c,0xff,0x1b,0xca,0xff,0xcd,0xc8,0x65,0xfc,0xdb,0x65,0xeb,0x23,0x0,0xc7,0x42,0xf7,0xf7,0xb5,0xbe,0xa4,0xf7,0xcf,0x59,0x38,0xaf,0x66,0xc7,0xd3,0xbb,0xe1,0xf9,0x22,0xd7,0x8d,0xe5,0x7f,0x75,0x39,0x9d,0x5e,0xfe,0x3f,0xaf,0xe7,0xff,0x2,0xd,0x2f,0x3a,0x83,0xce,0x22,0x38,0x16,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xf,0xd,0x2d,0xcd,0xa6,0x10,0x43,0x0,0x0,0x0,0xd2,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x93,0x3d,0x6a,0xc3,0x40,0x10,0x85,0xbf,0x55,0x6,0x2c,0x9,0x17,0xa9,0x77,0xb1,0x4f,0xe0,0x9f,0x42,0x27,0x12,0x42,0x65,0x8,0x3e,0x49,0xe,0x20,0x8c,0x4f,0xe4,0xc2,0x3f,0x75,0x9a,0xb0,0xaa,0x53,0x84,0x48,0x82,0x31,0x4a,0x11,0xa5,0x5d,0x5,0xd4,0xb8,0xf0,0x2b,0x87,0x79,0xdf,0x30,0xf0,0x9e,0x1,0x52,0xe0,0x19,0x98,0x3,0x4f,0x80,0x21,0xac,0x1e,0xb8,0x1,0x5f,0xc0,0xa7,0xc,0xe6,0xd,0xb0,0x0,0xe2,0x7f,0x2,0x5a,0xe0,0x3,0x38,0xcb,0x70,0x79,0xb9,0x5e,0x6d,0xdf,0x9c,0x75,0x89,0x88,0x4,0x1,0xaa,0xda,0xfb,0xda,0x37,0x97,0xeb,0x69,0x7,0xbc,0xb,0x20,0xc0,0xcc,0x59,0x97,0xb6,0x6d,0xcb,0xfe,0x50,0x1d,0x43,0x80,0x22,0x2f,0x33,0x67,0x5d,0x7a,0xb9,0x9e,0x66,0x80,0x44,0xc3,0xdc,0x88,0xc8,0xa8,0x19,0x60,0x7f,0xa8,0x8e,0x22,0xc2,0xdf,0xab,0x51,0x78,0x7d,0x5c,0xf,0xc0,0x3d,0x1,0x7a,0x55,0xa5,0xc8,0xcb,0x6c,0xcc,0x50,0xe4,0x65,0xa6,0xaa,0xf0,0x1b,0x69,0x4,0x50,0xa0,0xf3,0xb5,0xff,0x76,0xd6,0x25,0xaf,0x2f,0xbb,0x20,0x24,0x8e,0xe3,0xde,0xd7,0xbe,0x1,0x3a,0x40,0xd,0x60,0x99,0x50,0x26,0xc3,0xc4,0x3a,0xff,0x0,0x26,0xe4,0x45,0xbd,0xbe,0xa2,0xc,0xd0,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char tree_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x30,0x0,0x27,0x0,0x35,0x33,0xd3,0x97,0xbf,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x11,0x4,0x30,0xb7,0x2d,0x2b,0x51,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xc0,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xd0,0x2d,0x8e,0x2,0x41,0x10,0x86,0xe1,0xb7,0x7f,0x66,0x4,0x20,0xd6,0xb0,0x21,0x60,0x20,0x70,0x1,0x34,0x8a,0x5b,0xac,0x26,0x5c,0x62,0x4f,0xc0,0x11,0x30,0x4,0xcd,0x29,0x40,0xa1,0xb9,0x0,0x9,0x6a,0x12,0x2,0x6,0x1,0x23,0x9a,0xa9,0x2e,0xcc,0x1e,0x60,0x3a,0xeb,0x8,0xaf,0xff,0x9e,0x4a,0xca,0xa8,0x2a,0x83,0xde,0x68,0x5,0xfc,0x0,0x4d,0xea,0xf5,0x0,0x36,0xa7,0xe2,0x38,0x37,0xfd,0xee,0x70,0xeb,0xbc,0x9f,0x7a,0xef,0x48,0xa9,0xaa,0x4,0xa9,0xaa,0x9d,0xe9,0x77,0x87,0xd2,0x68,0x36,0xac,0x73,0xe,0x6b,0xea,0x21,0x51,0x5,0x11,0xa1,0x7c,0x94,0xd1,0x3,0x36,0xf3,0x79,0xd2,0x75,0x6b,0x1c,0xd6,0x3b,0xa0,0xb4,0x96,0x7f,0xf6,0x1,0xde,0x6,0x28,0xa2,0x4a,0xf2,0xf0,0x6f,0x53,0x58,0x60,0x19,0x42,0x20,0x5,0x89,0x2a,0x84,0x10,0x0,0x96,0x46,0x55,0x99,0x8c,0xa7,0x8b,0xeb,0xed,0x3c,0x7b,0x86,0xe7,0x77,0x1d,0x20,0xcb,0xb3,0x4b,0xfb,0xab,0xb3,0xde,0x1f,0x76,0xbf,0x46,0x55,0x41,0xc9,0x81,0x56,0xc2,0x4f,0x22,0x70,0xc7,0x10,0x5e,0xb5,0x47,0x48,0x5e,0x61,0x62,0xef,0xf5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x12,0xb,0xd,0x3b,0xe,0x30,0x79,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xbd,0x49,0x44,0x41,0x54,0x38,0x8d,0xdd,0x93,0x41,0x6a,0xc3,0x30,0x14,0x44,0xdf,0xa8,0x8a,0x97,0x26,0x27,0x48,0x9a,0x3,0xb4,0x90,0x1b,0xf4,0x66,0xf5,0x91,0x4b,0x16,0x9,0xd8,0x5f,0x9e,0x2e,0xac,0xa4,0x34,0xb8,0xb,0x6b,0xd9,0x1,0xa1,0x41,0x62,0x3e,0x33,0x1f,0x46,0xef,0x6f,0xe7,0xcf,0xcb,0xe5,0x6b,0x48,0x12,0x92,0x0,0xb0,0xbd,0xca,0xef,0xb0,0xcd,0x6c,0xd3,0xf7,0xfb,0x41,0xaf,0xc7,0x93,0xbb,0xdd,0x8e,0x9c,0xbb,0xe5,0x57,0x2,0x7b,0x9d,0x2f,0x6a,0x0,0x22,0x46,0xc6,0x69,0x22,0x27,0x89,0x9c,0x3b,0x72,0xce,0x6c,0x45,0x44,0x90,0x9e,0xed,0x6d,0x81,0x24,0xd2,0x2f,0x7b,0xdb,0xd4,0x0,0x75,0x40,0xb,0x6c,0x6c,0xd7,0x1,0xf7,0x45,0x6d,0x36,0x21,0x92,0x1b,0xc5,0x8f,0x8,0x92,0xda,0x76,0xf0,0xf,0x22,0x54,0xb4,0x47,0xa8,0x9a,0xf6,0x8,0x2c,0xa5,0xca,0xb3,0x4d,0xc4,0xf8,0xf3,0xfa,0x54,0x9a,0xbf,0xca,0x15,0x31,0x32,0xdb,0xbc,0x1c,0xe,0x27,0xae,0xb7,0xeb,0x47,0x29,0x41,0x29,0x41,0x89,0x69,0x39,0x25,0x88,0x7a,0xaf,0xf1,0x28,0x85,0xbe,0xdf,0xf,0xdf,0x7a,0xec,0x7c,0x19,0x53,0x3a,0x70,0xa,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -395,42 +415,22 @@ static const unsigned char tree_cursor_unfocus_png[]={ static const unsigned char tree_title_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4e,0x0,0x41,0x0,0x56,0xed,0xd0,0x4e,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x1e,0xf,0xb3,0x20,0x42,0xee,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x77,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x92,0xbd,0x4e,0xdc,0x50,0x10,0x85,0xbf,0xd9,0xb5,0xb2,0x38,0x80,0x4,0x11,0xb0,0x26,0x74,0x14,0xa4,0x48,0x4,0x1d,0x55,0x2a,0x44,0xc1,0x63,0xa0,0x74,0x79,0x4,0x1a,0xa2,0x54,0x91,0xf2,0x2,0x74,0x11,0x8f,0x41,0x41,0x49,0x95,0x32,0x52,0x9a,0xf4,0x28,0xcb,0xff,0x22,0x7e,0xc,0x6b,0x7b,0x4e,0x8a,0x7b,0xbd,0xe,0xa4,0xc8,0x22,0x46,0xb2,0x8e,0x74,0x75,0xef,0x37,0x73,0xce,0xd8,0x24,0x91,0xcd,0xbd,0xde,0x4,0x3e,0x2,0xab,0x8c,0x56,0xdf,0x81,0x1d,0x59,0xb5,0x6b,0xdd,0xd9,0xf9,0xed,0xee,0x4c,0xf6,0xf9,0xed,0xd2,0x32,0xd3,0x53,0xaf,0x46,0x7a,0x7d,0xd1,0x3f,0xe7,0xe7,0xaf,0x1f,0x1c,0x9d,0xf6,0x3e,0x59,0x77,0x76,0xfe,0xf7,0xfa,0xfb,0x8d,0x2c,0xbf,0xbb,0x25,0xbf,0xcf,0x47,0x2,0xa4,0x9d,0x94,0x74,0xec,0x25,0xfb,0x7,0x7b,0xbd,0x4,0xc8,0xce,0x2f,0xcf,0x78,0x4a,0xe5,0xf7,0x79,0xdd,0x2c,0x4b,0x0,0xe4,0x8e,0x64,0x98,0x9,0xcc,0x40,0x8d,0xd6,0xe7,0x92,0x81,0x9,0x3,0x4,0x58,0x84,0x25,0x0,0x95,0x3b,0x66,0x86,0x5c,0x41,0xd5,0xa8,0x0,0x53,0xbc,0xad,0xf0,0xf8,0x6f,0x40,0x8b,0x67,0x56,0xb0,0x20,0xa1,0x38,0x85,0x2b,0x8c,0x59,0x2b,0x80,0xc7,0x8e,0x8a,0xd6,0x6a,0x1b,0xd,0xc0,0x3d,0x5e,0x74,0x88,0x5e,0x87,0xa,0x98,0x2c,0x8c,0x6e,0xc2,0xdc,0x70,0x1a,0x5f,0x21,0x3,0x55,0xb4,0x68,0x21,0xfd,0xb,0x18,0xfa,0x95,0x5,0x0,0x60,0xb4,0x70,0x79,0x3,0x40,0xc2,0xa9,0x9a,0xf0,0xfc,0xa1,0xba,0xe2,0x24,0x44,0x8b,0x11,0x3c,0x4,0x78,0xb4,0x50,0xe7,0x11,0xba,0x85,0x69,0xdc,0x7c,0x98,0x85,0x22,0xa8,0xde,0x4e,0xd,0x38,0x1c,0x14,0xc5,0x42,0xd2,0x6e,0x3f,0x8c,0xf7,0xd1,0xea,0x1e,0x57,0x59,0x55,0x0,0x87,0xed,0x89,0xf1,0xc9,0xb4,0x28,0x6,0x6b,0x9d,0x4e,0xa,0xf5,0xee,0xff,0xf3,0x95,0x65,0xc9,0xc9,0xd9,0x11,0x45,0x59,0x7c,0x35,0x49,0xbc,0x7b,0xb3,0xf2,0xa5,0x7f,0x75,0xf1,0xa1,0x2c,0xcb,0xb9,0x91,0x76,0x9f,0x24,0xc7,0x53,0x93,0xd3,0xdf,0x4e,0xfa,0xbd,0x2d,0x93,0xc4,0xcd,0xe5,0xcd,0xb,0x60,0xe2,0x9,0x3f,0x96,0x3,0xd7,0x8b,0x4b,0x8b,0x83,0x3f,0xb0,0xb8,0xed,0xb9,0xad,0xea,0xa4,0x9f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x14,0x11,0x9,0x88,0xc3,0x72,0x9,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x1d,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x54,0x55,0x56,0xfd,0xcf,0x40,0x1,0x60,0xa2,0x44,0xf3,0xa8,0x1,0xa3,0x6,0x8c,0x1a,0x30,0x98,0xc,0x0,0x0,0x7,0x54,0x1,0x8c,0x3f,0xc3,0xfb,0x99,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char tree_title_pressed_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x21,0x14,0x61,0x9b,0xa1,0x3e,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x69,0x49,0x44,0x41,0x54,0x38,0xcb,0x95,0x92,0xcd,0x4a,0x5b,0x41,0x14,0xc7,0x7f,0xff,0xb9,0xd7,0xc6,0x5b,0x22,0x69,0x12,0x90,0x6c,0xa,0x2d,0xd,0x85,0xbe,0x80,0xf,0xe0,0x93,0x88,0x3b,0x1f,0xc1,0x8d,0xe2,0x4a,0xf0,0x5,0xdc,0x89,0xcf,0xe3,0x23,0x94,0x2e,0xba,0x91,0xb4,0x62,0x2a,0x25,0x21,0x26,0xf7,0x7a,0x73,0x5c,0xdc,0x99,0xc9,0x88,0x2e,0xae,0x3,0x7,0x66,0xe6,0x7c,0xfc,0x3f,0x38,0x32,0x33,0x6,0x9f,0x86,0x7,0xc0,0x11,0xb0,0x47,0xbb,0x73,0x3,0x5c,0x6e,0x75,0xf2,0x6b,0xf5,0x7b,0x83,0x93,0x7e,0x6f,0x78,0x36,0xec,0xf,0x1,0xb5,0xec,0x37,0xa6,0xf,0x53,0x1e,0xfe,0x4f,0x4f,0xd5,0xef,0xd,0x26,0xe3,0x2f,0xdf,0x47,0xf5,0x7a,0xcd,0x6a,0xb5,0x6c,0xd5,0xde,0xe9,0x6c,0x93,0x39,0xc7,0xaf,0xdf,0x3f,0xff,0xe4,0xc0,0x68,0xf1,0xb8,0xe0,0x3d,0x27,0x1,0x1a,0xe5,0x0,0x92,0x3,0x81,0xcc,0xb0,0x58,0xa6,0x48,0x37,0xbc,0xa5,0xe6,0xd9,0x54,0x35,0xf9,0x66,0x80,0xf3,0xc5,0x12,0xa,0xb9,0xd8,0x27,0x48,0xff,0x1c,0x28,0xf1,0x2a,0x7,0x70,0x3e,0x6b,0xd,0xd,0xdf,0x27,0xcc,0x37,0x85,0x19,0x88,0x58,0xf9,0x92,0x81,0x84,0x21,0x9c,0x4,0x96,0x88,0x10,0x98,0x40,0x26,0xe4,0xdb,0x90,0x7,0x34,0x5e,0x4a,0x50,0xe4,0xa8,0x14,0xaa,0xd1,0x2d,0xef,0x41,0xf4,0x44,0xd1,0xa2,0x8d,0x89,0xe0,0x25,0x24,0xdb,0xf0,0xe6,0x5a,0x28,0x31,0x3a,0xe,0x48,0x10,0xcc,0x83,0x7,0x12,0x9,0x60,0x50,0xe7,0x7c,0x7e,0x63,0xa2,0xdc,0x6,0x2e,0x98,0xe8,0x35,0x28,0x61,0x11,0x80,0x3c,0xd7,0x38,0xec,0xb6,0xaa,0x2a,0x24,0xf9,0x70,0x3e,0xd2,0x7b,0xf6,0xea,0xbf,0xaa,0x2a,0x80,0xdb,0xac,0xd8,0x2e,0x8a,0x55,0xb9,0xdc,0x2f,0x3a,0x5,0x59,0xbe,0x95,0x14,0x85,0xc0,0x87,0xb,0x17,0xca,0x72,0xc9,0xdf,0xfb,0x9,0x4f,0xf5,0xd3,0x85,0xcc,0x8c,0xaf,0x9f,0xbf,0x9d,0xcf,0x17,0xb3,0xc3,0xba,0xae,0x77,0xdb,0xac,0x72,0x96,0x65,0x77,0xdd,0x8f,0x3b,0x57,0x8b,0x72,0x7e,0x2c,0x33,0x63,0xf6,0x6f,0xf6,0x1,0xe8,0x7a,0x49,0x6d,0xce,0x1a,0x98,0x8f,0x7f,0x8c,0xcb,0x67,0x6d,0xca,0x77,0x8d,0xe2,0x85,0x9c,0x25,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x14,0x11,0x5,0x81,0x75,0x3e,0x22,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x1d,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x34,0x33,0x31,0xfb,0xcf,0x40,0x1,0x60,0xa2,0x44,0xf3,0xa8,0x1,0xa3,0x6,0x8c,0x1a,0x30,0x98,0xc,0x0,0x0,0xd6,0x1e,0x1,0xbf,0x4c,0xf9,0x63,0xb6,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char unchecked_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x34,0x0,0x2e,0x0,0x39,0xc0,0x34,0x46,0xdb,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x7,0x34,0x99,0x2b,0x2,0xd2,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x24,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x93,0x3b,0x4e,0x2,0x51,0x14,0x86,0xbf,0x61,0x26,0x23,0x8,0xc6,0xf8,0x62,0x6,0x8c,0x96,0x96,0x16,0x16,0x54,0x2e,0xc0,0xca,0x35,0x10,0x17,0x62,0xa2,0x9,0x6b,0xa0,0x73,0x11,0x56,0x2e,0xc0,0x86,0xc6,0xc2,0xd2,0xce,0x44,0x60,0x50,0x22,0xbe,0xc8,0xcc,0x5c,0xee,0xc3,0x6a,0x12,0x8,0x17,0x8c,0xcc,0x9f,0x9c,0xe6,0x26,0xe7,0xbb,0xe7,0xff,0x73,0x8e,0x63,0x8c,0x1,0x20,0x8,0x2,0x56,0x51,0x81,0x9c,0x9a,0x1,0xb8,0xc6,0x6f,0xba,0xc6,0xef,0xb8,0xc6,0x37,0xb,0xaa,0xe3,0x1a,0xbf,0x39,0xdd,0xe3,0x4d,0x35,0x5f,0x86,0xbb,0xf5,0xab,0xe3,0xa3,0x13,0xb6,0x37,0xf7,0xac,0xbf,0xbd,0x7f,0xbe,0x35,0x1e,0x9f,0x1e,0x1a,0xd1,0xb0,0x77,0xa8,0x1c,0x71,0xd,0xe0,0x64,0x19,0xd4,0xab,0x7,0xfd,0xb3,0xd3,0xf3,0x70,0x1c,0x8f,0x49,0xd2,0xd8,0xa,0x28,0xae,0x95,0x28,0x97,0xca,0xdc,0xdd,0xdf,0x46,0xca,0x11,0xb5,0x99,0x9,0x80,0xf0,0xe3,0x7b,0x84,0x52,0x6a,0xa1,0xdf,0x24,0x8d,0x99,0x48,0x1,0x10,0xce,0x59,0x0,0x48,0x45,0xf2,0x67,0x68,0x52,0x4d,0xb0,0x66,0x0,0x90,0xd9,0xf9,0x8f,0x66,0x0,0x52,0xca,0x7c,0x0,0x6d,0x54,0x4e,0x80,0xd6,0xb9,0x0,0x5d,0x21,0xc5,0xbe,0x57,0xf0,0x96,0x87,0xa8,0x25,0x40,0xd7,0xb6,0x89,0xed,0xc1,0xb0,0x87,0x90,0x2,0xa5,0xb5,0xb5,0x84,0x14,0xc,0x86,0x3d,0x80,0xf6,0xdc,0x4,0xca,0x11,0xad,0xf5,0x62,0x50,0x79,0x19,0x3c,0x5f,0x48,0x29,0xab,0xd6,0x71,0x3d,0xef,0x75,0x6b,0x63,0xe7,0xe6,0x2b,0x19,0xb5,0xb2,0x37,0x67,0xfa,0x1a,0xa3,0x7e,0xe4,0x3,0x95,0x25,0x47,0xa6,0x81,0x9f,0xb0,0x16,0xa,0x2b,0x60,0x15,0xfd,0x2,0x76,0xc9,0x92,0x92,0xf5,0xaf,0x5f,0x3b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x14,0x5,0x3b,0xd6,0x6,0x93,0xb9,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xf2,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x93,0xb1,0x4a,0xc4,0x50,0x10,0x45,0xcf,0x4b,0x26,0x71,0x2a,0xb7,0x58,0xc1,0xca,0x6f,0xb0,0xb4,0x74,0x75,0x59,0x11,0xbf,0xc1,0x1f,0xf0,0xaf,0xac,0xfc,0x1,0x61,0x11,0x45,0x85,0x5d,0xb6,0xb0,0xf4,0x1b,0xb4,0x10,0xd1,0x42,0xc1,0x65,0x30,0xb3,0x59,0x8b,0x24,0x10,0x10,0xf2,0x82,0xb5,0xb7,0x99,0xea,0xdc,0x79,0xf3,0xb8,0x37,0x50,0x29,0x0,0x9,0x20,0xf5,0xec,0x52,0x9,0x78,0x3d,0xd7,0xa1,0x86,0x33,0x60,0x8,0xec,0x0,0x9b,0x1d,0x26,0x25,0xf0,0x9,0x3c,0x1,0xef,0x40,0xd1,0x6c,0x1c,0x4a,0x2a,0xa3,0xf1,0xe1,0xe4,0x22,0xcb,0xb2,0xce,0xf5,0x45,0x51,0x70,0x7b,0x7f,0x73,0xea,0xee,0x77,0xc0,0x6b,0x0,0x36,0x80,0xdd,0xe3,0xa3,0x93,0x7,0x33,0xc3,0xcc,0x3a,0xd,0x54,0x15,0x55,0xe5,0xea,0x7a,0xba,0x7,0x3c,0x26,0xf5,0xb,0x6,0x22,0x12,0x85,0x1,0xcc,0xc,0x11,0x1,0x18,0x0,0x49,0x73,0x6b,0x88,0x92,0xbf,0x95,0x0,0x21,0xf6,0xe3,0xbd,0x5c,0xfe,0xd,0x2a,0xad,0xff,0xc0,0x96,0x8d,0x41,0x9,0x7c,0xb8,0x3b,0xaa,0x1a,0xa5,0x54,0x15,0x77,0x87,0x2a,0xd2,0xab,0x0,0xa4,0xc0,0x76,0x9e,0xe7,0x93,0x83,0xfd,0xf1,0x79,0x9f,0x28,0xcf,0x17,0xb3,0xb3,0xe5,0xf2,0xeb,0x12,0x78,0x69,0x97,0x69,0x8b,0xfe,0x65,0x7a,0x6,0xde,0x80,0xef,0x26,0x81,0xed,0x3a,0xa7,0x91,0x2b,0x56,0xb4,0xea,0xfc,0x3,0x6e,0x28,0x47,0x29,0x38,0xc5,0x49,0x7f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char updown_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x2b,0x8a,0x3e,0x7d,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x16,0x3a,0x99,0x23,0xd9,0x67,0x0,0x0,0x1,0x1,0x49,0x44,0x41,0x54,0x28,0xcf,0x85,0x91,0x3b,0x4e,0xc3,0x40,0x14,0x45,0x8f,0xc7,0x8e,0xad,0x28,0x2,0x45,0x4a,0x8a,0x20,0x50,0x24,0x36,0x40,0x83,0x44,0x8b,0x68,0xd8,0x4,0x9f,0x2e,0x9b,0x61,0x15,0xc8,0xde,0x45,0xa,0xa8,0x91,0xa8,0xd8,0x0,0x22,0x45,0x62,0x25,0x63,0x33,0xf6,0xc8,0x31,0x3f,0xcf,0xd0,0x38,0x28,0x38,0xa,0xdc,0xf2,0x9d,0x5b,0xbc,0xf3,0x1e,0xac,0x45,0x25,0x9a,0x66,0x44,0x3,0xa,0x19,0xab,0xcd,0x42,0xd,0x7d,0x63,0xec,0x1,0x30,0x5a,0x2f,0x79,0x2b,0x68,0xad,0xed,0x69,0x55,0xbc,0x0,0x74,0x76,0xda,0x6f,0x32,0x56,0x51,0x7f,0xd0,0xc5,0x51,0x89,0xf6,0xad,0xb5,0xbd,0xfc,0xb5,0x98,0x2,0x15,0xe0,0xd6,0xa5,0x6b,0x1c,0x22,0x61,0x8d,0xdd,0xaf,0xe1,0x97,0x1f,0xb4,0xee,0x3a,0xbb,0xed,0xb,0x80,0x42,0x97,0x21,0x70,0xe9,0x19,0x6b,0xf,0x1,0xfc,0xa0,0x75,0xbf,0x37,0xec,0x9f,0x3,0xc8,0x58,0xb9,0x85,0x2e,0x43,0x53,0x99,0x23,0x54,0xa2,0xdd,0x74,0x91,0x1d,0x37,0xf5,0xd2,0x79,0x76,0xf2,0x4b,0x73,0x5b,0x44,0x55,0x99,0x53,0xad,0x96,0x8f,0xb3,0x89,0x1c,0xaf,0x86,0x32,0x56,0x57,0x3a,0x5b,0x3e,0xcc,0xa7,0xe9,0x8d,0x27,0x1c,0xe7,0x19,0xe0,0xe3,0xfd,0xf3,0x6c,0x36,0x91,0xe3,0x56,0xe0,0xdd,0x16,0x79,0x19,0x2,0x8,0x57,0x3c,0xfd,0xa9,0xd9,0x1f,0x74,0x23,0xa7,0xbe,0xe4,0x7a,0xe9,0x7,0xd2,0x78,0x94,0x9f,0x2e,0xf2,0xa1,0x8c,0xd5,0x68,0xeb,0xc6,0x2a,0xd1,0xff,0x5a,0x6d,0xe4,0x1b,0x83,0x27,0x93,0x7,0x1d,0x11,0x34,0xe5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 -}; - - -static const unsigned char vscroll_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x24,0x11,0x6c,0x86,0xa1,0xf4,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x51,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x94,0x14,0x95,0x99,0xc6,0xc0,0xc0,0x90,0xc9,0x80,0x9,0xa6,0x33,0x30,0x30,0x64,0x31,0x4a,0x8a,0xca,0xfc,0x67,0x63,0x61,0x63,0xe0,0x60,0xe7,0x64,0x60,0x66,0x66,0x66,0x60,0x62,0x62,0x62,0x60,0x63,0x65,0x67,0x78,0xfe,0xfa,0x29,0xc3,0xd3,0x17,0x8f,0x44,0x99,0x18,0x8,0x80,0xc1,0xa0,0x80,0x85,0x81,0x81,0x61,0xfa,0xaf,0x3f,0xbf,0x32,0x7f,0xfd,0xf9,0x85,0xcd,0x9b,0x6f,0x0,0xae,0x38,0x11,0xcb,0x70,0x15,0x64,0xf2,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 -}; - - -static const unsigned char vscroll_bg_focus_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x24,0x1e,0xfc,0x39,0xbc,0x65,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x51,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x94,0x14,0x95,0x99,0xc6,0xc0,0xc0,0x90,0xc9,0x80,0x9,0xa6,0x33,0x30,0x30,0x64,0x31,0x4a,0x8a,0xca,0xfc,0x67,0x63,0x61,0x63,0xe0,0x60,0xe7,0x64,0x60,0x66,0x66,0x66,0x60,0x62,0x62,0x62,0x60,0x63,0x65,0x67,0x78,0xfe,0xfa,0x29,0xc3,0xd3,0x17,0x8f,0x44,0x99,0x18,0x8,0x80,0xc1,0xa0,0x80,0x85,0x81,0x81,0x61,0xfa,0xaf,0x3f,0xbf,0x32,0x7f,0xfd,0xf9,0x85,0xcd,0x9b,0x6f,0x0,0xae,0x38,0x11,0xcb,0x70,0x15,0x64,0xf2,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 -}; - - -static const unsigned char vscroll_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x27,0x14,0x37,0xc1,0x6,0xb8,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x9c,0x49,0x44,0x41,0x54,0x18,0xd3,0x7d,0x8f,0x3d,0xb,0x82,0x40,0x0,0x40,0x9f,0xe7,0x75,0x67,0x4,0x41,0x86,0xa1,0x20,0xcd,0x4d,0xd1,0x10,0xb4,0xf4,0xf3,0x5b,0x5a,0x83,0x86,0xa6,0x8,0xa2,0xec,0x73,0xca,0xf2,0x2e,0xb5,0x26,0xf,0x5a,0x7a,0xe3,0xe3,0x2d,0xcf,0x4b,0xa2,0xf4,0xd3,0xeb,0x86,0xe4,0xcf,0x7,0xb6,0xb4,0x48,0x29,0x1,0x28,0xcb,0x12,0xc0,0x93,0x0,0xf6,0x6d,0x18,0xf4,0x13,0xd2,0x78,0x88,0x56,0x1,0x9b,0xed,0x9a,0xec,0x7a,0x60,0x32,0x9a,0x22,0x0,0xa2,0x30,0x46,0xab,0x0,0x63,0xb,0x8c,0x2d,0x98,0x8d,0xe7,0x34,0x8,0x0,0x21,0x84,0x13,0x55,0x55,0xd1,0xd6,0x9d,0xdf,0xe0,0x1f,0x2,0xa0,0xae,0x6b,0x27,0x7c,0xdf,0xe7,0x65,0xf2,0xdf,0xe0,0x72,0xcf,0x30,0xb6,0x40,0xab,0x0,0xad,0x2,0x96,0xab,0x85,0xb,0x24,0x80,0x6a,0x69,0xce,0xb7,0x23,0xfb,0xd3,0xce,0x6d,0x36,0x7c,0x1,0xa3,0x8f,0x31,0x52,0x6,0xb1,0x57,0x8b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 -}; - - -static const unsigned char vscroll_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x27,0x25,0x66,0x1f,0x6,0x82,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xa2,0x49,0x44,0x41,0x54,0x18,0xd3,0x7d,0x8f,0x3b,0xf,0xc1,0x50,0x0,0x46,0x8f,0xdb,0x56,0xef,0x65,0x32,0x78,0x4,0xd,0x91,0xe,0x46,0x83,0xc1,0x6a,0xf0,0xab,0xd,0x56,0x8b,0xc1,0x24,0x91,0x48,0xbc,0xe2,0x31,0x12,0xf4,0x5e,0x57,0xcb,0xa4,0xd2,0xc5,0x19,0x4f,0xce,0x37,0x7c,0xb9,0x76,0x23,0x7c,0x97,0x4b,0x15,0xae,0xb7,0xb,0xc6,0x1a,0x3c,0xcf,0x3,0xc0,0x5a,0x8b,0x79,0xea,0x9c,0xb,0x60,0x9e,0x9a,0x66,0xad,0x45,0x27,0x8,0x91,0x52,0x31,0x5f,0xcc,0xd8,0x1e,0xd7,0xf4,0xba,0x7d,0x4,0x40,0xbd,0x1a,0xa0,0xfc,0x2,0xda,0x44,0x68,0x1d,0x31,0x1c,0x8c,0xf8,0x22,0x0,0x84,0x70,0x52,0xf1,0x8a,0x63,0x94,0x2c,0x66,0x83,0x7f,0x8,0x80,0x24,0x89,0x53,0xe1,0x3a,0xe,0x91,0xbe,0x67,0x83,0xc3,0x79,0x47,0x64,0x1e,0x48,0x5f,0x21,0xa5,0x62,0x32,0x1d,0xff,0x6,0x0,0x7e,0x5e,0xb2,0x3f,0x6d,0x58,0xed,0x96,0xe9,0xcd,0x2f,0x1f,0x74,0x4f,0x34,0x2d,0xfc,0x9b,0x87,0x78,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x2b,0x8a,0x3e,0x7d,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x2a,0x25,0x8e,0xd3,0xb6,0x1b,0x0,0x0,0x0,0xfb,0x49,0x44,0x41,0x54,0x28,0x91,0x85,0x8f,0xbd,0x4a,0xc4,0x40,0x14,0x46,0xbf,0x4c,0x26,0xd3,0x4c,0x23,0x6c,0xa,0x83,0xb2,0xe0,0xb,0xd8,0x8,0xb6,0x62,0xe3,0x4b,0xf8,0xd3,0xed,0xcb,0xf8,0x14,0x92,0xbc,0xc5,0x16,0x5a,0xb,0x56,0xbe,0x80,0xd8,0x38,0x4b,0x98,0xc,0x97,0x4c,0x6,0x24,0x64,0x66,0x6c,0xb2,0xb2,0xc9,0xb2,0x7a,0xca,0x7b,0x4e,0x71,0x3f,0x60,0x7,0x6a,0x2c,0xe6,0xb0,0x89,0x4c,0x3d,0xd3,0x1b,0xda,0xf,0x46,0x29,0x42,0x8,0xa7,0xe0,0xc3,0x6a,0x37,0xe2,0x5b,0x19,0x63,0x5c,0x58,0x6b,0x3f,0x1,0x40,0x4a,0xf9,0xad,0x37,0x54,0xe5,0xc7,0x47,0x48,0x88,0x48,0xc4,0x18,0x17,0x6d,0xdb,0x7e,0x1,0xf0,0x0,0xd2,0x31,0x7a,0x80,0xe7,0x15,0xb,0x21,0x9c,0x8c,0x72,0x10,0x42,0x3c,0x4b,0x29,0x6f,0x1,0xc0,0x39,0x57,0x22,0x1d,0xee,0x78,0x8c,0xf1,0xc,0x0,0x84,0x10,0x2f,0x45,0x51,0xdc,0x0,0x80,0xd6,0x3a,0x75,0xce,0x95,0x21,0x84,0x73,0x10,0x51,0x6a,0x8c,0xb9,0x98,0xcf,0x6b,0x9a,0xe6,0x72,0x32,0xf3,0x10,0xcc,0x7b,0x7f,0x65,0xad,0x7d,0x53,0x4a,0xad,0xb7,0x47,0xad,0xf5,0x7d,0xd7,0x75,0xaf,0x75,0x5d,0x3f,0xf2,0x24,0x49,0x3e,0x0,0xa0,0xef,0xfb,0x6b,0xa5,0xd4,0x3a,0xcb,0xb2,0x27,0xe7,0x5c,0x9,0x0,0x8c,0xb1,0xf7,0x3f,0x67,0xe6,0x79,0x5e,0x25,0x0,0x30,0x8b,0x7e,0xe5,0xe4,0x19,0x22,0x12,0xc6,0x98,0xa5,0xd6,0x7a,0x75,0xf0,0x63,0x22,0xfa,0x77,0xd5,0x1e,0x3f,0x3b,0xb0,0x99,0x1,0x70,0x56,0xb8,0xf7,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -440,32 +440,32 @@ static const unsigned char vseparator_png[]={ static const unsigned char vslider_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x16,0x2b,0x31,0xd7,0x79,0x35,0x2f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0x93,0x31,0x6a,0x2,0x51,0x14,0x45,0xcf,0x7f,0xff,0x39,0xa2,0x19,0x3,0x21,0x28,0xa,0xae,0x23,0xeb,0x9,0x76,0xb3,0x89,0x58,0x9,0xd9,0xc1,0x74,0x71,0x3f,0xb1,0xb1,0x73,0x3,0x8a,0xa0,0x84,0x14,0x13,0x23,0x84,0xef,0xfb,0xe9,0x44,0xe4,0x8b,0x4e,0xef,0x2d,0x2f,0xe7,0x9e,0xee,0x3a,0x12,0x19,0x74,0x87,0x6f,0x40,0x1,0xf4,0x81,0x15,0x50,0xae,0xb7,0xcb,0x49,0x8a,0x75,0x89,0xf1,0xab,0xf7,0x7e,0x9a,0x69,0x46,0xd6,0x68,0xa2,0xaa,0xfc,0xee,0x77,0xe4,0xed,0xc7,0xf7,0xf9,0x62,0x36,0x16,0x2f,0x7f,0xa7,0xbc,0x24,0xa4,0x85,0x73,0xe,0x11,0x41,0x44,0x70,0x8,0xf,0xad,0xe,0xdf,0xd5,0xd7,0x8,0xc8,0xcf,0xe1,0x94,0xe0,0x45,0x10,0xc4,0xf9,0x63,0xa1,0xaa,0x84,0x10,0x7a,0x29,0x3e,0x25,0xa8,0x95,0xbb,0xe0,0x2e,0xb8,0x24,0xf8,0x34,0xc,0x8b,0x87,0x63,0x11,0x42,0x40,0x55,0x37,0x80,0xdd,0x22,0x28,0x63,0x8c,0x98,0x19,0x66,0x46,0xc4,0xd8,0xed,0x2b,0x9e,0x3a,0xcf,0x1f,0xc0,0xcf,0xd5,0x37,0xd6,0xbd,0xf3,0x3f,0xe8,0xbb,0x37,0x1e,0x27,0x3c,0x2c,0x9e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xdd,0x0,0xdd,0x0,0xdd,0xf5,0x15,0x8,0x9d,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xf,0xc,0x18,0x82,0xe,0xe5,0x21,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x4d,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x68,0xc0,0x88,0x4d,0x50,0x42,0x42,0x62,0x1a,0x3,0x3,0x43,0x26,0x9a,0xf0,0xf4,0x17,0x2f,0x5e,0x64,0x11,0x6b,0xc0,0x7f,0x76,0x76,0x4e,0x14,0xb1,0x9f,0x3f,0xbf,0x33,0xbc,0x78,0xf1,0x2,0x43,0x3d,0x13,0xd1,0x6e,0xc5,0x1,0x46,0xd,0x18,0x35,0x0,0x9f,0x1,0xd3,0x7f,0xfe,0xfc,0xce,0x80,0x8c,0x19,0x18,0x18,0xa6,0x53,0x6a,0x19,0x6d,0x0,0x0,0x59,0x9c,0x18,0xe9,0x50,0xa4,0x59,0x7a,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char vslider_grabber_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x16,0x2a,0xf,0xf,0x3,0x19,0xc5,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xa7,0x49,0x44,0x41,0x54,0x38,0xcb,0xc5,0x93,0x3d,0x4c,0x14,0x41,0x18,0x86,0x9f,0x6f,0x66,0x5d,0xd8,0x2c,0x97,0x3b,0xee,0x64,0x4e,0x2e,0x78,0x86,0xd8,0x99,0xd8,0x5e,0x6c,0x24,0x26,0x56,0x36,0x26,0x26,0x5a,0x51,0x59,0xda,0x6a,0x3,0xad,0xd,0x34,0x5a,0x99,0xd0,0x58,0xd8,0x9f,0x15,0x8d,0x95,0x21,0xa1,0x32,0x86,0x10,0xa3,0x89,0x31,0x24,0xc4,0xe3,0xef,0xc0,0xe5,0x27,0x22,0x5e,0x56,0xf6,0x6e,0xf9,0x2c,0xe4,0x4e,0x90,0x43,0x4a,0xbe,0x62,0x32,0x33,0xc9,0xfb,0xce,0x3b,0xcf,0x37,0x3,0xe7,0x5d,0x52,0xa9,0x54,0x0,0xa8,0xd5,0x6a,0x9d,0xcd,0x7b,0xb7,0x46,0x6f,0x4e,0xcf,0x54,0x67,0xff,0xa3,0xdb,0x0,0xa6,0x52,0x49,0x9e,0xca,0xed,0x1b,0x77,0x0,0x78,0xfb,0xee,0xd,0xce,0x39,0xac,0xfa,0xf7,0xad,0xb5,0x55,0x97,0xbf,0xc4,0xc5,0x9c,0x43,0x44,0x10,0x31,0x88,0x11,0x8c,0x80,0x7f,0xa1,0x97,0x5c,0xa6,0x9f,0xf,0x5f,0xe6,0xd8,0xd8,0xaa,0x3f,0xb4,0x3,0xa5,0x3c,0x89,0xc6,0x34,0x9b,0x4d,0xac,0xfa,0x8f,0x3d,0xcf,0x7b,0x39,0x54,0xbc,0x42,0xb6,0xaf,0xff,0x50,0x2c,0x88,0x1,0x3,0x88,0x18,0x40,0x50,0x55,0x86,0x8a,0x65,0x16,0x57,0x16,0x4a,0xa6,0x9d,0xc9,0xaa,0x3f,0x11,0xf4,0x4,0xcf,0xca,0x83,0xc3,0x84,0x41,0x78,0x3c,0xb0,0xa,0x2a,0x7f,0x97,0xbf,0xf6,0x63,0xf2,0xd9,0x1,0x80,0x8a,0xc9,0x98,0x2,0x2b,0x5f,0xeb,0x13,0x61,0x10,0x8e,0x95,0x5c,0x19,0xdf,0xf3,0xff,0xc5,0x74,0x38,0xa,0xa0,0x27,0x60,0x78,0x9f,0x17,0x3f,0x3d,0xca,0xf6,0xe5,0xc6,0x8a,0x85,0x41,0x44,0xa4,0xb,0x2f,0xfd,0x23,0xd6,0x8e,0xd7,0xb1,0x32,0x80,0x3d,0xab,0x55,0xa,0xe8,0x29,0xe,0xe6,0xda,0xd5,0xeb,0x2f,0x76,0x7f,0x7e,0x9f,0x5c,0x8b,0x96,0x69,0xa5,0xe9,0xe9,0xfd,0xee,0x76,0x3c,0x60,0xf6,0xe,0xb6,0xb9,0x3c,0x5c,0x1a,0x6f,0xc4,0x8d,0xc9,0x7a,0xb4,0x4c,0xd2,0x4a,0xba,0x88,0x15,0x15,0xed,0x6e,0xd0,0x9e,0xa4,0x92,0x8c,0xc7,0xfb,0xf1,0x93,0xd5,0xf5,0x25,0x1a,0x71,0xe3,0xc4,0x15,0x8e,0x26,0xe8,0xed,0x9,0xd8,0xd9,0xdd,0x4,0x78,0x6f,0x32,0xa6,0x40,0xc6,0x14,0x88,0xa2,0x88,0x54,0x92,0xe7,0x49,0x2b,0x79,0xb0,0xfa,0x6d,0x89,0x9d,0x1f,0x5b,0x47,0x98,0x4b,0x87,0x82,0xb5,0x96,0x30,0x8,0xf9,0xb8,0x30,0xf,0x30,0xe5,0xed,0x1d,0x6c,0x3,0xe0,0x9c,0x6b,0x27,0x79,0x7d,0x77,0x64,0x74,0x64,0x7a,0xa6,0x3a,0xbb,0xbe,0xb9,0x76,0xd6,0x53,0x7e,0x75,0xee,0x9f,0x91,0xdf,0x78,0x37,0x8a,0xe3,0x79,0x7e,0x6,0x97,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x92,0x0,0x92,0x0,0x99,0x25,0xc1,0x88,0x71,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x2,0x1f,0xac,0xde,0x45,0xed,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xa4,0x49,0x44,0x41,0x54,0x38,0x8d,0x9d,0x93,0xb1,0x6e,0x1a,0x41,0x14,0x45,0xcf,0xcc,0xce,0x9a,0x85,0x25,0x44,0x58,0x8a,0x15,0xc5,0x49,0x93,0x2,0xb2,0x2,0x51,0xf2,0x7,0x2e,0x68,0xf2,0x15,0xae,0x22,0xc1,0x77,0xa4,0xe,0x65,0x5c,0xe4,0x2f,0xf8,0xb,0x47,0xb6,0x2c,0x21,0xb0,0x44,0xb7,0x22,0x52,0x9a,0x0,0x82,0x9d,0xd9,0x1d,0x76,0xd3,0xec,0x22,0x40,0xb1,0x8d,0x72,0xa5,0x29,0xe6,0xcd,0xbd,0xf7,0xbd,0x79,0x33,0x4f,0x70,0x84,0x66,0xb3,0x79,0x1c,0x3a,0xc0,0x64,0x32,0x39,0xd8,0xcb,0x7f,0x88,0x2f,0x81,0xaf,0xc0,0x1d,0x10,0xe5,0xeb,0x2e,0x8f,0x5d,0x1e,0x27,0x10,0xdd,0x6e,0x17,0x80,0xc5,0x62,0x1,0x70,0xd,0x7c,0xb,0x82,0x76,0xb9,0x52,0xf1,0x71,0xdd,0x33,0x0,0x92,0x24,0x66,0xb3,0x59,0x33,0x1e,0x3f,0x44,0xc0,0xc0,0x5a,0x7b,0xb3,0x5e,0xaf,0x49,0xd3,0x14,0xe7,0xd3,0x87,0xe,0xbf,0xff,0xfc,0x2,0xb8,0xae,0xd7,0xcf,0xbf,0xb7,0x5a,0x1d,0xb7,0x5a,0xad,0xa1,0x94,0x42,0x8,0x81,0x10,0x2,0xa5,0x14,0xe5,0x72,0x85,0x8b,0x8b,0xb7,0xae,0xd6,0xd1,0xe7,0x38,0x36,0xa1,0xef,0xfb,0xb7,0x5a,0x6b,0x9c,0x33,0xdf,0x29,0xca,0x1e,0xb5,0x5a,0x1d,0xb7,0x54,0xf2,0x9e,0xbc,0xbf,0x52,0x8a,0x5a,0xed,0x35,0xf3,0x79,0x78,0x95,0x65,0xd9,0xf,0x6b,0xed,0xaa,0xe8,0x41,0x3f,0x8,0xda,0xe5,0xe7,0xc4,0x5,0x4a,0x25,0x8f,0x20,0x68,0x97,0x81,0xbe,0xeb,0xba,0xbb,0x26,0xf6,0x2a,0x15,0xff,0x45,0x71,0x81,0x9c,0xdb,0x53,0x4a,0x21,0xb3,0x2c,0x3,0x68,0x14,0xd,0x3b,0x5,0x39,0xb7,0x21,0xa5,0x3c,0x7c,0xc6,0xff,0x81,0x14,0x42,0x0,0x4c,0x93,0x24,0x3e,0x59,0x94,0x73,0xa7,0x69,0x9a,0xee,0x2a,0x18,0x6d,0x36,0xeb,0x93,0xd,0x72,0xee,0xc8,0x5a,0xbb,0x33,0x18,0x8e,0xc7,0xf,0x91,0x31,0xfa,0x45,0xb1,0x31,0xba,0xf8,0x50,0xc3,0x24,0x49,0x90,0xef,0xeb,0x1f,0x1,0x42,0x60,0x30,0x9b,0x3d,0xf2,0x9c,0x89,0x31,0x9a,0xd9,0xec,0x11,0x60,0xe0,0x38,0x4e,0xb8,0xdd,0x6e,0x71,0xde,0xbc,0x3b,0xc7,0xf3,0x3c,0x8c,0x31,0xb7,0x5a,0x47,0xe1,0x7c,0x1e,0x5e,0x55,0xab,0xaf,0x5c,0x29,0x25,0x52,0x4a,0xb2,0x2c,0x23,0x8e,0xd,0xab,0xd5,0x82,0xfb,0xfb,0x9f,0x91,0xd6,0xd1,0x17,0x6b,0xed,0xcd,0x72,0xb9,0x24,0x4d,0x53,0xc4,0x7e,0x86,0xbd,0x61,0xea,0x3,0x3d,0xa0,0x91,0x1f,0x4d,0x81,0x11,0x30,0x4,0xc2,0xfd,0x89,0x3c,0x30,0xd8,0x33,0x79,0x12,0xc7,0xe3,0xfc,0x17,0x9c,0xcc,0xa8,0xb2,0xd4,0xe8,0x7,0x23,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char vslider_grabber_hl_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4b,0x0,0x3f,0x0,0x52,0x7c,0x32,0x40,0x52,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x16,0x2b,0x3,0x1f,0xae,0x64,0xaf,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0xac,0x49,0x44,0x41,0x54,0x38,0xcb,0xc5,0x93,0xb1,0x6f,0xd3,0x40,0x14,0x87,0xbf,0x77,0x8e,0x5d,0x9c,0xc4,0x55,0xe3,0x10,0x43,0x4c,0xa1,0x44,0xa8,0x42,0xe2,0xf,0x88,0xba,0xc0,0x82,0x18,0x60,0x86,0xad,0xb,0x4b,0x25,0x56,0x58,0xda,0x95,0xa5,0x5d,0x60,0x42,0xea,0xc2,0x80,0xd4,0xad,0x65,0xcf,0xd4,0xa5,0x53,0x55,0x21,0x26,0x14,0x89,0x4a,0x55,0x1c,0x28,0x25,0xd,0x4,0x2a,0x92,0xd6,0xc4,0x86,0x1c,0x4b,0x13,0x1a,0x62,0x60,0xec,0x1b,0x9e,0xee,0x7e,0xa7,0xf7,0xf4,0xdd,0xef,0xdd,0xc1,0x69,0x87,0x94,0xcb,0x65,0x0,0x82,0x20,0x18,0x88,0xb3,0x77,0xe6,0xae,0xaf,0x56,0x56,0x36,0xfe,0x51,0xd7,0x0,0x96,0x23,0x1d,0x3e,0x96,0x9b,0x33,0xb7,0x1,0x58,0xdf,0xac,0xe0,0x79,0x1e,0x96,0xd8,0x77,0x8d,0x54,0x6a,0xad,0x78,0xf6,0x2,0x9e,0x7b,0x1e,0x11,0x41,0x44,0xa1,0xc,0x41,0x9,0x58,0xa6,0x4d,0x6e,0xdc,0xe5,0xd5,0x9b,0x4d,0x3e,0xec,0xbf,0xbb,0x6f,0x14,0x7c,0x97,0x48,0x87,0xc4,0x71,0x8c,0x25,0xf6,0x43,0xd3,0x34,0x9f,0x4f,0xf9,0x57,0xc8,0x39,0xee,0x71,0xb1,0x20,0xa,0x94,0x6,0x51,0xa,0x10,0xb4,0xd6,0x5c,0x2a,0x5e,0x66,0x3b,0xa8,0xfa,0xaa,0xcf,0x64,0x89,0xbd,0x98,0x3e,0x93,0x79,0x52,0x9a,0x9c,0x26,0x9b,0xce,0xe,0x3,0x6b,0x41,0xab,0xdf,0xdb,0xb0,0x1b,0x92,0x9f,0x28,0x0,0x94,0x95,0xa3,0xf2,0xec,0xd5,0xf7,0x17,0xb3,0x19,0x67,0xfe,0x62,0xb1,0xc4,0x98,0x69,0xfd,0x69,0xd3,0x71,0x16,0x40,0x8f,0x98,0x91,0x7a,0x5b,0xab,0x3e,0xc8,0x8d,0xbb,0xf3,0x7e,0x61,0x12,0x51,0x92,0xe0,0x97,0x46,0x21,0xd0,0x3,0x8c,0xd1,0x53,0x95,0x2c,0xf,0x47,0xf,0xd0,0xe8,0x1,0xcd,0x50,0x83,0xab,0xa5,0x6b,0xcf,0xbe,0x7e,0xfb,0xb2,0x54,0x6f,0xd4,0x88,0x7f,0xfc,0xfc,0xfb,0xbc,0x91,0x44,0x5d,0xb5,0x7b,0x2d,0xfc,0xa9,0x73,0xb,0x9d,0xc3,0xf6,0xd2,0xfb,0x8f,0x35,0xba,0x71,0x94,0x80,0xa9,0xd1,0x4a,0x27,0x37,0xe8,0x2f,0x22,0x1d,0x2e,0x1c,0x7d,0x3f,0x7c,0x54,0xdf,0xdd,0xa1,0x73,0xd4,0x19,0xb9,0xc2,0x49,0x2,0x7b,0xcc,0xa6,0x75,0xf0,0x9,0x60,0x4b,0x39,0x2a,0x8f,0xa3,0xf2,0x34,0x9b,0x4d,0x22,0x1d,0x3e,0xed,0xc6,0xdd,0x7b,0xc1,0xde,0xe,0x9f,0xf,0x9a,0x27,0x3c,0x97,0x81,0xb,0x86,0x61,0x90,0x49,0x67,0x79,0x5d,0xdd,0x2,0x58,0x4e,0xb5,0x7b,0x2d,0x0,0x3c,0xcf,0xeb,0x93,0xbc,0x9c,0xbd,0x35,0x77,0x63,0xb5,0xb2,0xb2,0xb1,0xdb,0xa8,0xff,0xef,0x29,0xbf,0x38,0xf5,0xcf,0xc8,0x2f,0x96,0x82,0x8d,0xc9,0x9c,0xd1,0x82,0x63,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x92,0x0,0x92,0x0,0x99,0x25,0xc1,0x88,0x71,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x12,0x0,0x2,0x21,0x6d,0xbf,0x58,0x46,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x30,0x49,0x44,0x41,0x54,0x38,0x8d,0xa5,0x93,0xb1,0x6a,0xc2,0x50,0x14,0x86,0xbf,0x63,0xe2,0x90,0xd0,0x2e,0xc1,0xad,0x8b,0xad,0x60,0x9e,0xc0,0xbe,0x41,0x7,0x33,0x38,0x7,0x1d,0xba,0x74,0x2a,0xe8,0xc3,0xe8,0x68,0xc1,0x49,0xc8,0xec,0x10,0x9f,0xa1,0x8,0xee,0x71,0xcf,0x52,0x4d,0x70,0x73,0x8a,0xb7,0x83,0x37,0x72,0x11,0xb4,0xa1,0xfe,0xe3,0xe5,0x7c,0xdf,0xbd,0x1c,0xfe,0xb,0x77,0x46,0x2e,0xf,0x7c,0xdf,0x7f,0x2,0x86,0x40,0x17,0x68,0xeb,0xe3,0xd,0xb0,0x4,0x26,0x49,0x92,0xa4,0x57,0x5,0xbe,0xef,0x7f,0x0,0xe3,0x30,0x1c,0x38,0x9e,0xd7,0x40,0xa4,0x6,0x80,0x52,0x47,0xf2,0x7c,0x47,0x14,0xcd,0xf,0xc0,0x28,0x49,0x92,0xaf,0x92,0xb1,0x4c,0xb8,0xd9,0x7c,0x9e,0xf6,0xfb,0xef,0x75,0xd7,0x7d,0xd4,0xb0,0x0,0x82,0x48,0xd,0xd7,0x7d,0xa0,0xd3,0x79,0xad,0x6f,0xb7,0x3f,0x3d,0xdb,0xb6,0xd2,0x2c,0xcb,0xd6,0x0,0x35,0xe3,0xd9,0xe3,0x20,0xe8,0x21,0x62,0x71,0x2d,0x22,0x16,0x41,0xd0,0x3,0x18,0x6b,0xe6,0x24,0x0,0x86,0x61,0x38,0x70,0x6e,0xc1,0xa6,0x24,0xc,0x7,0x8e,0xde,0xd3,0x59,0xd0,0xf5,0xbc,0xc6,0x9f,0x70,0x19,0x3d,0xdb,0x35,0x5,0xed,0x72,0x61,0x55,0xa2,0x67,0xdb,0xa6,0xe0,0xdf,0x29,0x5,0x1b,0xa5,0x8e,0x95,0x21,0x3d,0xbb,0x31,0x5,0xcb,0x3c,0xdf,0x55,0x16,0xe8,0xd9,0xa5,0x29,0x98,0x44,0xd1,0xfc,0xa0,0x54,0x51,0xe1,0xf6,0xa2,0x2c,0xd4,0xe4,0x2c,0xd0,0xf5,0x1c,0xc5,0xf1,0x82,0x5b,0x12,0xa5,0xa,0xe2,0x78,0x1,0xa7,0x36,0xa6,0x60,0x34,0x31,0xcb,0xb2,0xb5,0x6d,0x5b,0xe9,0x6a,0xf5,0xfd,0xd6,0x6a,0xbd,0xd4,0x1d,0xc7,0x41,0x44,0x34,0x78,0x24,0xcf,0xb7,0xcc,0x66,0xd3,0xc3,0x7e,0xbf,0xff,0x34,0xab,0x7c,0xf7,0x67,0xba,0x3b,0xbf,0x4d,0x78,0x75,0x34,0x1f,0x21,0x5d,0xa6,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char vslider_tick_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x4,0x8,0x6,0x0,0x0,0x0,0x87,0xb4,0xbf,0xec,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xb,0x4,0x17,0x21,0x6,0x30,0xa,0xe5,0x29,0x0,0x0,0x0,0x46,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0xa0,0x10,0x30,0xb6,0xd7,0xd6,0x56,0x72,0x73,0x73,0x33,0x70,0x73,0x73,0x33,0x3c,0xe1,0x97,0x6a,0xe7,0xe6,0xe2,0x66,0x28,0x9,0xf1,0xc0,0xaa,0xd8,0x22,0x34,0x9e,0x41,0xfa,0xcb,0x6b,0x43,0x13,0x13,0x63,0xf,0x98,0x1e,0x96,0x33,0x67,0xce,0xee,0x80,0x29,0x78,0xca,0x23,0x4a,0x8c,0xa5,0xaf,0x91,0xf5,0x50,0xc,0x0,0x35,0x9a,0x11,0x6d,0xa1,0xf1,0x5c,0x24,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x4,0x8,0x6,0x0,0x0,0x0,0x87,0xb4,0xbf,0xec,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x28,0x1f,0x7a,0xe9,0xd,0x2b,0x0,0x0,0x0,0x46,0x49,0x44,0x41,0x54,0x18,0x95,0x63,0x60,0xa0,0x10,0x30,0x36,0x35,0x35,0x55,0x72,0x73,0x73,0x33,0x70,0x73,0x73,0x33,0xbc,0xe4,0x12,0x6d,0xe7,0xe6,0xe2,0x66,0x28,0x9,0xf1,0xc0,0xaa,0xd8,0x22,0x34,0x9e,0x41,0xec,0xe7,0x7b,0x43,0x13,0x13,0x13,0xf,0x98,0x1e,0x96,0x33,0x67,0xce,0xec,0x80,0x29,0x78,0xc5,0x2e,0x48,0x8c,0xa5,0xaf,0x91,0xf5,0x50,0xc,0x0,0x36,0xc,0x11,0x6c,0x6d,0xa6,0x47,0xcd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char vsplit_bg_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x3b,0x0,0x36,0x0,0x38,0x27,0x56,0x13,0x54,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xc,0x1b,0x3,0x20,0x0,0x61,0x7,0xe1,0x28,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x7b,0x49,0x44,0x41,0x54,0x18,0xd3,0x4d,0x8c,0xc1,0xe,0xc2,0x30,0x14,0xc3,0x1c,0xe8,0x6f,0x22,0x2e,0xfc,0xbf,0x34,0xa4,0x6d,0x54,0xcd,0x6b,0x38,0x6c,0x82,0xf9,0x92,0x83,0x23,0xeb,0xf5,0x78,0xa6,0x7f,0x3a,0x21,0x48,0xe2,0x20,0x80,0x58,0xd7,0x95,0xb6,0x2c,0x6f,0x5c,0x86,0x5c,0xe,0x87,0x67,0xdb,0x76,0x9a,0x4,0x55,0x86,0x8,0x94,0xff,0x22,0x1c,0xd3,0x5c,0x13,0xbb,0xce,0xb4,0x90,0x72,0x4,0x2,0x35,0x43,0xb3,0x7,0x55,0x75,0xea,0x5f,0x9d,0x0,0x99,0xa1,0x55,0x15,0xbe,0x1c,0xae,0x4c,0x9b,0xe6,0x2a,0x66,0x99,0x20,0x8,0xe8,0x18,0x0,0x86,0x4d,0xeb,0xfd,0xc3,0xbe,0x77,0x44,0xb8,0xdd,0xee,0xff,0x3e,0x61,0x8c,0xc1,0x17,0xf5,0xc0,0x57,0xfd,0xb2,0x2f,0x89,0xfc,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x13,0x1b,0xd5,0xd9,0x6e,0x6b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x15,0x49,0x44,0x41,0x54,0x18,0x95,0x63,0x54,0x57,0xd7,0xfc,0xcf,0x80,0x7,0x30,0xe1,0x93,0x1c,0x3e,0xa,0x0,0x86,0x1b,0x1,0x86,0x56,0xb4,0xba,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; static const unsigned char vsplitter_png[]={ -0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0x49,0x62,0xf9,0xdf,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0xc,0x18,0xf,0x2c,0x3,0x4f,0x14,0xa9,0x14,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x36,0x49,0x44,0x41,0x54,0x48,0xc7,0x63,0x60,0x18,0x5,0xc,0xc,0xcb,0x66,0xcd,0xf9,0x9f,0x1d,0x9f,0xf4,0x7f,0x24,0xf2,0x99,0x18,0x18,0x18,0x18,0x8e,0x1e,0x3d,0xc6,0x70,0xf9,0xe6,0x75,0x78,0x80,0x8c,0x34,0xfe,0x28,0x18,0x2d,0x3,0x46,0xcb,0x80,0xd1,0x32,0x60,0xc4,0x2,0x0,0x41,0x33,0x3b,0x34,0xfe,0xbe,0xf2,0x77,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0x49,0x62,0xf9,0xdf,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0xf,0x14,0x27,0x31,0x21,0xa7,0x1c,0x2b,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x48,0x89,0x63,0x60,0x18,0x5,0xc,0xc,0xb,0x16,0x2c,0xf8,0x9f,0x9a,0x9a,0xfa,0x7f,0x24,0xf2,0x99,0x18,0x18,0x18,0x18,0x8e,0x1e,0x3d,0xca,0x70,0xed,0xda,0x35,0x78,0x80,0x8c,0x34,0xfe,0x28,0x18,0xf1,0x60,0x30,0xe5,0x49,0x7a,0xf3,0x47,0xcb,0x80,0x91,0xe,0x0,0x53,0x40,0x3b,0xd4,0x11,0xa7,0x10,0x39,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; diff --git a/scene/resources/default_theme/toggle_off.png b/scene/resources/default_theme/toggle_off.png Binary files differindex d5809cd72b..3e92aa0ece 100644 --- a/scene/resources/default_theme/toggle_off.png +++ b/scene/resources/default_theme/toggle_off.png diff --git a/scene/resources/default_theme/toggle_on.png b/scene/resources/default_theme/toggle_on.png Binary files differindex 692e03b01d..a49c234f51 100644 --- a/scene/resources/default_theme/toggle_on.png +++ b/scene/resources/default_theme/toggle_on.png diff --git a/scene/resources/default_theme/tooltip_bg.png b/scene/resources/default_theme/tooltip_bg.png Binary files differindex c61169f7fc..c5eb502ace 100644 --- a/scene/resources/default_theme/tooltip_bg.png +++ b/scene/resources/default_theme/tooltip_bg.png diff --git a/scene/resources/default_theme/tree_bg.png b/scene/resources/default_theme/tree_bg.png Binary files differindex e16317d348..6b9c9b4f8d 100644 --- a/scene/resources/default_theme/tree_bg.png +++ b/scene/resources/default_theme/tree_bg.png diff --git a/scene/resources/default_theme/tree_title.png b/scene/resources/default_theme/tree_title.png Binary files differindex 7104085467..e7a158b961 100644 --- a/scene/resources/default_theme/tree_title.png +++ b/scene/resources/default_theme/tree_title.png diff --git a/scene/resources/default_theme/tree_title_pressed.png b/scene/resources/default_theme/tree_title_pressed.png Binary files differindex ffba8e8fb1..82b49cdd2f 100644 --- a/scene/resources/default_theme/tree_title_pressed.png +++ b/scene/resources/default_theme/tree_title_pressed.png diff --git a/scene/resources/default_theme/unchecked.png b/scene/resources/default_theme/unchecked.png Binary files differindex 65b9ba4d23..39a70e6003 100644 --- a/scene/resources/default_theme/unchecked.png +++ b/scene/resources/default_theme/unchecked.png diff --git a/scene/resources/default_theme/updown.png b/scene/resources/default_theme/updown.png Binary files differindex 8d4189cf1c..a5ca1212e0 100644 --- a/scene/resources/default_theme/updown.png +++ b/scene/resources/default_theme/updown.png diff --git a/scene/resources/default_theme/vscroll_bg.png b/scene/resources/default_theme/vscroll_bg.png Binary files differdeleted file mode 100644 index 18b79553b7..0000000000 --- a/scene/resources/default_theme/vscroll_bg.png +++ /dev/null diff --git a/scene/resources/default_theme/vscroll_bg_focus.png b/scene/resources/default_theme/vscroll_bg_focus.png Binary files differdeleted file mode 100644 index 30abdd0c98..0000000000 --- a/scene/resources/default_theme/vscroll_bg_focus.png +++ /dev/null diff --git a/scene/resources/default_theme/vscroll_grabber.png b/scene/resources/default_theme/vscroll_grabber.png Binary files differdeleted file mode 100644 index 81c9c58064..0000000000 --- a/scene/resources/default_theme/vscroll_grabber.png +++ /dev/null diff --git a/scene/resources/default_theme/vscroll_grabber_hl.png b/scene/resources/default_theme/vscroll_grabber_hl.png Binary files differdeleted file mode 100644 index a0cfa37ae1..0000000000 --- a/scene/resources/default_theme/vscroll_grabber_hl.png +++ /dev/null diff --git a/scene/resources/default_theme/vslider_bg.png b/scene/resources/default_theme/vslider_bg.png Binary files differindex d184e87aa4..5472bb366f 100644 --- a/scene/resources/default_theme/vslider_bg.png +++ b/scene/resources/default_theme/vslider_bg.png diff --git a/scene/resources/default_theme/vslider_grabber.png b/scene/resources/default_theme/vslider_grabber.png Binary files differindex dfb9578d5e..988c25d9dd 100644 --- a/scene/resources/default_theme/vslider_grabber.png +++ b/scene/resources/default_theme/vslider_grabber.png diff --git a/scene/resources/default_theme/vslider_grabber_hl.png b/scene/resources/default_theme/vslider_grabber_hl.png Binary files differindex 2c8e414b6f..f319df3319 100644 --- a/scene/resources/default_theme/vslider_grabber_hl.png +++ b/scene/resources/default_theme/vslider_grabber_hl.png diff --git a/scene/resources/default_theme/vslider_tick.png b/scene/resources/default_theme/vslider_tick.png Binary files differindex 17980a858c..76c5870dbc 100644 --- a/scene/resources/default_theme/vslider_tick.png +++ b/scene/resources/default_theme/vslider_tick.png diff --git a/scene/resources/default_theme/vsplit_bg.png b/scene/resources/default_theme/vsplit_bg.png Binary files differindex 353ff8960c..f4e1715447 100644 --- a/scene/resources/default_theme/vsplit_bg.png +++ b/scene/resources/default_theme/vsplit_bg.png diff --git a/scene/resources/default_theme/vsplitter.png b/scene/resources/default_theme/vsplitter.png Binary files differindex 255995fdb4..4a9904a3ec 100644 --- a/scene/resources/default_theme/vsplitter.png +++ b/scene/resources/default_theme/vsplitter.png diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index df18e4f0f5..1e3b9772ee 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -108,13 +108,14 @@ void Environment::_bind_methods() { ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"fxaa/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_FXAA); - ADD_PROPERTY( PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Keep,Default Color,Color,Texture,Cubemap,Texture RGBE,Cubemap RGBE"),_SCS("set_background"),_SCS("get_background")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"background/mode",PROPERTY_HINT_ENUM,"Keep,Default Color,Color,Texture,Cubemap,Canvas"),_SCS("set_background"),_SCS("get_background")); ADD_PROPERTYI( PropertyInfo(Variant::COLOR,"background/color"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_COLOR); ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_TEXTURE); - ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/cubemap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CUBEMAP); + ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/cubemap",PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CUBEMAP); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/energy",PROPERTY_HINT_RANGE,"0,128,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_ENERGY); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/scale",PROPERTY_HINT_RANGE,"0.001,16,0.001"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_SCALE); ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/glow",PROPERTY_HINT_RANGE,"0.00,8,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_GLOW); + ADD_PROPERTYI( PropertyInfo(Variant::INT,"background/canvas_max_layer"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CANVAS_MAX_LAYER); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"glow/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GLOW); ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_passes",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_PASSES); @@ -182,10 +183,10 @@ void Environment::_bind_methods() { BIND_CONSTANT( BG_COLOR ); BIND_CONSTANT( BG_TEXTURE ); BIND_CONSTANT( BG_CUBEMAP ); - BIND_CONSTANT( BG_TEXTURE_RGBE ); - BIND_CONSTANT( BG_CUBEMAP_RGBE ); + BIND_CONSTANT( BG_CANVAS ); BIND_CONSTANT( BG_MAX ); + BIND_CONSTANT( BG_PARAM_CANVAS_MAX_LAYER ); BIND_CONSTANT( BG_PARAM_COLOR ); BIND_CONSTANT( BG_PARAM_TEXTURE ); BIND_CONSTANT( BG_PARAM_CUBEMAP ); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index a9e2f422b9..d672a898d5 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -44,14 +44,14 @@ public: BG_COLOR=VS::ENV_BG_COLOR, BG_TEXTURE=VS::ENV_BG_TEXTURE, BG_CUBEMAP=VS::ENV_BG_CUBEMAP, - BG_TEXTURE_RGBE=VS::ENV_BG_TEXTURE_RGBE, - BG_CUBEMAP_RGBE=VS::ENV_BG_CUBEMAP_RGBE, + BG_CANVAS=VS::ENV_BG_CANVAS, BG_MAX=VS::ENV_BG_MAX }; enum BGParam { - BG_PARAM_COLOR=VS::ENV_BG_PARAM_COLOR, + BG_PARAM_CANVAS_MAX_LAYER=VS::ENV_BG_PARAM_CANVAS_MAX_LAYER, + BG_PARAM_COLOR=VS::ENV_BG_PARAM_COLOR, BG_PARAM_TEXTURE=VS::ENV_BG_PARAM_TEXTURE, BG_PARAM_CUBEMAP=VS::ENV_BG_PARAM_CUBEMAP, BG_PARAM_ENERGY=VS::ENV_BG_PARAM_ENERGY, diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 49ee3ee017..79316f0019 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -398,6 +398,17 @@ int Font::get_kerning_pair(CharType p_A,CharType p_B) const { return 0; } +void Font::set_distance_field_hint(bool p_distance_field) { + + distance_field_hint=p_distance_field; + emit_changed(); +} + +bool Font::is_distance_field_hint() const{ + + return distance_field_hint; +} + void Font::clear() { @@ -406,6 +417,7 @@ void Font::clear() { char_map.clear(); textures.clear(); kerning_map.clear(); + distance_field_hint=false; } Size2 Font::get_string_size(const String& p_string) const { @@ -511,9 +523,16 @@ void Font::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_texture","texture:Texture"),&Font::add_texture); ObjectTypeDB::bind_method(_MD("add_char","character","texture","rect","align","advance"),&Font::add_char,DEFVAL(Point2()),DEFVAL(-1)); + + ObjectTypeDB::bind_method(_MD("get_texture_count"),&Font::get_texture_count); + ObjectTypeDB::bind_method(_MD("get_texture:Texture","idx"),&Font::get_texture); + ObjectTypeDB::bind_method(_MD("get_char_size","char","next"),&Font::get_char_size,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("get_string_size","string"),&Font::get_string_size); + ObjectTypeDB::bind_method(_MD("set_distance_field_hint","enable"),&Font::set_distance_field_hint); + ObjectTypeDB::bind_method(_MD("is_distance_field_hint"),&Font::is_distance_field_hint); + ObjectTypeDB::bind_method(_MD("clear"),&Font::clear); ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","string","modulate","clip_w"),&Font::draw,DEFVAL(Color(1,1,1)),DEFVAL(-1)); @@ -535,12 +554,14 @@ void Font::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,1" ), _SCS("set_height"), _SCS("get_height") ); ADD_PROPERTY( PropertyInfo( Variant::REAL, "ascent", PROPERTY_HINT_RANGE,"-1024,1024,1" ), _SCS("set_ascent"), _SCS("get_ascent") ); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "distance_field" ), _SCS("set_distance_field_hint"), _SCS("is_distance_field_hint") ); } Font::Font() { clear(); + } diff --git a/scene/resources/font.h b/scene/resources/font.h index a64ec1ef7a..498bc6863a 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -75,6 +75,7 @@ private: float height; float ascent; + bool distance_field_hint; void _set_chars(const DVector<int>& p_chars); DVector<int> _get_chars() const; @@ -116,6 +117,9 @@ public: Size2 get_string_size(const String& p_string) const; void clear(); + + void set_distance_field_hint(bool p_distance_field); + bool is_distance_field_hint() const; void draw(RID p_canvas_item, const Point2& p_pos, const String& p_text,const Color& p_modulate=Color(1,1,1),int p_clip_w=-1) const; void draw_halign(RID p_canvas_item, const Point2& p_pos, HAlign p_align,float p_width,const String& p_text,const Color& p_modulate=Color(1,1,1)) const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 351d65654d..633dd72ce3 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -458,6 +458,8 @@ FixedMaterial::~FixedMaterial() { } + + bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) { if (p_name==SceneStringNames::get_singleton()->shader_shader) { @@ -465,10 +467,20 @@ bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) { return true; } else { - String n = p_name; - if (n.begins_with("param/")) { - VisualServer::get_singleton()->material_set_param(material,String(n.ptr()+6),p_value); - return true; + if (shader.is_valid()) { + + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/")==0) { //backwards compatibility + pr = n.substr(6,n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->material_set_param(material,pr,p_value); + return true; + } } } @@ -484,10 +496,13 @@ bool ShaderMaterial::_get(const StringName& p_name,Variant &r_ret) const { return true; } else { - String n = p_name; - if (n.begins_with("param/")) { - r_ret=VisualServer::get_singleton()->material_get_param(material,String(n.ptr()+6)); - return true; + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret=VisualServer::get_singleton()->material_get_param(material,pr); + return true; + } } } @@ -499,7 +514,7 @@ bool ShaderMaterial::_get(const StringName& p_name,Variant &r_ret) const { void ShaderMaterial::_get_property_list( List<PropertyInfo> *p_list) const { - p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"Shader" ) ); + p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"MaterialShader,MaterialShaderGraph" ) ); if (!shader.is_null()) { @@ -550,128 +565,34 @@ void ShaderMaterial::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"), &ShaderMaterial::set_shader ); ObjectTypeDB::bind_method(_MD("get_shader:Shader"), &ShaderMaterial::get_shader ); - ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed ); -} - - - - -ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){ - - -} - - -///////////////////////////////// - -void ParticleSystemMaterial::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_texture","texture"),&ParticleSystemMaterial::set_texture); - ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&ParticleSystemMaterial::get_texture); - - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture" ), _SCS("set_texture"), _SCS("get_texture")); - -} - -void ParticleSystemMaterial::set_texture(const Ref<Texture>& p_texture) { - texture=p_texture; - RID rid; - if (texture.is_valid()) - rid=texture->get_rid(); - - VS::get_singleton()->fixed_material_set_texture(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,rid); -} - -Ref<Texture> ParticleSystemMaterial::get_texture() const { - - return texture; -} - - -ParticleSystemMaterial::ParticleSystemMaterial() :Material(VisualServer::get_singleton()->fixed_material_create()){ - - set_flag(FLAG_DOUBLE_SIDED,true); - set_flag(FLAG_UNSHADED,true); - set_depth_draw_mode(DEPTH_DRAW_NEVER); - VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,true); - VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); - set_flag(FLAG_COLOR_ARRAY_SRGB,true); - -} - -ParticleSystemMaterial::~ParticleSystemMaterial() { - - -} - -////////////////////////////// - - - -void UnshadedMaterial::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_texture","texture"),&UnshadedMaterial::set_texture); - ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&UnshadedMaterial::get_texture); - - ObjectTypeDB::bind_method(_MD("set_use_alpha","enable"),&UnshadedMaterial::set_use_alpha); - ObjectTypeDB::bind_method(_MD("is_using_alpha"),&UnshadedMaterial::is_using_alpha); - - ObjectTypeDB::bind_method(_MD("set_use_color_array","enable"),&UnshadedMaterial::set_use_color_array); - ObjectTypeDB::bind_method(_MD("is_using_color_array"),&UnshadedMaterial::is_using_color_array); - - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture" ), _SCS("set_texture"), _SCS("get_texture")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "alpha" ), _SCS("set_use_alpha"), _SCS("is_using_alpha")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "color_array" ), _SCS("set_use_color_array"), _SCS("is_using_color_array")); - -} - -void UnshadedMaterial::set_texture(const Ref<Texture>& p_texture) { - RID rid; - if (texture.is_valid()) - rid=texture->get_rid(); - - VS::get_singleton()->fixed_material_set_texture(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,rid); -} -Ref<Texture> UnshadedMaterial::get_texture() const { - - return texture; -} -void UnshadedMaterial::set_use_alpha(bool p_use_alpha) { + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value:var"), &ShaderMaterial::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param:var","param"), &ShaderMaterial::get_shader_param); - alpha=p_use_alpha; - VS::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,p_use_alpha); - //set_depth_draw_mode(); - //set_hint(HINT,p_use_alpha); - -} - -bool UnshadedMaterial::is_using_alpha() const{ - - return alpha; + ObjectTypeDB::bind_method(_MD("_shader_changed"), &ShaderMaterial::_shader_changed ); } -void UnshadedMaterial::set_use_color_array(bool p_use_color_array){ - color_array=p_use_color_array; - VS::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,p_use_color_array); +void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { -} + String f = p_function.operator String(); + if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) { -bool UnshadedMaterial::is_using_color_array() const{ - - return color_array; + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\""); + } + } + } + Material::get_argument_options(p_function,p_idx,r_options); } -UnshadedMaterial::UnshadedMaterial() :Material(VisualServer::get_singleton()->fixed_material_create()){ +ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){ - set_flag(FLAG_UNSHADED,true); - set_use_alpha(true); - set_flag(FLAG_COLOR_ARRAY_SRGB,true); } -UnshadedMaterial::~UnshadedMaterial() { - -} +///////////////////////////////// diff --git a/scene/resources/material.h b/scene/resources/material.h index 9c3feede08..73d1a4e188 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -243,6 +243,7 @@ public: void set_shader_param(const StringName& p_param,const Variant& p_value); Variant get_shader_param(const StringName& p_param) const; + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; ShaderMaterial(); }; @@ -252,68 +253,6 @@ public: -class ParticleSystemMaterial : public Material { - - OBJ_TYPE( ParticleSystemMaterial, Material ); - REVERSE_GET_PROPERTY_LIST - -private: - - - - Ref<Texture> texture; - -protected: - - - static void _bind_methods(); - -public: - - void set_texture(const Ref<Texture>& p_texture); - Ref<Texture> get_texture() const; - - - ParticleSystemMaterial(); - ~ParticleSystemMaterial(); - -}; - -/////////////////////////////////////////// - - -class UnshadedMaterial : public Material { - - OBJ_TYPE( UnshadedMaterial, Material ); - REVERSE_GET_PROPERTY_LIST - -private: - - - bool alpha; - bool color_array; - Ref<Texture> texture; - -protected: - - - static void _bind_methods(); - -public: - - void set_texture(const Ref<Texture>& p_texture); - Ref<Texture> get_texture() const; - - void set_use_alpha(bool p_use_alpha); - bool is_using_alpha() const; - - void set_use_color_array(bool p_use_color_array); - bool is_using_color_array() const; - - UnshadedMaterial(); - ~UnshadedMaterial(); - -}; #endif diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 3aeccdc551..f4bb3088c3 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -743,6 +743,225 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } +Ref<Mesh> Mesh::create_outline(float p_margin) const { + + + Array arrays; + int index_accum=0; + for(int i=0;i<get_surface_count();i++) { + + if (surface_get_primitive_type(i)!=PRIMITIVE_TRIANGLES) + continue; + + Array a = surface_get_arrays(i); + int vcount=0; + + if (i==0) { + arrays=a; + DVector<Vector3> v=a[ARRAY_VERTEX]; + index_accum+=v.size(); + } else { + + for(int j=0;j<arrays.size();j++) { + + if (arrays[j].get_type()==Variant::NIL || a[j].get_type()==Variant::NIL) { + //mismatch, do not use + arrays[j]=Variant(); + continue; + } + + switch(j) { + + case ARRAY_VERTEX: + case ARRAY_NORMAL: { + + DVector<Vector3> dst = arrays[j]; + DVector<Vector3> src = a[j]; + if (j==ARRAY_VERTEX) + vcount=src.size(); + if (dst.size()==0 || src.size()==0) { + arrays[j]=Variant(); + continue; + } + dst.append_array(src); + arrays[j]=dst; + } break; + case ARRAY_TANGENT: + case ARRAY_BONES: + case ARRAY_WEIGHTS: { + + DVector<real_t> dst = arrays[j]; + DVector<real_t> src = a[j]; + if (dst.size()==0 || src.size()==0) { + arrays[j]=Variant(); + continue; + } + dst.append_array(src); + arrays[j]=dst; + + } break; + case ARRAY_COLOR: { + DVector<Color> dst = arrays[j]; + DVector<Color> src = a[j]; + if (dst.size()==0 || src.size()==0) { + arrays[j]=Variant(); + continue; + } + dst.append_array(src); + arrays[j]=dst; + + } break; + case ARRAY_TEX_UV: + case ARRAY_TEX_UV2: { + DVector<Vector2> dst = arrays[j]; + DVector<Vector2> src = a[j]; + if (dst.size()==0 || src.size()==0) { + arrays[j]=Variant(); + continue; + } + dst.append_array(src); + arrays[j]=dst; + + } break; + case ARRAY_INDEX: { + DVector<int> dst = arrays[j]; + DVector<int> src = a[j]; + if (dst.size()==0 || src.size()==0) { + arrays[j]=Variant(); + continue; + } + { + int ss = src.size(); + DVector<int>::Write w = src.write(); + for(int k=0;k<ss;k++) { + w[k]+=index_accum; + } + + } + dst.append_array(src); + arrays[j]=dst; + index_accum+=vcount; + + } break; + + } + } + } + } + + { + int tc=0; + DVector<int>::Write ir; + DVector<int> indices =arrays[ARRAY_INDEX]; + bool has_indices=false; + DVector<Vector3> vertices =arrays[ARRAY_VERTEX]; + int vc = vertices.size(); + ERR_FAIL_COND_V(!vc,Ref<Mesh>()); + DVector<Vector3>::Write r=vertices.write(); + + + if (indices.size()) { + vc=indices.size(); + ir=indices.write(); + has_indices=true; + } + + Map<Vector3,Vector3> normal_accum; + + //fill normals with triangle normals + for(int i=0;i<vc;i+=3) { + + + Vector3 t[3]; + + if (has_indices) { + t[0]=r[ir[i+0]]; + t[1]=r[ir[i+1]]; + t[2]=r[ir[i+2]]; + } else { + t[0]=r[i+0]; + t[1]=r[i+1]; + t[2]=r[i+2]; + } + + Vector3 n = Plane(t[0],t[1],t[2]).normal; + + for(int j=0;j<3;j++) { + + Map<Vector3,Vector3>::Element *E=normal_accum.find(t[j]); + if (!E) { + normal_accum[t[j]]=n; + } else { + float d = n.dot(E->get()); + if (d<1.0) + E->get()+=n*(1.0-d); + //E->get()+=n; + } + } + } + + //normalize + + for (Map<Vector3,Vector3>::Element *E=normal_accum.front();E;E=E->next()) { + E->get().normalize(); + } + + + //displace normals + int vc2 = vertices.size(); + + for(int i=0;i<vc2;i++) { + + + Vector3 t=r[i]; + + Map<Vector3,Vector3>::Element *E=normal_accum.find(t); + ERR_CONTINUE(!E); + + t+=E->get()*p_margin; + r[i]=t; + } + + r = DVector<Vector3>::Write(); + arrays[ARRAY_VERTEX]=vertices; + + if (!has_indices) { + + DVector<int> new_indices; + new_indices.resize(vertices.size()); + DVector<int>::Write iw = new_indices.write(); + + for(int j=0;j<vc2;j+=3) { + + iw[j]=j; + iw[j+1]=j+2; + iw[j+2]=j+1; + } + + iw=DVector<int>::Write(); + arrays[ARRAY_INDEX]=new_indices; + + } else { + + for(int j=0;j<vc;j+=3) { + + SWAP(ir[j+1],ir[j+2]); + } + ir=DVector<int>::Write(); + arrays[ARRAY_INDEX]=indices; + + } + } + + + + + Ref<Mesh> newmesh = memnew( Mesh ); + newmesh->add_surface(PRIMITIVE_TRIANGLES,arrays); + return newmesh; +} + + void Mesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_morph_target","name"),&Mesh::add_morph_target); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index d6ab6a1198..5aacc8be57 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -166,6 +166,8 @@ public: Ref<Shape> create_trimesh_shape() const; Ref<Shape> create_convex_shape() const; + Ref<Mesh> create_outline(float p_margin) const; + void center_geometry(); void regen_normalmaps(); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 75a1b765ee..5883686f20 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -272,6 +272,10 @@ Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map< continue; }*/ + if (E->get().usage & PROPERTY_USAGE_NO_INSTANCE_STATE) { + continue; + } + if (instance_state[name]==value) { continue; } diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index afb0ae1815..e8cdec66df 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -142,6 +142,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector if (d<closest_dist) { ignore_from_edge=E->get(); closest_dist=d; + closest_point=closest; } } @@ -168,6 +169,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector if (d<closest_dist) { ignore_to_edge=E->get(); closest_dist=d; + closest_point=closest; } } @@ -523,24 +525,32 @@ bool PolygonPathFinder::is_point_inside(const Vector2& p_point) const { Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const { - int closest_idx=-1; float closest_dist=1e20; - for(int i=0;i<points.size()-2;i++) { + Vector2 closest_point; + + for (Set<Edge>::Element *E=edges.front();E;E=E->next()) { + + const Edge& e=E->get(); + Vector2 seg[2]={ + points[e.points[0]].pos, + points[e.points[1]].pos + }; + + + Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point,seg); + float d = p_point.distance_squared_to(closest); - float d = p_point.distance_squared_to(points[i].pos); if (d<closest_dist) { - d=closest_dist; - closest_idx=i; + closest_dist=d; + closest_point=closest; } - } + + ERR_FAIL_COND_V(closest_dist==1e20,Vector2()); - ERR_FAIL_COND_V(closest_idx==-1,Vector2()); - - return points[closest_idx].pos; + return closest_point; } - Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2& p_from, const Vector2& p_to) const { Vector<Vector2> inters; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 6d65da3782..42251124bd 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -33,12 +33,6 @@ #include "scene/scene_string_names.h" -void Shader::set_mode(Mode p_mode) { - - ERR_FAIL_INDEX(p_mode,2); - VisualServer::get_singleton()->shader_set_mode(shader,VisualServer::ShaderMode(p_mode)); - emit_signal(SceneStringNames::get_singleton()->changed); -} Shader::Mode Shader::get_mode() const { @@ -90,7 +84,7 @@ void Shader::get_param_list(List<PropertyInfo> *p_params) const { for(List<PropertyInfo>::Element *E=local.front();E;E=E->next()) { PropertyInfo pi=E->get(); - pi.name="param/"+pi.name; + pi.name="shader_param/"+pi.name; params_cache[pi.name]=E->get().name; if (p_params) { @@ -120,6 +114,13 @@ Dictionary Shader::_get_code() { c["vertex_ofs"]=0; c["light"]=ls; c["light_ofs"]=0; + Array arr; + for(const Map<StringName,Ref<Texture> >::Element *E=default_textures.front();E;E=E->next()) { + arr.push_back(E->key()); + arr.push_back(E->get()); + } + if (arr.size()) + c["default_tex"]=arr; return c; } @@ -132,11 +133,46 @@ void Shader::_set_code(const Dictionary& p_string) { light=p_string["light"]; set_code(p_string["vertex"],p_string["fragment"],light); + if (p_string.has("default_tex")) { + Array arr=p_string["default_tex"]; + if ((arr.size()&1)==0) { + for(int i=0;i<arr.size();i+=2) + set_default_texture_param(arr[i],arr[i+1]); + } + } } +void Shader::set_default_texture_param(const StringName& p_param,const Ref<Texture>& p_texture) { + + if (p_texture.is_valid()) { + default_textures[p_param]=p_texture; + VS::get_singleton()->shader_set_default_texture_param(shader,p_param,p_texture->get_rid()); + } else { + default_textures.erase(p_param); + VS::get_singleton()->shader_set_default_texture_param(shader,p_param,RID()); + } +} + +Ref<Texture> Shader::get_default_texture_param(const StringName& p_param) const{ + + if (default_textures.has(p_param)) + return default_textures[p_param]; + else + return Ref<Texture>(); +} + +void Shader::get_default_texture_param_list(List<StringName>* r_textures) const{ + + for(const Map<StringName,Ref<Texture> >::Element *E=default_textures.front();E;E=E->next()) { + + r_textures->push_back(E->key()); + } + +} + + void Shader::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Shader::set_mode); ObjectTypeDB::bind_method(_MD("get_mode"),&Shader::get_mode); ObjectTypeDB::bind_method(_MD("set_code","vcode","fcode","lcode","fofs","lofs"),&Shader::set_code,DEFVAL(0),DEFVAL(0)); @@ -144,6 +180,9 @@ void Shader::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_fragment_code"),&Shader::get_fragment_code); ObjectTypeDB::bind_method(_MD("get_light_code"),&Shader::get_light_code); + ObjectTypeDB::bind_method(_MD("set_default_texture_param","param","texture:Texture"),&Shader::set_default_texture_param); + ObjectTypeDB::bind_method(_MD("get_default_texture_param:Texture","param"),&Shader::get_default_texture_param); + ObjectTypeDB::bind_method(_MD("has_param","name"),&Shader::has_param); ObjectTypeDB::bind_method(_MD("_set_code","code"),&Shader::_set_code); @@ -160,9 +199,9 @@ void Shader::_bind_methods() { } -Shader::Shader() { +Shader::Shader(Mode p_mode) { - shader = VisualServer::get_singleton()->shader_create(); + shader = VisualServer::get_singleton()->shader_create(VS::ShaderMode(p_mode)); params_cache_dirty=true; } @@ -194,7 +233,7 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin String base_path = p_path.get_base_dir(); - Ref<Shader> shader( memnew( Shader ) ); + Ref<Shader> shader;//( memnew( Shader ) ); int line=0; diff --git a/scene/resources/shader.h b/scene/resources/shader.h index fff6f1d28a..4a380d455b 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -31,7 +31,7 @@ #include "resource.h" #include "io/resource_loader.h" - +#include "scene/resources/texture.h" class Shader : public Resource { OBJ_TYPE(Shader,Resource); @@ -48,6 +48,9 @@ class Shader : public Resource { // convertion fast and save memory. mutable bool params_cache_dirty; mutable Map<StringName,StringName> params_cache; //map a shader param to a material param.. + Map<StringName,Ref<Texture> > default_textures; + + protected: @@ -58,10 +61,11 @@ public: MODE_MATERIAL, MODE_CANVAS_ITEM, - MODE_POST_PROCESS + MODE_POST_PROCESS, + MODE_MAX }; - void set_mode(Mode p_mode); + //void set_mode(Mode p_mode); Mode get_mode() const; void set_code( const String& p_vertex, const String& p_fragment, const String& p_light,int p_fragment_ofs=0,int p_light_ofs=0); @@ -72,15 +76,47 @@ public: void get_param_list(List<PropertyInfo> *p_params) const; bool has_param(const StringName& p_param) const; + void set_default_texture_param(const StringName& p_param, const Ref<Texture> &p_texture); + Ref<Texture> get_default_texture_param(const StringName& p_param) const; + void get_default_texture_param_list(List<StringName>* r_textures) const; + + _FORCE_INLINE_ StringName remap_param(const StringName& p_param) const { + if (params_cache_dirty) + get_param_list(NULL); + + const Map<StringName,StringName>::Element *E=params_cache.find(p_param); + if (E) + return E->get(); + return StringName(); + } + virtual RID get_rid() const; - Shader(); + Shader(Mode p_mode); ~Shader(); }; VARIANT_ENUM_CAST( Shader::Mode ); +class MaterialShader : public Shader { + + OBJ_TYPE(MaterialShader,Shader); + +public: + + MaterialShader() : Shader(MODE_MATERIAL) {}; +}; + +class CanvasItemShader : public Shader { + + OBJ_TYPE(CanvasItemShader,Shader); + +public: + + CanvasItemShader() : Shader(MODE_CANVAS_ITEM) {}; +}; + class ResourceFormatLoaderShader : public ResourceFormatLoader { diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index df5fee81a8..be54d649e2 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -27,129 +27,361 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "shader_graph.h" +#include "scene/scene_string_names.h" +Array ShaderGraph::_get_node_list(ShaderType p_type) const { + List<int> nodes; + get_node_list(p_type,&nodes); + Array arr(true); + for (List<int>::Element *E=nodes.front();E;E=E->next()) + arr.push_back(E->get()); + return arr; +} +Array ShaderGraph::_get_connections(ShaderType p_type) const { -# if 0 -void ShaderGraph::_set(const String& p_name, const Variant& p_value) { + List<Connection> connections; + get_node_connections(p_type,&connections); + Array arr(true); + for (List<Connection>::Element *E=connections.front();E;E=E->next()) { - if (p_name.begins_with("nodes/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data=p_value; + Dictionary d(true); + d["src_id"]=E->get().src_id; + d["src_slot"]=E->get().src_slot; + d["dst_id"]=E->get().dst_id; + d["dst_slot"]=E->get().dst_slot; + arr.push_back(d); - ERR_FAIL_COND(!data.has("type")); - String type=data["type"]; + } + return arr; +} - VS::NodeType node_type=VS::NODE_TYPE_MAX; - for(int i=0;i<NODE_TYPE_MAX;i++) { +void ShaderGraph::_set_data(const Dictionary &p_data) { - if (type==VisualServer::shader_node_get_type_info((VS::NodeType)i).name) - node_type=(VS::NodeType)i; - } + Dictionary d=p_data; + ERR_FAIL_COND(!d.has("shaders")); + Array sh=d["shaders"]; + ERR_FAIL_COND(sh.size()!=3); - ERR_FAIL_COND(node_type==VS::NODE_TYPE_MAX); + for(int t=0;t<3;t++) { + Array data=sh[t]; + ERR_FAIL_COND((data.size()%6)!=0); + shader[t].node_map.clear(); + for(int i=0;i<data.size();i+=6) { - node_add( (NodeType)node_type, idx ); - if (data.has("param")) - node_set_param(idx,data["param"]); - if (data.has("pos")) - node_set_pos(idx,data["pos"]); - } + Node n; + n.id=data[i+0]; + n.type=NodeType(int(data[i+1])); + n.pos=data[i+2]; + n.param1=data[i+3]; + n.param2=data[i+4]; + + Array conns=data[i+5]; + ERR_FAIL_COND((conns.size()%3)!=0); + + for(int j=0;j<conns.size();j+=3) { - if (p_name.begins_with("conns/")) { - Dictionary data=p_value; - ERR_FAIL_COND( !data.has("src_id") ); - ERR_FAIL_COND( !data.has("src_slot") ); - ERR_FAIL_COND( !data.has("dst_id") ); - ERR_FAIL_COND( !data.has("dst_slot") ); + SourceSlot ss; + int ls=conns[j+0]; + ss.id=conns[j+1]; + ss.slot=conns[j+2]; + n.connections[ls]=ss; + } + shader[t].node_map[n.id]=n; - connect(data["src_id"],data["src_slot"],data["dst_id"],data["dst_slot"]); + } } - return false; + _update_shader(); + } -Variant ShaderGraph::_get(const String& p_name) const { - if (p_name.begins_with("nodes/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data; - data["type"]=VisualServer::shader_node_get_type_info((VS::NodeType)node_get_type(idx)).name; - data["pos"]=node_get_pos(idx); - data["param"]=node_get_param(idx); - return data; - } - if (p_name.begins_with("conns/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data; - - List<Connection> connections; - get_connections(&connections); - ERR_FAIL_INDEX_V( idx,connections.size(), Variant() ); - Connection c = connections[idx]; - - data["src_id"]=c.src_id; - data["src_slot"]=c.src_slot; - data["dst_id"]=c.dst_id; - data["dst_slot"]=c.dst_slot; - return data; +Dictionary ShaderGraph::_get_data() const { + + Array sh; + for(int i=0;i<3;i++) { + Array data; + int ec = shader[i].node_map.size(); + data.resize(ec*6); + int idx=0; + for (Map<int,Node>::Element*E=shader[i].node_map.front();E;E=E->next()) { + + data[idx+0]=E->key(); + data[idx+1]=E->get().type; + data[idx+2]=E->get().pos; + data[idx+3]=E->get().param1; + data[idx+4]=E->get().param2; + + Array conns; + conns.resize(E->get().connections.size()*3); + int idx2=0; + for(Map<int,SourceSlot>::Element*F=E->get().connections.front();F;F=F->next()) { + + conns[idx2+0]=F->key(); + conns[idx2+1]=F->get().id; + conns[idx2+2]=F->get().slot; + idx2+=3; + } + data[idx+5]=conns; + idx+=6; + } + sh.push_back(data); } - return Variant(); + Dictionary data; + data["shaders"]=sh; + return data; } -void ShaderGraph::_get_property_list( List<PropertyInfo> *p_list) const { - List<int> nodes; - get_node_list(&nodes); - for(List<int>::Element *E=nodes.front();E;E=E->next()) { - int idx=E->get(); - p_list->push_back(PropertyInfo( Variant::DICTIONARY , "nodes/"+itos(idx),PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_STORAGE ) ); - } - - List<Connection> connections; - get_connections(&connections); - int idx=0; - for(List<Connection>::Element *E=connections.front();E;E=E->next()) { - p_list->push_back(PropertyInfo( Variant::DICTIONARY , "conns/"+itos(idx++),PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_STORAGE ) ); - } +ShaderGraph::GraphError ShaderGraph::get_graph_error(ShaderType p_type) const { + ERR_FAIL_INDEX_V(p_type,3,GRAPH_OK); + return shader[p_type].error; } -#endif -#if 0 -Array ShaderGraph::_get_connections_helper() const { +void ShaderGraph::_bind_methods() { - Array connections_ret; - List<Connection> connections; - get_connections(&connections); - connections_ret.resize(connections.size()); - - int idx=0; - for(List<Connection>::Element *E=connections.front();E;E=E->next()) { - - Connection c = E->get(); - Dictionary data; - data["src_id"]=c.src_id; - data["src_slot"]=c.src_slot; - data["dst_id"]=c.dst_id; - data["dst_slot"]=c.dst_slot; - connections_ret.set(idx++,data); - } + ObjectTypeDB::bind_method(_MD("_update_shader"),&ShaderGraph::_update_shader); - return connections_ret; -} + ObjectTypeDB::bind_method(_MD("node_add","shader_type","node_type","id"),&ShaderGraph::node_add); + ObjectTypeDB::bind_method(_MD("node_remove","shader_type","id"),&ShaderGraph::node_remove); + ObjectTypeDB::bind_method(_MD("node_set_pos","shader_type","id","pos"),&ShaderGraph::node_set_pos); + ObjectTypeDB::bind_method(_MD("node_get_pos","shader_type","id"),&ShaderGraph::node_get_pos); -void ShaderGraph::_bind_methods() { + ObjectTypeDB::bind_method(_MD("node_get_type","shader_type","id"),&ShaderGraph::node_get_type); + + ObjectTypeDB::bind_method(_MD("get_node_list","shader_type"),&ShaderGraph::_get_node_list); + + ObjectTypeDB::bind_method(_MD("scalar_const_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_const_node_set_value); + ObjectTypeDB::bind_method(_MD("scalar_const_node_get_value","shader_type","id"),&ShaderGraph::scalar_const_node_set_value); + + ObjectTypeDB::bind_method(_MD("vec_const_node_set_value","shader_type","id","value"),&ShaderGraph::vec_const_node_set_value); + ObjectTypeDB::bind_method(_MD("vec_const_node_get_value","shader_type","id"),&ShaderGraph::vec_const_node_set_value); + + ObjectTypeDB::bind_method(_MD("rgb_const_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_const_node_set_value); + ObjectTypeDB::bind_method(_MD("rgb_const_node_get_value","shader_type","id"),&ShaderGraph::rgb_const_node_set_value); + + ObjectTypeDB::bind_method(_MD("xform_const_node_set_value","shader_type","id","value"),&ShaderGraph::xform_const_node_set_value); + ObjectTypeDB::bind_method(_MD("xform_const_node_get_value","shader_type","id"),&ShaderGraph::xform_const_node_set_value); + + +// void get_node_list(ShaderType p_which,List<int> *p_node_list) const; + + ObjectTypeDB::bind_method(_MD("texture_node_set_filter_size","shader_type","id","filter_size"),&ShaderGraph::texture_node_set_filter_size); + ObjectTypeDB::bind_method(_MD("texture_node_get_filter_size","shader_type","id"),&ShaderGraph::texture_node_set_filter_size); + + ObjectTypeDB::bind_method(_MD("texture_node_set_filter_strength","shader_type","id","filter_strength"),&ShaderGraph::texture_node_set_filter_strength); + ObjectTypeDB::bind_method(_MD("texture_node_get_filter_strength","shader_type","id"),&ShaderGraph::texture_node_set_filter_strength); + + ObjectTypeDB::bind_method(_MD("scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::scalar_op_node_set_op); + ObjectTypeDB::bind_method(_MD("scalar_op_node_get_op","shader_type","id"),&ShaderGraph::scalar_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("vec_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_op_node_set_op); + ObjectTypeDB::bind_method(_MD("vec_op_node_get_op","shader_type","id"),&ShaderGraph::vec_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("vec_scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_scalar_op_node_set_op); + ObjectTypeDB::bind_method(_MD("vec_scalar_op_node_get_op","shader_type","id"),&ShaderGraph::vec_scalar_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("rgb_op_node_set_op","shader_type","id","op"),&ShaderGraph::rgb_op_node_set_op); + ObjectTypeDB::bind_method(_MD("rgb_op_node_get_op","shader_type","id"),&ShaderGraph::rgb_op_node_get_op); + + + ObjectTypeDB::bind_method(_MD("xform_vec_mult_node_set_no_translation","shader_type","id","disable"),&ShaderGraph::xform_vec_mult_node_set_no_translation); + ObjectTypeDB::bind_method(_MD("xform_vec_mult_node_get_no_translation","shader_type","id"),&ShaderGraph::xform_vec_mult_node_get_no_translation); + + ObjectTypeDB::bind_method(_MD("scalar_func_node_set_function","shader_type","id","func"),&ShaderGraph::scalar_func_node_set_function); + ObjectTypeDB::bind_method(_MD("scalar_func_node_get_function","shader_type","id"),&ShaderGraph::scalar_func_node_get_function); + + ObjectTypeDB::bind_method(_MD("vec_func_node_set_function","shader_type","id","func"),&ShaderGraph::vec_func_node_set_function); + ObjectTypeDB::bind_method(_MD("vec_func_node_get_function","shader_type","id"),&ShaderGraph::vec_func_node_get_function); + + ObjectTypeDB::bind_method(_MD("input_node_set_name","shader_type","id","name"),&ShaderGraph::input_node_set_name); + ObjectTypeDB::bind_method(_MD("input_node_get_name","shader_type","id"),&ShaderGraph::input_node_get_name); + + ObjectTypeDB::bind_method(_MD("scalar_input_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_input_node_set_value); + ObjectTypeDB::bind_method(_MD("scalar_input_node_get_value","shader_type","id"),&ShaderGraph::scalar_input_node_get_value); + ObjectTypeDB::bind_method(_MD("vec_input_node_set_value","shader_type","id","value"),&ShaderGraph::vec_input_node_set_value); + ObjectTypeDB::bind_method(_MD("vec_input_node_get_value","shader_type","id"),&ShaderGraph::vec_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("rgb_input_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_input_node_set_value); + ObjectTypeDB::bind_method(_MD("rgb_input_node_get_value","shader_type","id"),&ShaderGraph::rgb_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("xform_input_node_set_value","shader_type","id","value"),&ShaderGraph::xform_input_node_set_value); + ObjectTypeDB::bind_method(_MD("xform_input_node_get_value","shader_type","id"),&ShaderGraph::xform_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("texture_input_node_set_value","shader_type","id","value:Texture"),&ShaderGraph::texture_input_node_set_value); + ObjectTypeDB::bind_method(_MD("texture_input_node_get_value:Texture","shader_type","id"),&ShaderGraph::texture_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("cubemap_input_node_set_value","shader_type","id","value:CubeMap"),&ShaderGraph::cubemap_input_node_set_value); + ObjectTypeDB::bind_method(_MD("cubemap_input_node_get_value:CubeMap","shader_type","id"),&ShaderGraph::cubemap_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("comment_node_set_text","shader_type","id","text"),&ShaderGraph::comment_node_set_text); + ObjectTypeDB::bind_method(_MD("comment_node_get_text","shader_type","id"),&ShaderGraph::comment_node_get_text); + + ObjectTypeDB::bind_method(_MD("color_ramp_node_set_ramp","shader_type","id","colors","offsets"),&ShaderGraph::color_ramp_node_set_ramp); + ObjectTypeDB::bind_method(_MD("color_ramp_node_get_colors","shader_type","id"),&ShaderGraph::color_ramp_node_get_colors); + ObjectTypeDB::bind_method(_MD("color_ramp_node_get_offsets","shader_type","id"),&ShaderGraph::color_ramp_node_get_offsets); + + ObjectTypeDB::bind_method(_MD("curve_map_node_set_points","shader_type","id","points"),&ShaderGraph::curve_map_node_set_points); + ObjectTypeDB::bind_method(_MD("curve_map_node_get_points","shader_type","id"),&ShaderGraph::curve_map_node_get_points); + + ObjectTypeDB::bind_method(_MD("connect_node:Error","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node); + ObjectTypeDB::bind_method(_MD("is_node_connected","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::is_node_connected); + ObjectTypeDB::bind_method(_MD("disconnect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::disconnect_node); + ObjectTypeDB::bind_method(_MD("get_node_connections","shader_type"),&ShaderGraph::_get_connections); + + ObjectTypeDB::bind_method(_MD("clear","shader_type"),&ShaderGraph::clear); + + ObjectTypeDB::bind_method(_MD("node_set_state","shader_type","id","state"),&ShaderGraph::node_set_state); + ObjectTypeDB::bind_method(_MD("node_get_state:var","shader_type","id"),&ShaderGraph::node_get_state); + + ObjectTypeDB::bind_method(_MD("_set_data"),&ShaderGraph::_set_data); + ObjectTypeDB::bind_method(_MD("_get_data"),&ShaderGraph::_get_data); + + ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data")); + + //void get_connections(ShaderType p_which,List<Connection> *p_connections) const; + + + BIND_CONSTANT( NODE_INPUT ); // all inputs (shader type dependent) + BIND_CONSTANT( NODE_SCALAR_CONST ); //scalar constant + BIND_CONSTANT( NODE_VEC_CONST ); //vec3 constant + BIND_CONSTANT( NODE_RGB_CONST ); //rgb constant (shows a color picker instead) + BIND_CONSTANT( NODE_XFORM_CONST ); // 4x4 matrix constant + BIND_CONSTANT( NODE_TIME ); // time in seconds + BIND_CONSTANT( NODE_SCREEN_TEX ); // screen texture sampler (takes UV) (only usable in fragment shader) + BIND_CONSTANT( NODE_SCALAR_OP ); // scalar vs scalar op (mul ); add ); div ); etc) + BIND_CONSTANT( NODE_VEC_OP ); // vec3 vs vec3 op (mul );ad );div );crossprod );etc) + BIND_CONSTANT( NODE_VEC_SCALAR_OP ); // vec3 vs scalar op (mul ); add ); div ); etc) + BIND_CONSTANT( NODE_RGB_OP ); // vec3 vs vec3 rgb op (with scalar amount) ); like brighten ); darken ); burn ); dodge ); multiply ); etc. + BIND_CONSTANT( NODE_XFORM_MULT ); // mat4 x mat4 + BIND_CONSTANT( NODE_XFORM_VEC_MULT ); // mat4 x vec3 mult (with no-translation option) + BIND_CONSTANT( NODE_XFORM_VEC_INV_MULT ); // mat4 x vec3 inverse mult (with no-translation option) + BIND_CONSTANT( NODE_SCALAR_FUNC ); // scalar function (sin ); cos ); etc) + BIND_CONSTANT( NODE_VEC_FUNC ); // vector function (normalize ); negate ); reciprocal ); rgb2hsv ); hsv2rgb ); etc ); etc) + BIND_CONSTANT( NODE_VEC_LEN ); // vec3 length + BIND_CONSTANT( NODE_DOT_PROD ); // vec3 . vec3 (dot product -> scalar output) + BIND_CONSTANT( NODE_VEC_TO_SCALAR ); // 1 vec3 input ); 3 scalar outputs + BIND_CONSTANT( NODE_SCALAR_TO_VEC ); // 3 scalar input ); 1 vec3 output + BIND_CONSTANT( NODE_VEC_TO_XFORM ); // 3 vec input ); 1 xform output + BIND_CONSTANT( NODE_XFORM_TO_VEC ); // 3 vec input ); 1 xform output + BIND_CONSTANT( NODE_SCALAR_INTERP ); // scalar interpolation (with optional curve) + BIND_CONSTANT( NODE_VEC_INTERP ); // vec3 interpolation (with optional curve) + BIND_CONSTANT( NODE_COLOR_RAMP ); + BIND_CONSTANT( NODE_CURVE_MAP ); + BIND_CONSTANT( NODE_SCALAR_INPUT ); // scalar uniform (assignable in material) + BIND_CONSTANT( NODE_VEC_INPUT ); // vec3 uniform (assignable in material) + BIND_CONSTANT( NODE_RGB_INPUT ); // color uniform (assignable in material) + BIND_CONSTANT( NODE_XFORM_INPUT ); // mat4 uniform (assignable in material) + BIND_CONSTANT( NODE_TEXTURE_INPUT ); // texture input (assignable in material) + BIND_CONSTANT( NODE_CUBEMAP_INPUT ); // cubemap input (assignable in material) + BIND_CONSTANT( NODE_DEFAULT_TEXTURE ); + BIND_CONSTANT( NODE_OUTPUT ); // output (shader type dependent) + BIND_CONSTANT( NODE_COMMENT ); // comment + BIND_CONSTANT( NODE_TYPE_MAX ); + + BIND_CONSTANT( SLOT_TYPE_SCALAR ); + BIND_CONSTANT( SLOT_TYPE_VEC ); + BIND_CONSTANT( SLOT_TYPE_XFORM ); + BIND_CONSTANT( SLOT_TYPE_TEXTURE ); + BIND_CONSTANT( SLOT_MAX ); + + BIND_CONSTANT( SHADER_TYPE_VERTEX ); + BIND_CONSTANT( SHADER_TYPE_FRAGMENT ); + BIND_CONSTANT( SHADER_TYPE_LIGHT ); + BIND_CONSTANT( SHADER_TYPE_MAX ); + + + BIND_CONSTANT( SLOT_IN ); + BIND_CONSTANT( SLOT_OUT ); + + BIND_CONSTANT( GRAPH_OK ); + BIND_CONSTANT( GRAPH_ERROR_CYCLIC ); + BIND_CONSTANT( GRAPH_ERROR_MISSING_CONNECTIONS ); + + BIND_CONSTANT( SCALAR_OP_ADD ); + BIND_CONSTANT( SCALAR_OP_SUB ); + BIND_CONSTANT( SCALAR_OP_MUL ); + BIND_CONSTANT( SCALAR_OP_DIV ); + BIND_CONSTANT( SCALAR_OP_MOD ); + BIND_CONSTANT( SCALAR_OP_POW ); + BIND_CONSTANT( SCALAR_OP_MAX ); + BIND_CONSTANT( SCALAR_OP_MIN ); + BIND_CONSTANT( SCALAR_OP_ATAN2 ); + BIND_CONSTANT( SCALAR_MAX_OP ); + + BIND_CONSTANT( VEC_OP_ADD ); + BIND_CONSTANT( VEC_OP_SUB ); + BIND_CONSTANT( VEC_OP_MUL ); + BIND_CONSTANT( VEC_OP_DIV ); + BIND_CONSTANT( VEC_OP_MOD ); + BIND_CONSTANT( VEC_OP_POW ); + BIND_CONSTANT( VEC_OP_MAX ); + BIND_CONSTANT( VEC_OP_MIN ); + BIND_CONSTANT( VEC_OP_CROSS ); + BIND_CONSTANT( VEC_MAX_OP ); + + BIND_CONSTANT( VEC_SCALAR_OP_MUL ); + BIND_CONSTANT( VEC_SCALAR_OP_DIV ); + BIND_CONSTANT( VEC_SCALAR_OP_POW ); + BIND_CONSTANT( VEC_SCALAR_MAX_OP ); + + BIND_CONSTANT( RGB_OP_SCREEN ); + BIND_CONSTANT( RGB_OP_DIFFERENCE ); + BIND_CONSTANT( RGB_OP_DARKEN ); + BIND_CONSTANT( RGB_OP_LIGHTEN ); + BIND_CONSTANT( RGB_OP_OVERLAY ); + BIND_CONSTANT( RGB_OP_DODGE ); + BIND_CONSTANT( RGB_OP_BURN ); + BIND_CONSTANT( RGB_OP_SOFT_LIGHT ); + BIND_CONSTANT( RGB_OP_HARD_LIGHT ); + BIND_CONSTANT( RGB_MAX_OP ); + + BIND_CONSTANT( SCALAR_FUNC_SIN ); + BIND_CONSTANT( SCALAR_FUNC_COS ); + BIND_CONSTANT( SCALAR_FUNC_TAN ); + BIND_CONSTANT( SCALAR_FUNC_ASIN ); + BIND_CONSTANT( SCALAR_FUNC_ACOS ); + BIND_CONSTANT( SCALAR_FUNC_ATAN ); + BIND_CONSTANT( SCALAR_FUNC_SINH ); + BIND_CONSTANT( SCALAR_FUNC_COSH ); + BIND_CONSTANT( SCALAR_FUNC_TANH ); + BIND_CONSTANT( SCALAR_FUNC_LOG ); + BIND_CONSTANT( SCALAR_FUNC_EXP ); + BIND_CONSTANT( SCALAR_FUNC_SQRT ); + BIND_CONSTANT( SCALAR_FUNC_ABS ); + BIND_CONSTANT( SCALAR_FUNC_SIGN ); + BIND_CONSTANT( SCALAR_FUNC_FLOOR ); + BIND_CONSTANT( SCALAR_FUNC_ROUND ); + BIND_CONSTANT( SCALAR_FUNC_CEIL ); + BIND_CONSTANT( SCALAR_FUNC_FRAC ); + BIND_CONSTANT( SCALAR_FUNC_SATURATE ); + BIND_CONSTANT( SCALAR_FUNC_NEGATE ); + BIND_CONSTANT( SCALAR_MAX_FUNC ); + + BIND_CONSTANT( VEC_FUNC_NORMALIZE ); + BIND_CONSTANT( VEC_FUNC_SATURATE ); + BIND_CONSTANT( VEC_FUNC_NEGATE ); + BIND_CONSTANT( VEC_FUNC_RECIPROCAL ); + BIND_CONSTANT( VEC_FUNC_RGB2HSV ); + BIND_CONSTANT( VEC_FUNC_HSV2RGB ); + BIND_CONSTANT( VEC_MAX_FUNC ); + + ADD_SIGNAL(MethodInfo("updated")); + + +#if 0 ObjectTypeDB::bind_method(_MD("node_add"),&ShaderGraph::node_add ); ObjectTypeDB::bind_method(_MD("node_remove"),&ShaderGraph::node_remove ); ObjectTypeDB::bind_method(_MD("node_set_param"),&ShaderGraph::node_set_param ); ObjectTypeDB::bind_method(_MD("node_set_pos"),&ShaderGraph::node_set_pos ); ObjectTypeDB::bind_method(_MD("node_get_pos"),&ShaderGraph::node_get_pos ); - ObjectTypeDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_type); - ObjectTypeDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_param); + ObjectTypeDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_param); + ObjectTypeDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_type); ObjectTypeDB::bind_method(_MD("connect"),&ShaderGraph::connect ); ObjectTypeDB::bind_method(_MD("disconnect"),&ShaderGraph::disconnect ); @@ -212,73 +444,161 @@ void ShaderGraph::_bind_methods() { BIND_CONSTANT( NODE_TEXTURE_2D_PARAMETER ); BIND_CONSTANT( NODE_TEXTURE_CUBE_PARAMETER ); BIND_CONSTANT( NODE_TYPE_MAX ); +#endif } -void ShaderGraph::node_add(NodeType p_type,int p_id) { + +String ShaderGraph::_find_unique_name(const String& p_base) { - ERR_FAIL_COND( node_map.has(p_id ) ); - ERR_FAIL_INDEX( p_type, NODE_TYPE_MAX ); + + int idx=1; + while(true) { + String tocmp=p_base; + if (idx>1) { + tocmp+="_"+itos(idx); + } + bool valid=true; + for(int i=0;i<3;i++) { + if (!valid) + break; + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + if (E->get().type!=NODE_SCALAR_INPUT && E->get().type!=NODE_VEC_INPUT && E->get().type==NODE_RGB_INPUT && E->get().type==NODE_XFORM_INPUT && E->get().type==NODE_TEXTURE_INPUT && E->get().type==NODE_CUBEMAP_INPUT) + continue; + String name = E->get().param1; + if (name==tocmp) { + valid=false; + break; + } + + } + } + + if (!valid) { + idx++; + continue; + } + return tocmp; + } + return String(); +} + +void ShaderGraph::node_add(ShaderType p_type, NodeType p_node_type,int p_id) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(p_id==0); + ERR_FAIL_COND(p_node_type==NODE_OUTPUT); //can't create output + ERR_FAIL_COND( shader[p_type].node_map.has(p_id ) ); + ERR_FAIL_INDEX( p_node_type, NODE_TYPE_MAX ); Node node; - node.type=p_type; + if (p_node_type==NODE_INPUT) { + //see if it already exists + for(Map<int,Node>::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + if (E->get().type==NODE_INPUT) { + ERR_EXPLAIN("Only one input node can be added to the graph."); + ERR_FAIL_COND(E->get().type==NODE_INPUT); + } + } + } + node.type=p_node_type; node.id=p_id; - node.x=0; - node.y=0; - node_map[p_id]=node; + switch(p_node_type) { + case NODE_INPUT: {} break; // all inputs (shader type dependent) + case NODE_SCALAR_CONST: { node.param1=0;} break; //scalar constant + case NODE_VEC_CONST: {node.param1=Vector3();} break; //vec3 constant + case NODE_RGB_CONST: {node.param1=Color();} break; //rgb constant (shows a color picker instead) + case NODE_XFORM_CONST: {node.param1=Transform();} break; // 4x4 matrix constant + case NODE_TIME: {} break; // time in seconds + case NODE_SCREEN_TEX: {Array arr; arr.push_back(0); arr.push_back(0); node.param2=arr;} break; // screen texture sampler (takes UV) (only usable in fragment shader) + case NODE_SCALAR_OP: {node.param1=SCALAR_OP_ADD;} break; // scalar vs scalar op (mul: {} break; add: {} break; div: {} break; etc) + case NODE_VEC_OP: {node.param1=VEC_OP_ADD;} break; // vec3 vs vec3 op (mul: {} break;ad: {} break;div: {} break;crossprod: {} break;etc) + case NODE_VEC_SCALAR_OP: {node.param1=VEC_SCALAR_OP_MUL;} break; // vec3 vs scalar op (mul: {} break; add: {} break; div: {} break; etc) + case NODE_RGB_OP: {node.param1=RGB_OP_SCREEN;} break; // vec3 vs vec3 rgb op (with scalar amount): {} break; like brighten: {} break; darken: {} break; burn: {} break; dodge: {} break; multiply: {} break; etc. + case NODE_XFORM_MULT: {} break; // mat4 x mat4 + case NODE_XFORM_VEC_MULT: {} break; // mat4 x vec3 mult (with no-translation option) + case NODE_XFORM_VEC_INV_MULT: {} break; // mat4 x vec3 inverse mult (with no-translation option) + case NODE_SCALAR_FUNC: {node.param1=SCALAR_FUNC_SIN;} break; // scalar function (sin: {} break; cos: {} break; etc) + case NODE_VEC_FUNC: {node.param1=VEC_FUNC_NORMALIZE;} break; // vector function (normalize: {} break; negate: {} break; reciprocal: {} break; rgb2hsv: {} break; hsv2rgb: {} break; etc: {} break; etc) + case NODE_VEC_LEN: {} break; // vec3 length + case NODE_DOT_PROD: {} break; // vec3 . vec3 (dot product -> scalar output) + case NODE_VEC_TO_SCALAR: {} break; // 1 vec3 input: {} break; 3 scalar outputs + case NODE_SCALAR_TO_VEC: {} break; // 3 scalar input: {} break; 1 vec3 output + case NODE_VEC_TO_XFORM: {} break; // 3 scalar input: {} break; 1 vec3 output + case NODE_XFORM_TO_VEC: {} break; // 3 scalar input: {} break; 1 vec3 output + case NODE_SCALAR_INTERP: {} break; // scalar interpolation (with optional curve) + case NODE_VEC_INTERP: {} break; // vec3 interpolation (with optional curve) + case NODE_COLOR_RAMP: { node.param1=DVector<Color>(); node.param2=DVector<real_t>();} break; // vec3 interpolation (with optional curve) + case NODE_CURVE_MAP: { node.param1=DVector<Vector2>();} break; // vec3 interpolation (with optional curve) + case NODE_SCALAR_INPUT: {node.param1=_find_unique_name("Scalar"); node.param2=0;} break; // scalar uniform (assignable in material) + case NODE_VEC_INPUT: {node.param1=_find_unique_name("Vec3");node.param2=Vector3();} break; // vec3 uniform (assignable in material) + case NODE_RGB_INPUT: {node.param1=_find_unique_name("Color");node.param2=Color();} break; // color uniform (assignable in material) + case NODE_XFORM_INPUT: {node.param1=_find_unique_name("XForm"); node.param2=Transform();} break; // mat4 uniform (assignable in material) + case NODE_TEXTURE_INPUT: {node.param1=_find_unique_name("Tex"); } break; // texture input (assignable in material) + case NODE_CUBEMAP_INPUT: {node.param1=_find_unique_name("Cube"); } break; // cubemap input (assignable in material) + case NODE_DEFAULT_TEXTURE: {}; break; + case NODE_OUTPUT: {} break; // output (shader type dependent) + case NODE_COMMENT: {} break; // comment + case NODE_TYPE_MAX: {}; + } + shader[p_type].node_map[p_id]=node; + _request_update(); } -void ShaderGraph::node_set_pos(int p_id, const Vector2& p_pos) { +void ShaderGraph::node_set_pos(ShaderType p_type,int p_id, const Vector2& p_pos) { + ERR_FAIL_INDEX(p_type,3); + + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + shader[p_type].node_map[p_id].pos=p_pos; + _request_update(); - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].x=p_pos.x; - node_map[p_id].y=p_pos.y; } -Vector2 ShaderGraph::node_get_pos(int p_id) const { +Vector2 ShaderGraph::node_get_pos(ShaderType p_type,int p_id) const { + ERR_FAIL_INDEX_V(p_type,3,Vector2()); - ERR_FAIL_COND_V(!node_map.has(p_id),Vector2()); - return Vector2(node_map[p_id].x,node_map[p_id].y); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector2()); + return shader[p_type].node_map[p_id].pos; } -void ShaderGraph::node_remove(int p_id) { +void ShaderGraph::node_remove(ShaderType p_type,int p_id) { + + ERR_FAIL_COND(p_id==0); + ERR_FAIL_INDEX(p_type,3); - ERR_FAIL_COND(!node_map.has(p_id)); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); //erase connections associated with node - List<Connection>::Element *N,*E=connections.front(); - while(E) { - N=E->next(); - const Connection &c = E->get(); - if (c.src_id==p_id || c.dst_id==p_id) { + for(Map<int,Node>::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + if (E->key()==p_id) + continue; //no self + + for (Map<int,SourceSlot>::Element *F=E->get().connections.front();F;) { + Map<int,SourceSlot>::Element *N=F->next(); + + if (F->get().id==p_id) { + E->get().connections.erase(F); + } - connections.erase(E); + F=N; } - E=N; } - node_map.erase(p_id); -} - -void ShaderGraph::node_change_type(int p_id, NodeType p_type) { + shader[p_type].node_map.erase(p_id); - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].type=p_type; - node_map[p_id].param=Variant(); + _request_update(); } -void ShaderGraph::node_set_param(int p_id, const Variant& p_value) { - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].param=p_value; -} -void ShaderGraph::get_node_list(List<int> *p_node_list) const { +void ShaderGraph::get_node_list(ShaderType p_type,List<int> *p_node_list) const { - Map<int,Node>::Element *E = node_map.front(); + ERR_FAIL_INDEX(p_type,3); + + Map<int,Node>::Element *E = shader[p_type].node_map.front(); while(E) { @@ -288,740 +608,1841 @@ void ShaderGraph::get_node_list(List<int> *p_node_list) const { } -ShaderGraph::NodeType ShaderGraph::node_get_type(int p_id) const { +ShaderGraph::NodeType ShaderGraph::node_get_type(ShaderType p_type,int p_id) const { - ERR_FAIL_COND_V(!node_map.has(p_id),NODE_TYPE_MAX); - return node_map[p_id].type; -} + ERR_FAIL_INDEX_V(p_type,3,NODE_TYPE_MAX); -Variant ShaderGraph::node_get_param(int p_id) const { - - ERR_FAIL_COND_V(!node_map.has(p_id),Variant()); - return node_map[p_id].param; + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),NODE_TYPE_MAX); + return shader[p_type].node_map[p_id].type; } -Error ShaderGraph::connect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +Error ShaderGraph::connect_node(ShaderType p_type,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { + ERR_FAIL_INDEX_V(p_type,3,ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_src_id==p_dst_id, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!node_map.has(p_src_id), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!node_map.has(p_dst_id), ERR_INVALID_PARAMETER); - NodeType type_src=node_map[p_src_id].type; - NodeType type_dst=node_map[p_dst_id].type; - //ERR_FAIL_INDEX_V( p_src_slot, VisualServer::shader_get_output_count(type_src), ERR_INVALID_PARAMETER ); - //ERR_FAIL_INDEX_V( p_dst_slot, VisualServer::shader_get_input_count(type_dst), ERR_INVALID_PARAMETER ); - //ERR_FAIL_COND_V(VisualServer::shader_is_output_vector(type_src,p_src_slot) != VisualServer::shader_is_input_vector(type_dst,p_dst_slot), ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_src_id), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_dst_id), ERR_INVALID_PARAMETER); + NodeType type_src=shader[p_type].node_map[p_src_id].type; + NodeType type_dst=shader[p_type].node_map[p_dst_id].type; + ERR_FAIL_INDEX_V( p_src_slot, get_node_output_slot_count(get_mode(),p_type,type_src), ERR_INVALID_PARAMETER ); + ERR_FAIL_INDEX_V( p_dst_slot, get_node_input_slot_count(get_mode(),p_type,type_dst), ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V(get_node_output_slot_type(get_mode(),p_type,type_src,p_src_slot) != get_node_input_slot_type(get_mode(),p_type,type_dst,p_dst_slot), ERR_INVALID_PARAMETER ); - List<Connection>::Element *E=connections.front(); - while(E) { - const Connection &c = E->get(); - ERR_FAIL_COND_V(c.dst_slot==p_dst_slot && c.dst_id == p_dst_id, ERR_ALREADY_EXISTS); + SourceSlot ts; + ts.id=p_src_id; + ts.slot=p_src_slot; + shader[p_type].node_map[p_dst_id].connections[p_dst_slot]=ts; + _request_update(); - E=E->next(); - } + return OK; +} - Connection c; - c.src_slot=p_src_slot; - c.src_id=p_src_id; - c.dst_slot=p_dst_slot; - c.dst_id=p_dst_id; +bool ShaderGraph::is_node_connected(ShaderType p_type,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const { - connections.push_back(c); + ERR_FAIL_INDEX_V(p_type,3,false); - return OK; + SourceSlot ts; + ts.id=p_src_id; + ts.slot=p_src_slot; + return shader[p_type].node_map.has(p_dst_id) && shader[p_type].node_map[p_dst_id].connections.has(p_dst_slot) && + shader[p_type].node_map[p_dst_id].connections[p_dst_slot]==ts; } -bool ShaderGraph::is_connected(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const { +void ShaderGraph::disconnect_node(ShaderType p_type,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { + ERR_FAIL_INDEX(p_type,3); - const List<Connection>::Element *E=connections.front(); - while(E) { - const Connection &c = E->get(); - if (c.dst_slot==p_dst_slot && c.dst_id == p_dst_id && c.src_slot==p_src_slot && c.src_id == p_src_id) - return true; + SourceSlot ts; + ts.id=p_src_id; + ts.slot=p_src_slot; + if (shader[p_type].node_map.has(p_dst_id) && shader[p_type].node_map[p_dst_id].connections.has(p_dst_slot) && + shader[p_type].node_map[p_dst_id].connections[p_dst_slot]==ts) { + shader[p_type].node_map[p_dst_id].connections.erase(p_dst_slot); - E=E->next(); } + _request_update(); - return false; } -void ShaderGraph::disconnect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +void ShaderGraph::get_node_connections(ShaderType p_type,List<Connection> *p_connections) const { - List<Connection>::Element *N,*E=connections.front(); - while(E) { - N=E->next(); - const Connection &c = E->get(); - if (c.src_slot==p_src_slot && c.src_id==p_src_id && c.dst_slot==p_dst_slot && c.dst_id == p_dst_id) { + ERR_FAIL_INDEX(p_type,3); + + for(const Map<int,Node>::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + for (const Map<int,SourceSlot>::Element *F=E->get().connections.front();F;F=F->next()) { - connections.erase(E); + Connection c; + c.dst_id=E->key(); + c.dst_slot=F->key(); + c.src_id=F->get().id; + c.src_slot=F->get().slot; + p_connections->push_back(c); } - E=N; } +} + + +void ShaderGraph::clear(ShaderType p_type) { + ERR_FAIL_INDEX(p_type,3); + shader[p_type].node_map.clear(); + Node out; + out.pos=Vector2(300,300); + out.type=NODE_OUTPUT; + shader[p_type].node_map.insert(0,out); + + _request_update(); } -void ShaderGraph::get_connections(List<Connection> *p_connections) const { - const List<Connection>::Element*E=connections.front(); - while(E) { - p_connections->push_back(E->get()); - E=E->next(); - } +void ShaderGraph::scalar_const_node_set_value(ShaderType p_type,int p_id,float p_value) { + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_CONST); + n.param1=p_value; + _request_update(); } +float ShaderGraph::scalar_const_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_CONST,0); + return n.param1; +} + +void ShaderGraph::vec_const_node_set_value(ShaderType p_type,int p_id,const Vector3& p_value){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_VEC_CONST); + n.param1=p_value; + _request_update(); -void ShaderGraph::clear() { - connections.clear(); - node_map.clear(); } +Vector3 ShaderGraph::vec_const_node_get_value(ShaderType p_type,int p_id) const{ + ERR_FAIL_INDEX_V(p_type,3,Vector3()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector3()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_CONST,Vector3()); + return n.param1; -#if 0 -void ShaderGraph::node_add(NodeType p_type,int p_id) { +} + +void ShaderGraph::rgb_const_node_set_value(ShaderType p_type,int p_id,const Color& p_value){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_RGB_CONST); + n.param1=p_value; + _request_update(); - ShaderNode sn; - sn.type=p_type; - nodes[p_id]=sn; - version++; } -void ShaderGraph::node_remove(int p_id) { +Color ShaderGraph::rgb_const_node_get_value(ShaderType p_type,int p_id) const{ - nodes.erase(p_id); + ERR_FAIL_INDEX_V(p_type,3,Color()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Color()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_RGB_CONST,Color()); + return n.param1; } -void ShaderGraph::node_set_param( int p_id, const Variant& p_value) { - VisualServer::get_singleton()->shader_node_set_param(shader,p_id,p_value); - version++; +void ShaderGraph::xform_const_node_set_value(ShaderType p_type,int p_id,const Transform& p_value){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_XFORM_CONST); + n.param1=p_value; + _request_update(); + } +Transform ShaderGraph::xform_const_node_get_value(ShaderType p_type,int p_id) const{ -void ShaderGraph::get_node_list(List<int> *p_node_list) const { + ERR_FAIL_INDEX_V(p_type,3,Transform()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Transform()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_XFORM_CONST,Transform()); + return n.param1; - VisualServer::get_singleton()->shader_get_node_list(shader,p_node_list); } -ShaderGraph::NodeType ShaderGraph::node_get_type(int p_id) const { - return (NodeType)VisualServer::get_singleton()->shader_node_get_type(shader,p_id); +void ShaderGraph::texture_node_set_filter_size(ShaderType p_type,int p_id,int p_size){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX); + Array arr = n.param2; + arr[0]=p_size; + n.param2=arr; + _request_update(); + +} +int ShaderGraph::texture_node_get_filter_size(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX,0); + Array arr = n.param2; + return arr[0]; + } -Variant ShaderGraph::node_get_param(int p_id) const { - return VisualServer::get_singleton()->shader_node_get_param(shader,p_id); +void ShaderGraph::texture_node_set_filter_strength(ShaderType p_type,float p_id,float p_strength){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX); + Array arr = n.param2; + arr[1]=p_strength; + n.param2=arr; + _request_update(); + +} +float ShaderGraph::texture_node_get_filter_strength(ShaderType p_type,float p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX,0); + Array arr = n.param2; + return arr[1]; } -void ShaderGraph::connect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { - VisualServer::get_singleton()->shader_connect(shader,p_src_id,p_src_slot,p_dst_id,p_dst_slot); - version++; +void ShaderGraph::scalar_op_node_set_op(ShaderType p_type,float p_id,ScalarOp p_op){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_OP); + n.param1=p_op; + _request_update(); + } -void ShaderGraph::disconnect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +ShaderGraph::ScalarOp ShaderGraph::scalar_op_node_get_op(ShaderType p_type,float p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,SCALAR_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),SCALAR_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_OP,SCALAR_MAX_OP); + int op = n.param1; + return ScalarOp(op); - VisualServer::get_singleton()->shader_disconnect(shader,p_src_id,p_src_slot,p_dst_id,p_dst_slot); - version++; } -void ShaderGraph::get_connections(List<Connection> *p_connections) const { - List<VS::ShaderGraphConnection> connections; - VisualServer::get_singleton()->shader_get_connections(shader,&connections); - for( List<VS::ShaderGraphConnection>::Element *E=connections.front();E;E=E->next()) { +void ShaderGraph::vec_op_node_set_op(ShaderType p_type,float p_id,VecOp p_op){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_VEC_OP); + n.param1=p_op; + _request_update(); - Connection c; - c.src_id=E->get().src_id; - c.src_slot=E->get().src_slot; - c.dst_id=E->get().dst_id; - c.dst_slot=E->get().dst_slot; - p_connections->push_back(c); - } } +ShaderGraph::VecOp ShaderGraph::vec_op_node_get_op(ShaderType p_type,float p_id) const{ -void ShaderGraph::node_set_pos(int p_id,const Point2& p_pos) { + ERR_FAIL_INDEX_V(p_type,3,VEC_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),VEC_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_OP,VEC_MAX_OP); + int op = n.param1; + return VecOp(op); -#ifdef TOOLS_ENABLED - ERR_FAIL_COND(!positions.has(p_id)); - positions[p_id]=p_pos; -#endif } -Point2 ShaderGraph::node_get_pos(int p_id) const { -#ifdef TOOLS_ENABLED - ERR_FAIL_COND_V(!positions.has(p_id),Point2()); - return positions[p_id]; -#endif + +void ShaderGraph::vec_scalar_op_node_set_op(ShaderType p_type,float p_id,VecScalarOp p_op){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_VEC_SCALAR_OP); + n.param1=p_op; + _request_update(); + } +ShaderGraph::VecScalarOp ShaderGraph::vec_scalar_op_node_get_op(ShaderType p_type,float p_id) const{ -void ShaderGraph::clear() { + ERR_FAIL_INDEX_V(p_type,3,VEC_SCALAR_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),VEC_SCALAR_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_SCALAR_OP,VEC_SCALAR_MAX_OP); + int op = n.param1; + return VecScalarOp(op); - VisualServer::get_singleton()->shader_clear(shader); - version++; } -#endif -ShaderGraph::ShaderGraph() { +void ShaderGraph::rgb_op_node_set_op(ShaderType p_type,float p_id,RGBOp p_op){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_RGB_OP); + n.param1=p_op; + + _request_update(); - //shader = VisualServer::get_singleton()->shader_create(); - version = 1; } +ShaderGraph::RGBOp ShaderGraph::rgb_op_node_get_op(ShaderType p_type,float p_id) const{ -ShaderGraph::~ShaderGraph() { + ERR_FAIL_INDEX_V(p_type,3,RGB_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),RGB_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_RGB_OP,RGB_MAX_OP); + int op = n.param1; + return RGBOp(op); - //VisualServer::get_singleton()->free(shader); } -#if 0 -void ShaderGraph::shader_get_default_input_nodes(Mode p_type,List<PropertyInfo> *p_inputs) { - switch(p_type) { +void ShaderGraph::xform_vec_mult_node_set_no_translation(ShaderType p_type,int p_id,bool p_no_translation){ - case SHADER_VERTEX: { + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_XFORM_VEC_MULT && n.type!=NODE_XFORM_VEC_INV_MULT); + n.param1=p_no_translation; + _request_update(); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"vertex") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"binormal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"tangent") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"uv") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; - case SHADER_FRAGMENT: { +} +bool ShaderGraph::xform_vec_mult_node_get_no_translation(ShaderType p_type,int p_id) const{ - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"position") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"binormal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"tangent") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"uv") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); + ERR_FAIL_INDEX_V(p_type,3,false); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),false); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_XFORM_VEC_MULT && n.type!=NODE_XFORM_VEC_INV_MULT,false); + return n.param1; - } break; - case SHADER_POST_PROCESS: { - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; +} - } +void ShaderGraph::scalar_func_node_set_function(ShaderType p_type,int p_id,ScalarFunc p_func){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_FUNC); + int func = p_func; + ERR_FAIL_INDEX(func,SCALAR_MAX_FUNC); + n.param1=func; + _request_update(); } -void ShaderGraph::shader_get_default_output_nodes(ShaderGraphType p_type,List<PropertyInfo> *p_outputs) { +ShaderGraph::ScalarFunc ShaderGraph::scalar_func_node_get_function(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,SCALAR_MAX_FUNC); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),SCALAR_MAX_FUNC); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_FUNC,SCALAR_MAX_FUNC); + int func = n.param1; + return ScalarFunc(func); +} - switch(p_type) { +void ShaderGraph::vec_func_node_set_function(ShaderType p_type,int p_id,VecFunc p_func){ - case SHADER_VERTEX: { + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_VEC_FUNC); + int func = p_func; + ERR_FAIL_INDEX(func,VEC_MAX_FUNC); + n.param1=func; - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"vertex") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"binormal") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"tangent") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"uv") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; - case SHADER_FRAGMENT: { + _request_update(); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"diffuse") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"specular") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"emission") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"spec_exp") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"glow") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha_discard") ); +} +ShaderGraph::VecFunc ShaderGraph::vec_func_node_get_function(ShaderType p_type, int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,VEC_MAX_FUNC); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),VEC_MAX_FUNC); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_FUNC,VEC_MAX_FUNC); + int func = n.param1; + return VecFunc(func); +} - } break; - case SHADER_POST_PROCESS: { - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; +void ShaderGraph::color_ramp_node_set_ramp(ShaderType p_type,int p_id,const DVector<Color>& p_colors, const DVector<real_t>& p_offsets){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + ERR_FAIL_COND(p_colors.size()!=p_offsets.size()); + Node& n = shader[p_type].node_map[p_id]; + n.param1=p_colors; + n.param2=p_offsets; + _request_update(); + +} + +DVector<Color> ShaderGraph::color_ramp_node_get_colors(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,DVector<Color>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<Color>()); + const Node& n = shader[p_type].node_map[p_id]; + return n.param1; + + +} + +DVector<real_t> ShaderGraph::color_ramp_node_get_offsets(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,DVector<real_t>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<real_t>()); + const Node& n = shader[p_type].node_map[p_id]; + return n.param2; + +} + + +void ShaderGraph::curve_map_node_set_points(ShaderType p_type,int p_id,const DVector<Vector2>& p_points) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + n.param1=p_points; + _request_update(); + +} + +DVector<Vector2> ShaderGraph::curve_map_node_get_points(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,DVector<Vector2>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<Vector2>()); + const Node& n = shader[p_type].node_map[p_id]; + return n.param1; + +} + + +void ShaderGraph::input_node_set_name(ShaderType p_type,int p_id,const String& p_name){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + ERR_FAIL_COND(!p_name.is_valid_identifier()); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_INPUT && n.type!=NODE_VEC_INPUT && n.type==NODE_RGB_INPUT && n.type==NODE_XFORM_INPUT && n.type==NODE_TEXTURE_INPUT && n.type==NODE_CUBEMAP_INPUT); + + n.param1=""; + n.param1=_find_unique_name(p_name); + _request_update(); + +} +String ShaderGraph::input_node_get_name(ShaderType p_type,int p_id){ + + ERR_FAIL_INDEX_V(p_type,3,String()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),String()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_INPUT && n.type!=NODE_VEC_INPUT && n.type==NODE_RGB_INPUT && n.type==NODE_XFORM_INPUT && n.type==NODE_TEXTURE_INPUT && n.type==NODE_CUBEMAP_INPUT,String()); + return n.param1; +} + + +void ShaderGraph::scalar_input_node_set_value(ShaderType p_type,int p_id,float p_value) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_INPUT); + n.param2=p_value; + _request_update(); + +} + +float ShaderGraph::scalar_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_INPUT,0); + + return n.param2; +} + +void ShaderGraph::vec_input_node_set_value(ShaderType p_type,int p_id,const Vector3& p_value){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_VEC_INPUT); + + n.param2=p_value; + _request_update(); + +} +Vector3 ShaderGraph::vec_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Vector3()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector3()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_INPUT,Vector3()); + return n.param2; +} + +void ShaderGraph::rgb_input_node_set_value(ShaderType p_type,int p_id,const Color& p_value){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_RGB_INPUT); + n.param2=p_value; + _request_update(); + +} +Color ShaderGraph::rgb_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Color()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Color()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_RGB_INPUT,Color()); + return n.param2; +} + +void ShaderGraph::xform_input_node_set_value(ShaderType p_type,int p_id,const Transform& p_value){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_XFORM_INPUT); + n.param2=p_value; + _request_update(); + +} +Transform ShaderGraph::xform_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Transform()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Transform()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_XFORM_INPUT,Transform()); + return n.param2; +} + + +void ShaderGraph::texture_input_node_set_value(ShaderType p_type,int p_id,const Ref<Texture>& p_texture) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_TEXTURE_INPUT); + n.param2=p_texture; + _request_update(); + +} + +Ref<Texture> ShaderGraph::texture_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Ref<Texture>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Ref<Texture>()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT,Ref<Texture>()); + return n.param2; +} + +void ShaderGraph::cubemap_input_node_set_value(ShaderType p_type,int p_id,const Ref<CubeMap>& p_cubemap){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_CUBEMAP_INPUT); + n.param2=p_cubemap; + _request_update(); + +} + +Ref<CubeMap> ShaderGraph::cubemap_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Ref<CubeMap>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Ref<CubeMap>()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_CUBEMAP_INPUT,Ref<CubeMap>()); + return n.param2; + +} + + +void ShaderGraph::comment_node_set_text(ShaderType p_type,int p_id,const String& p_comment) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_COMMENT); + n.param1=p_comment; + +} + +String ShaderGraph::comment_node_get_text(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,String()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),String()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_COMMENT,String()); + return n.param1; + +} + +void ShaderGraph::_request_update() { + + if (_pending_update_shader) + return; + + _pending_update_shader=true; + call_deferred("_update_shader"); + +} + +Variant ShaderGraph::node_get_state(ShaderType p_type,int p_id) const { + + ERR_FAIL_INDEX_V(p_type,3,Variant()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Variant()); + const Node& n = shader[p_type].node_map[p_id]; + Dictionary s; + s["pos"]=n.pos; + s["param1"]=n.param1; + s["param2"]=n.param2; + return s; + +} +void ShaderGraph::node_set_state(ShaderType p_type,int p_id,const Variant& p_state) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + Dictionary d = p_state; + ERR_FAIL_COND(!d.has("pos")); + ERR_FAIL_COND(!d.has("param1")); + ERR_FAIL_COND(!d.has("param2")); + n.pos=d["pos"]; + n.param1=d["param1"]; + n.param2=d["param2"]; + +} + +ShaderGraph::ShaderGraph(Mode p_mode) : Shader(p_mode) { + + //shader = VisualServer::get_singleton()->shader_create(); + _pending_update_shader=false; + Node out; + out.id=0; + out.pos=Vector2(250,20); + out.type=NODE_OUTPUT; + for(int i=0;i<3;i++) { + + shader[i].node_map.insert(0,out); } +} + +ShaderGraph::~ShaderGraph() { + + //VisualServer::get_singleton()->free(shader); +} + + +const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ + //material vertex in + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Vertex","SRC_VERTEX","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Normal","SRC_NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Tangent","SRC_TANGENT","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"BinormalF","SRC_BINORMALF","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Color","SRC_COLOR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Alpha","SRC_ALPHA","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV","SRC_UV","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV2","SRC_UV2","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"WorldMatrix","WORLD_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"InvCameraMatrix","INV_CAMERA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"ProjectionMatrix","PROJECTION_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"ModelviewMatrix","MODELVIEW_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"InstanceID","INSTANCE_ID","",SLOT_TYPE_SCALAR,SLOT_IN}, + + //material vertex out + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Vertex","VERTEX","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Tangent","TANGENT","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Binormal","BINORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV","UV",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV2","UV2",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"SpecExp","SPEC_EXP","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"PointSize","POINT_SIZE","",SLOT_TYPE_SCALAR,SLOT_OUT}, + //pixel vertex in + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Vertex","VERTEX","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Position","POSITION.xyz","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Normal","IN_NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Tangent","TANGENT","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Binormal","BINORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0);","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV2","UV2","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"InvCameraMatrix","INV_CAMERA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + //pixel vertex out + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Diffuse","DIFFUSE_OUT","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"DiffuseAlpha","ALPHA_OUT","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Specular","SPECULAR","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"SpecularExp","SPECULAR","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Emission","EMISSION","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Glow","GLOW","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"ShadeParam","SHADE_PARAM","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"NormalMap","NORMALMAP","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"NormalMapDepth","NORMALMAP_DEPTH","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Discard","DISCARD",">0.5",SLOT_TYPE_SCALAR,SLOT_OUT}, + //light in + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"LightDir","LIGHT_DIR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"LightDiffuse","LIGHT_DIFFUSE","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"LightSpecular","LIGHT_SPECULAR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"EyeVec","EYE_VEC","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Diffuse","DIFFUSE","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Specular","SPECULAR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"SpecExp","SPECULAR_EXP","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"ShadeParam","SHADE_PARAM","",SLOT_TYPE_SCALAR,SLOT_IN}, + //light out + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT}, + //canvas item vertex in + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","vec3(SRC_VERTEX,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","SRC_UV","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Color","SRC_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Alpha","SRC_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"WorldMatrix","WORLD_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"ExtraMatrix","EXTRA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"ProjectionMatrix","PROJECTION_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + //canvas item vertex out + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","VERTEX",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","UV",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"PointSize","POINT_SIZE","",SLOT_TYPE_SCALAR,SLOT_OUT}, + //canvas item fragment in + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","SRC_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","SRC_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, + //canvas item fragment out + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + //canvas item light in + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"UV","vec3(UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightHeight","LIGHT_HEIGHT","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, + //canvas item light out + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + //end + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT}, + + + +}; + +void ShaderGraph::get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List<SlotInfo> *r_slots) { + + const InOutParamInfo* iop = &inout_param_info[0]; + while(iop->name) { + if (p_mode==iop->shader_mode && p_type==iop->shader_type) { + + SlotInfo si; + si.dir=iop->dir; + si.name=iop->name; + si.type=iop->slot_type; + r_slots->push_back(si); + } + iop++; + } +} + +const ShaderGraph::NodeSlotInfo ShaderGraph::node_slot_info[]= { + + {NODE_SCALAR_CONST,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, //scalar constant + {NODE_VEC_CONST,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, //vec3 constant + {NODE_RGB_CONST,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, //rgb constant (shows a color picker instead) + {NODE_XFORM_CONST,{SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // 4x4 matrix constant + {NODE_TIME,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // time in seconds + {NODE_SCREEN_TEX,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // screen texture sampler (takes UV) (only usable in fragment shader) + {NODE_SCALAR_OP,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_OP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // scalar vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_SCALAR_OP,{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_RGB_OP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_XFORM_MULT,{SLOT_TYPE_XFORM,SLOT_TYPE_XFORM,SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // mat4 x mat4 + {NODE_XFORM_VEC_MULT,{SLOT_TYPE_XFORM,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // mat4 x vec3 mult (with no-translation option) + {NODE_XFORM_VEC_INV_MULT,{SLOT_TYPE_VEC,SLOT_TYPE_XFORM,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // mat4 x vec3 inverse mult (with no-translation option) + {NODE_SCALAR_FUNC,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar function (sin,{SLOT_MAX},{SLOT_MAX}}, cos,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_FUNC,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vector function (normalize,{SLOT_MAX},{SLOT_MAX}}, negate,{SLOT_MAX},{SLOT_MAX}}, reciprocal,{SLOT_MAX},{SLOT_MAX}}, rgb2hsv,{SLOT_MAX},{SLOT_MAX}}, hsv2rgb,{SLOT_MAX},{SLOT_MAX}}, etc,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_LEN,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 length + {NODE_DOT_PROD,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 . vec3 (dot product -> scalar output) + {NODE_VEC_TO_SCALAR,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR}}, // 1 vec3 input,{SLOT_MAX},{SLOT_MAX}}, 3 scalar outputs + {NODE_SCALAR_TO_VEC,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR},{SLOT_TYPE_VEC,SLOT_MAX}}, // 3 scalar input,{SLOT_MAX},{SLOT_MAX}}, 1 vec3 output + {NODE_SCALAR_INTERP,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar interpolation (with optional curve) + {NODE_VEC_INTERP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_TYPE_SCALAR},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 interpolation (with optional curve) + {NODE_COLOR_RAMP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve) + {NODE_CURVE_MAP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve) + {NODE_SCALAR_INPUT,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar uniform (assignable in material) + {NODE_VEC_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 uniform (assignable in material) + {NODE_RGB_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // color uniform (assignable in material) + {NODE_XFORM_INPUT,{SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // mat4 uniform (assignable in material) + {NODE_TEXTURE_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // texture input (assignable in material) + {NODE_CUBEMAP_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material) + {NODE_DEFAULT_TEXTURE,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material) + {NODE_COMMENT,{SLOT_MAX},{SLOT_MAX}}, // comment + {NODE_TYPE_MAX,{SLOT_MAX},{SLOT_MAX}} +}; + +int ShaderGraph::get_node_input_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type) { + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_OUT) + pc++; + } + iop++; + } + return pc; + } else if (p_type==NODE_VEC_TO_XFORM){ + return 4; + } else if (p_type==NODE_XFORM_TO_VEC){ + return 1; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + int pc=0; + for(int i=0;i<NodeSlotInfo::MAX_INS;i++) { + if (nsi->ins[i]==SLOT_MAX) + break; + pc++; + } + return pc; + } + + nsi++; + } + + return 0; + + } } +int ShaderGraph::get_node_output_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type){ + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { -PropertyInfo ShaderGraph::shader_node_get_type_info(NodeType p_type) { - - switch(p_type) { - - case NODE_IN: return PropertyInfo(Variant::STRING,"in"); - case NODE_OUT: return PropertyInfo(Variant::STRING,"out"); - case NODE_CONSTANT: return PropertyInfo(Variant::REAL,"const"); - case NODE_PARAMETER: return PropertyInfo(Variant::STRING,"param"); - case NODE_ADD: return PropertyInfo(Variant::NIL,"add"); - case NODE_SUB: return PropertyInfo(Variant::NIL,"sub"); - case NODE_MUL: return PropertyInfo(Variant::NIL,"mul"); - case NODE_DIV: return PropertyInfo(Variant::NIL,"div"); - case NODE_MOD: return PropertyInfo(Variant::NIL,"rem"); - case NODE_SIN: return PropertyInfo(Variant::NIL,"sin"); - case NODE_COS: return PropertyInfo(Variant::NIL,"cos"); - case NODE_TAN: return PropertyInfo(Variant::NIL,"tan"); - case NODE_ARCSIN: return PropertyInfo(Variant::NIL,"arcsin"); - case NODE_ARCCOS: return PropertyInfo(Variant::NIL,"arccos"); - case NODE_ARCTAN: return PropertyInfo(Variant::NIL,"arctan"); - case NODE_POW: return PropertyInfo(Variant::NIL,"pow"); - case NODE_LOG: return PropertyInfo(Variant::NIL,"log"); - case NODE_MAX: return PropertyInfo(Variant::NIL,"max"); - case NODE_MIN: return PropertyInfo(Variant::NIL,"min"); - case NODE_COMPARE: return PropertyInfo(Variant::NIL,"cmp"); - case NODE_TEXTURE: return PropertyInfo(Variant::_RID,"texture1D",PROPERTY_HINT_RESOURCE_TYPE,"Texture"); - case NODE_TIME: return PropertyInfo(Variant::NIL,"time"); - case NODE_NOISE: return PropertyInfo(Variant::NIL,"noise"); - case NODE_PASS: return PropertyInfo(Variant::NIL,"pass"); - case NODE_VEC_IN: return PropertyInfo(Variant::STRING,"vin"); - case NODE_VEC_OUT: return PropertyInfo(Variant::STRING,"vout"); - case NODE_VEC_CONSTANT: return PropertyInfo(Variant::VECTOR3,"vconst"); - case NODE_VEC_PARAMETER: return PropertyInfo(Variant::STRING,"vparam"); - case NODE_VEC_ADD: return PropertyInfo(Variant::NIL,"vadd"); - case NODE_VEC_SUB: return PropertyInfo(Variant::NIL,"vsub"); - case NODE_VEC_MUL: return PropertyInfo(Variant::NIL,"vmul"); - case NODE_VEC_DIV: return PropertyInfo(Variant::NIL,"vdiv"); - case NODE_VEC_MOD: return PropertyInfo(Variant::NIL,"vrem"); - case NODE_VEC_CROSS: return PropertyInfo(Variant::NIL,"cross"); - case NODE_VEC_DOT: return PropertyInfo(Variant::NIL,"dot"); - case NODE_VEC_POW: return PropertyInfo(Variant::NIL,"vpow"); - case NODE_VEC_NORMALIZE: return PropertyInfo(Variant::NIL,"normalize"); - case NODE_VEC_INTERPOLATE: return PropertyInfo(Variant::NIL,"mix"); - case NODE_VEC_SCREEN_TO_UV: return PropertyInfo(Variant::NIL,"scrn2uv"); - case NODE_VEC_TRANSFORM3: return PropertyInfo(Variant::NIL,"xform3"); - case NODE_VEC_TRANSFORM4: return PropertyInfo(Variant::NIL,"xform4"); - case NODE_VEC_COMPARE: return PropertyInfo(Variant::_RID,"vcmp",PROPERTY_HINT_RESOURCE_TYPE,"Texture"); - case NODE_VEC_TEXTURE_2D: return PropertyInfo(Variant::_RID,"texture2D",PROPERTY_HINT_RESOURCE_TYPE,"Texture"); - case NODE_VEC_TEXTURE_CUBE: return PropertyInfo(Variant::NIL,"texcube"); - case NODE_VEC_NOISE: return PropertyInfo(Variant::NIL,"vec_noise"); - case NODE_VEC_0: return PropertyInfo(Variant::NIL,"vec_0"); - case NODE_VEC_1: return PropertyInfo(Variant::NIL,"vec_1"); - case NODE_VEC_2: return PropertyInfo(Variant::NIL,"vec_2"); - case NODE_VEC_BUILD: return PropertyInfo(Variant::NIL,"vbuild"); - case NODE_VEC_PASS: return PropertyInfo(Variant::NIL,"vpass"); - case NODE_COLOR_CONSTANT: return PropertyInfo(Variant::COLOR,"color_const"); - case NODE_COLOR_PARAMETER: return PropertyInfo(Variant::STRING,"color_param"); - case NODE_TEXTURE_PARAMETER: return PropertyInfo(Variant::STRING,"tex1D_param"); - case NODE_TEXTURE_2D_PARAMETER: return PropertyInfo(Variant::STRING,"tex2D_param"); - case NODE_TEXTURE_CUBE_PARAMETER: return PropertyInfo(Variant::STRING,"texcube_param"); - case NODE_TRANSFORM_CONSTANT: return PropertyInfo(Variant::TRANSFORM,"xform_const"); - case NODE_TRANSFORM_PARAMETER: return PropertyInfo(Variant::STRING,"xform_param"); - case NODE_LABEL: return PropertyInfo(Variant::STRING,"label"); - - default: {} + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_IN) + pc++; + } + iop++; + } + return pc; + } else if (p_type==NODE_VEC_TO_XFORM){ + return 1; + } else if (p_type==NODE_XFORM_TO_VEC){ + return 4; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + int pc=0; + for(int i=0;i<NodeSlotInfo::MAX_OUTS;i++) { + if (nsi->outs[i]==SLOT_MAX) + break; + pc++; + } + return pc; + } + + nsi++; + } + + return 0; } +} +ShaderGraph::SlotType ShaderGraph::get_node_input_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx){ + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_OUT) { + if (pc==p_idx) + return iop->slot_type; + pc++; + } + } + iop++; + } + ERR_FAIL_V(SLOT_MAX); + } else if (p_type==NODE_VEC_TO_XFORM){ + return SLOT_TYPE_VEC; + } else if (p_type==NODE_XFORM_TO_VEC){ + return SLOT_TYPE_XFORM; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + for(int i=0;i<NodeSlotInfo::MAX_INS;i++) { + + if (nsi->ins[i]==SLOT_MAX) + break; + if (i==p_idx) + return nsi->ins[i]; + } + } + + nsi++; + } + + ERR_FAIL_V(SLOT_MAX); - ERR_FAIL_V( PropertyInfo(Variant::NIL,"error") ); -} -int ShaderGraph::shader_get_input_count(NodeType p_type) { - - switch(p_type) { - case NODE_IN: return 0; - case NODE_OUT: return 1; - case NODE_CONSTANT: return 0; - case NODE_PARAMETER: return 0; - case NODE_ADD: return 2; - case NODE_SUB: return 2; - case NODE_MUL: return 2; - case NODE_DIV: return 2; - case NODE_MOD: return 2; - case NODE_SIN: return 1; - case NODE_COS: return 1; - case NODE_TAN: return 1; - case NODE_ARCSIN: return 1; - case NODE_ARCCOS: return 1; - case NODE_ARCTAN: return 1; - case NODE_POW: return 2; - case NODE_LOG: return 1; - case NODE_MAX: return 2; - case NODE_MIN: return 2; - case NODE_COMPARE: return 4; - case NODE_TEXTURE: return 1; ///< param 0: texture - case NODE_TIME: return 1; ///< param 0: interval length - case NODE_NOISE: return 0; - case NODE_PASS: return 1; - case NODE_VEC_IN: return 0; ///< param 0: name - case NODE_VEC_OUT: return 1; ///< param 0: name - case NODE_VEC_CONSTANT: return 0; ///< param 0: value - case NODE_VEC_PARAMETER: return 0; ///< param 0: name - case NODE_VEC_ADD: return 2; - case NODE_VEC_SUB: return 2; - case NODE_VEC_MUL: return 2; - case NODE_VEC_DIV: return 2; - case NODE_VEC_MOD: return 2; - case NODE_VEC_CROSS: return 2; - case NODE_VEC_DOT: return 2; - case NODE_VEC_POW: return 2; - case NODE_VEC_NORMALIZE: return 1; - case NODE_VEC_INTERPOLATE: return 3; - case NODE_VEC_SCREEN_TO_UV: return 1; - case NODE_VEC_TRANSFORM3: return 4; - case NODE_VEC_TRANSFORM4: return 5; - case NODE_VEC_COMPARE: return 4; - case NODE_VEC_TEXTURE_2D: return 1; - case NODE_VEC_TEXTURE_CUBE: return 1; - case NODE_VEC_NOISE: return 0; - case NODE_VEC_0: return 1; - case NODE_VEC_1: return 1; - case NODE_VEC_2: return 1; - case NODE_VEC_BUILD: return 3; - case NODE_VEC_PASS: return 1; - case NODE_COLOR_CONSTANT: return 0; - case NODE_COLOR_PARAMETER: return 0; - case NODE_TEXTURE_PARAMETER: return 1; - case NODE_TEXTURE_2D_PARAMETER: return 1; - case NODE_TEXTURE_CUBE_PARAMETER: return 1; - case NODE_TRANSFORM_CONSTANT: return 1; - case NODE_TRANSFORM_PARAMETER: return 1; - case NODE_LABEL: return 0; - default: {} } - ERR_FAIL_V( 0 ); -} -int ShaderGraph::shader_get_output_count(NodeType p_type) { - - switch(p_type) { - case NODE_IN: return 1; - case NODE_OUT: return 0; - case NODE_CONSTANT: return 1; - case NODE_PARAMETER: return 1; - case NODE_ADD: return 1; - case NODE_SUB: return 1; - case NODE_MUL: return 1; - case NODE_DIV: return 1; - case NODE_MOD: return 1; - case NODE_SIN: return 1; - case NODE_COS: return 1; - case NODE_TAN: return 1; - case NODE_ARCSIN: return 1; - case NODE_ARCCOS: return 1; - case NODE_ARCTAN: return 1; - case NODE_POW: return 1; - case NODE_LOG: return 1; - case NODE_MAX: return 1; - case NODE_MIN: return 1; - case NODE_COMPARE: return 2; - case NODE_TEXTURE: return 3; ///< param 0: texture - case NODE_TIME: return 1; ///< param 0: interval length - case NODE_NOISE: return 1; - case NODE_PASS: return 1; - case NODE_VEC_IN: return 1; ///< param 0: name - case NODE_VEC_OUT: return 0; ///< param 0: name - case NODE_VEC_CONSTANT: return 1; ///< param 0: value - case NODE_VEC_PARAMETER: return 1; ///< param 0: name - case NODE_VEC_ADD: return 1; - case NODE_VEC_SUB: return 1; - case NODE_VEC_MUL: return 1; - case NODE_VEC_DIV: return 1; - case NODE_VEC_MOD: return 1; - case NODE_VEC_CROSS: return 1; - case NODE_VEC_DOT: return 1; - case NODE_VEC_POW: return 1; - case NODE_VEC_NORMALIZE: return 1; - case NODE_VEC_INTERPOLATE: return 1; - case NODE_VEC_SCREEN_TO_UV: return 1; - case NODE_VEC_TRANSFORM3: return 1; - case NODE_VEC_TRANSFORM4: return 1; - case NODE_VEC_COMPARE: return 2; - case NODE_VEC_TEXTURE_2D: return 3; - case NODE_VEC_TEXTURE_CUBE: return 3; - case NODE_VEC_NOISE: return 1; - case NODE_VEC_0: return 1; - case NODE_VEC_1: return 1; - case NODE_VEC_2: return 1; - case NODE_VEC_BUILD: return 1; - case NODE_VEC_PASS: return 1; - case NODE_COLOR_CONSTANT: return 2; - case NODE_COLOR_PARAMETER: return 2; - case NODE_TEXTURE_PARAMETER: return 3; - case NODE_TEXTURE_2D_PARAMETER: return 3; - case NODE_TEXTURE_CUBE_PARAMETER: return 3; - case NODE_TRANSFORM_CONSTANT: return 1; - case NODE_TRANSFORM_PARAMETER: return 1; - case NODE_LABEL: return 0; - - default: {} +} +ShaderGraph::SlotType ShaderGraph::get_node_output_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx){ + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_IN) { + if (pc==p_idx) + return iop->slot_type; + pc++; + } + } + iop++; + } + ERR_FAIL_V(SLOT_MAX); + } else if (p_type==NODE_VEC_TO_XFORM){ + return SLOT_TYPE_XFORM; + } else if (p_type==NODE_XFORM_TO_VEC){ + return SLOT_TYPE_VEC; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + for(int i=0;i<NodeSlotInfo::MAX_OUTS;i++) { + if (nsi->outs[i]==SLOT_MAX) + break; + if (i==p_idx) + return nsi->outs[i]; + } + } + + nsi++; + } + + ERR_FAIL_V(SLOT_MAX); } - ERR_FAIL_V( 0 ); - -} - -#define RET2(m_a,m_b) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else return ""; -#define RET3(m_a,m_b,m_c) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else if (p_idx==2) return m_c; else return ""; -#define RET4(m_a,m_b,m_c,m_d) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else if (p_idx==2) return m_c; else if (p_idx==3) return m_d; else return ""; - -#define RET5(m_a,m_b,m_c,m_d,m_e) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else if (p_idx==2) return m_c; else if (p_idx==3) return m_d; else if (p_idx==4) return m_e; else return ""; - -String ShaderGraph::shader_get_input_name(NodeType p_type,int p_idx) { - - switch(p_type) { - - case NODE_IN: return ""; - case NODE_OUT: return "out"; - case NODE_CONSTANT: return ""; - case NODE_PARAMETER: return ""; - case NODE_ADD: RET2("a","b"); - case NODE_SUB: RET2("a","b"); - case NODE_MUL: RET2("a","b"); - case NODE_DIV: RET2("a","b"); - case NODE_MOD: RET2("a","b"); - case NODE_SIN: return "rad"; - case NODE_COS: return "rad"; - case NODE_TAN: return "rad"; - case NODE_ARCSIN: return "in"; - case NODE_ARCCOS: return "in"; - case NODE_ARCTAN: return "in"; - case NODE_POW: RET2("in","exp"); - case NODE_LOG: return "in"; - case NODE_MAX: return "in"; - case NODE_MIN: return "in"; - case NODE_COMPARE: RET4("a","b","ret1","ret2"); - case NODE_TEXTURE: return "u"; - case NODE_TIME: return ""; - case NODE_NOISE: return ""; - case NODE_PASS: return "in"; - case NODE_VEC_IN: return ""; - case NODE_VEC_OUT: return "out"; - case NODE_VEC_CONSTANT: return ""; - case NODE_VEC_PARAMETER: return ""; - case NODE_VEC_ADD: RET2("a","b"); - case NODE_VEC_SUB: RET2("a","b"); - case NODE_VEC_MUL: RET2("a","b"); - case NODE_VEC_DIV: RET2("a","b"); - case NODE_VEC_MOD: RET2("a","b"); - case NODE_VEC_CROSS: RET2("a","b"); - case NODE_VEC_DOT: RET2("a","b"); - case NODE_VEC_POW: RET2("a","b"); - case NODE_VEC_NORMALIZE: return "vec"; - case NODE_VEC_INTERPOLATE: RET3("a","b","c"); - case NODE_VEC_SCREEN_TO_UV: return "scr"; - case NODE_VEC_TRANSFORM3: RET4("in","col0","col1","col2"); - case NODE_VEC_TRANSFORM4: RET5("in","col0","col1","col2","col3"); - case NODE_VEC_COMPARE: RET4("a","b","ret1","ret2"); - case NODE_VEC_TEXTURE_2D: return "uv"; - case NODE_VEC_TEXTURE_CUBE: return "uvw"; - case NODE_VEC_NOISE: return ""; - case NODE_VEC_0: return "vec"; - case NODE_VEC_1: return "vec"; - case NODE_VEC_2: return "vec"; - case NODE_VEC_BUILD: RET3("x/r","y/g","z/b"); - case NODE_VEC_PASS: return "in"; - case NODE_COLOR_CONSTANT: return ""; - case NODE_COLOR_PARAMETER: return ""; - case NODE_TEXTURE_PARAMETER: return "u"; - case NODE_TEXTURE_2D_PARAMETER: return "uv"; - case NODE_TEXTURE_CUBE_PARAMETER: return "uvw"; - case NODE_TRANSFORM_CONSTANT: return "in"; - case NODE_TRANSFORM_PARAMETER: return "in"; - case NODE_LABEL: return ""; - - default: {} +} + + + + + +void ShaderGraph::_update_shader() { + + + String code[3]; + + List<StringName> names; + get_default_texture_param_list(&names); + + for (List<StringName>::Element *E=names.front();E;E=E->next()) { + set_default_texture_param(E->get(),Ref<Texture>()); } - ERR_FAIL_V(""); -} -String ShaderGraph::shader_get_output_name(NodeType p_type,int p_idx) { - - switch(p_type) { - - case NODE_IN: return "in"; - case NODE_OUT: return ""; - case NODE_CONSTANT: return "out"; - case NODE_PARAMETER: return "out"; - case NODE_ADD: return "sum"; - case NODE_SUB: return "dif"; - case NODE_MUL: return "prod"; - case NODE_DIV: return "quot"; - case NODE_MOD: return "rem"; - case NODE_SIN: return "out"; - case NODE_COS: return "out"; - case NODE_TAN: return "out"; - case NODE_ARCSIN: return "rad"; - case NODE_ARCCOS: return "rad"; - case NODE_ARCTAN: return "rad"; - case NODE_POW: RET2("in","exp"); - case NODE_LOG: return "out"; - case NODE_MAX: return "out"; - case NODE_MIN: return "out"; - case NODE_COMPARE: RET2("a/b","a/b"); - case NODE_TEXTURE: RET3("rgb","a","v"); - case NODE_TIME: return "out"; - case NODE_NOISE: return "out"; - case NODE_PASS: return "out"; - case NODE_VEC_IN: return "in"; - case NODE_VEC_OUT: return ""; - case NODE_VEC_CONSTANT: return "out"; - case NODE_VEC_PARAMETER: return "out"; - case NODE_VEC_ADD: return "sum"; - case NODE_VEC_SUB: return "sub"; - case NODE_VEC_MUL: return "mul"; - case NODE_VEC_DIV: return "div"; - case NODE_VEC_MOD: return "rem"; - case NODE_VEC_CROSS: return "crs"; - case NODE_VEC_DOT: return "prod"; - case NODE_VEC_POW: return "out"; - case NODE_VEC_NORMALIZE: return "norm"; - case NODE_VEC_INTERPOLATE: return "out"; - case NODE_VEC_SCREEN_TO_UV: return "uv"; - case NODE_VEC_TRANSFORM3: return "prod"; - case NODE_VEC_TRANSFORM4: return "prod"; - case NODE_VEC_COMPARE: RET2("a/b","a/b"); - case NODE_VEC_TEXTURE_2D: RET3("rgb","a","v"); - case NODE_VEC_TEXTURE_CUBE: RET3("rgb","a","v"); - case NODE_VEC_NOISE: return "out"; - case NODE_VEC_0: return "x/r"; - case NODE_VEC_1: return "y/g"; - case NODE_VEC_2: return "z/b"; - case NODE_VEC_BUILD: return "vec"; - case NODE_VEC_PASS: return "out"; - case NODE_COLOR_CONSTANT: RET2("rgb","a"); - case NODE_COLOR_PARAMETER: RET2("rgb","a"); - case NODE_TEXTURE_PARAMETER: RET3("rgb","a","v"); - case NODE_TEXTURE_2D_PARAMETER: RET3("rgb","a","v"); - case NODE_TEXTURE_CUBE_PARAMETER: RET3("rgb","a","v"); - case NODE_TRANSFORM_CONSTANT: return "out"; - case NODE_TRANSFORM_PARAMETER: return "out"; - case NODE_LABEL: return ""; - - default: {} + + for(int i=0;i<3;i++) { + + int idx=0; + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + + E->get().sort_order=idx++; + } + //simple method for graph solving using bubblesort derived algorithm + int iters=0; + int iter_max=shader[i].node_map.size()*shader[i].node_map.size(); + + while(true) { + if (iters>iter_max) + break; + + int swaps=0; + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + + for(Map<int,SourceSlot>::Element *F=E->get().connections.front();F;F=F->next()) { + + //this is kinda slow, could be sped up + Map<int,Node>::Element *G = shader[i].node_map.find(F->get().id); + ERR_FAIL_COND(!G); + if (G->get().sort_order > E->get().sort_order) { + + SWAP(G->get().sort_order,E->get().sort_order); + swaps++; + } + } + } + + iters++; + if (swaps==0) { + iters=0; + break; + } + } + + if (iters>0) { + + shader[i].error=GRAPH_ERROR_CYCLIC; + continue; + } + + Vector<Node*> order; + order.resize(shader[i].node_map.size()); + + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + + order[E->get().sort_order]=&E->get(); + } + + //generate code for the ordered graph + bool failed=false; + + if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { + code[i]+="vec3 DIFFUSE_OUT=vec3(0,0,0);\n"; + code[i]+="float ALPHA_OUT=0;\n"; + } + + + Map<String,String> inputs_xlate; + Map<String,String> input_names_xlate; + Set<String> inputs_used; + + for(int j=0;j<order.size();j++) { + + Node *n=order[j]; + if (n->type==NODE_INPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int idx=0; + while(iop->name) { + if (get_mode()==iop->shader_mode && i==iop->shader_type && SLOT_IN==iop->dir) { + + const char *typestr[4]={"float","vec3","mat4","texture"}; + + String vname=("nd"+itos(n->id)+"sl"+itos(idx)); + inputs_xlate[vname]=String(typestr[iop->slot_type])+" "+vname+"="+iop->variable+";\n"; + input_names_xlate[vname]=iop->variable; + idx++; + } + iop++; + } + + } else if (n->type==NODE_OUTPUT) { + + + bool use_alpha=false; + const InOutParamInfo* iop = &inout_param_info[0]; + int idx=0; + while(iop->name) { + if (get_mode()==iop->shader_mode && i==iop->shader_type && SLOT_OUT==iop->dir) { + + if (n->connections.has(idx)) { + String iname=("nd"+itos(n->connections[idx].id)+"sl"+itos(n->connections[idx].slot)); + if (node_get_type(ShaderType(i),n->connections[idx].id)==NODE_INPUT) + inputs_used.insert(iname); + code[i]+=String(iop->variable)+"="+iname+String(iop->postfix)+";\n"; + if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL && String(iop->name)=="DiffuseAlpha") + use_alpha=true; + } + idx++; + } + iop++; + } + + if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { + + if (use_alpha) { + code[i]+="DIFFUSE_ALPHA=vec4(DIFFUSE_OUT,ALPHA_OUT);\n"; + } else { + code[i]+="DIFFUSE=DIFFUSE_OUT;\n"; + } + } + + } else { + Vector<String> inputs; + int max = get_node_input_slot_count(get_mode(),ShaderType(i),n->type); + for(int k=0;k<max;k++) { + if (!n->connections.has(k)) { + shader[i].error=GRAPH_ERROR_MISSING_CONNECTIONS; + failed=true; + break; + } + String iname="nd"+itos(n->connections[k].id)+"sl"+itos(n->connections[k].slot); + inputs.push_back(iname); + if (node_get_type(ShaderType(i),n->connections[k].id)==NODE_INPUT) { + inputs_used.insert(iname); + } + + } + + if (failed) + break; + + if (n->type==NODE_TEXTURE_INPUT || n->type==NODE_CUBEMAP_INPUT) { + + set_default_texture_param(n->param1,n->param2); + } + _add_node_code(ShaderType(i),n,inputs,code[i]); + } + + } + + if (failed) + continue; + + + for(Set<String>::Element *E=inputs_used.front();E;E=E->next()) { + + ERR_CONTINUE( !inputs_xlate.has(E->get())); + code[i]=inputs_xlate[E->get()]+code[i]; + String name=input_names_xlate[E->get()]; + + if (i==SHADER_TYPE_VERTEX && get_mode()==MODE_MATERIAL) { + if (name==("SRC_COLOR")) + code[i]="vec3 SRC_COLOR=COLOR.rgb;\n"+code[i]; + if (name==("SRC_ALPHA")) + code[i]="float SRC_ALPHA=COLOR.a;\n"+code[i]; + if (name==("SRC_UV")) + code[i]="vec3 SRC_UV=vec3(UV,0);\n"+code[i]; + if (name==("SRC_UV2")) + code[i]="float SRC_UV2=vec3(UV2,0);\n"+code[i]; + } else if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { + if (name==("IN_NORMAL")) + code[i]="vec3 IN_NORMAL=NORMAL;\n"+code[i]; + } else if (i==SHADER_TYPE_VERTEX && get_mode()==MODE_CANVAS_ITEM) { + if (name==("SRC_COLOR")) + code[i]="vec3 SRC_COLOR=COLOR.rgb;\n"+code[i]; + if (name==("SRC_UV")) + code[i]="vec3 SRC_UV=vec3(UV,0);\n"+code[i]; + } + + } + + + + shader[i].error=GRAPH_OK; + } - ERR_FAIL_V(""); -} -bool ShaderGraph::shader_is_input_vector(NodeType p_type,int p_input) { - - switch(p_type) { - - case NODE_IN: return false; - case NODE_OUT: return false; - case NODE_CONSTANT: return false; - case NODE_PARAMETER: return false; - case NODE_ADD: return false; - case NODE_SUB: return false; - case NODE_MUL: return false; - case NODE_DIV: return false; - case NODE_MOD: return false; - case NODE_SIN: return false; - case NODE_COS: return false; - case NODE_TAN: return false; - case NODE_ARCSIN: return false; - case NODE_ARCCOS: return false; - case NODE_ARCTAN: return false; - case NODE_POW: return false; - case NODE_LOG: return false; - case NODE_MAX: return false; - case NODE_MIN: return false; - case NODE_COMPARE: return false; - case NODE_TEXTURE: return false; - case NODE_TIME: return false; - case NODE_NOISE: return false; - case NODE_PASS: return false; - case NODE_VEC_IN: return false; - case NODE_VEC_OUT: return true; - case NODE_VEC_CONSTANT: return false; - case NODE_VEC_PARAMETER: return false; - case NODE_VEC_ADD: return true; - case NODE_VEC_SUB: return true; - case NODE_VEC_MUL: return true; - case NODE_VEC_DIV: return true; - case NODE_VEC_MOD: return true; - case NODE_VEC_CROSS: return true; - case NODE_VEC_DOT: return true; - case NODE_VEC_POW: return (p_input==0)?true:false; - case NODE_VEC_NORMALIZE: return true; - case NODE_VEC_INTERPOLATE: return (p_input<2)?true:false; - case NODE_VEC_SCREEN_TO_UV: return true; - case NODE_VEC_TRANSFORM3: return true; - case NODE_VEC_TRANSFORM4: return true; - case NODE_VEC_COMPARE: return (p_input<2)?false:true; - case NODE_VEC_TEXTURE_2D: return true; - case NODE_VEC_TEXTURE_CUBE: return true; - case NODE_VEC_NOISE: return false; - case NODE_VEC_0: return true; - case NODE_VEC_1: return true; - case NODE_VEC_2: return true; - case NODE_VEC_BUILD: return false; - case NODE_VEC_PASS: return true; - case NODE_COLOR_CONSTANT: return false; - case NODE_COLOR_PARAMETER: return false; - case NODE_TEXTURE_PARAMETER: return false; - case NODE_TEXTURE_2D_PARAMETER: return true; - case NODE_TEXTURE_CUBE_PARAMETER: return true; - case NODE_TRANSFORM_CONSTANT: return true; - case NODE_TRANSFORM_PARAMETER: return true; - case NODE_LABEL: return false; - - default: {} + bool all_ok=true; + for(int i=0;i<3;i++) { + if (shader[i].error!=GRAPH_OK) + all_ok=false; } - ERR_FAIL_V(false); -} -bool ShaderGraph::shader_is_output_vector(NodeType p_type,int p_input) { - - switch(p_type) { - - case NODE_IN: return false; - case NODE_OUT: return false ; - case NODE_CONSTANT: return false; - case NODE_PARAMETER: return false; - case NODE_ADD: return false; - case NODE_SUB: return false; - case NODE_MUL: return false; - case NODE_DIV: return false; - case NODE_MOD: return false; - case NODE_SIN: return false; - case NODE_COS: return false; - case NODE_TAN: return false; - case NODE_ARCSIN: return false; - case NODE_ARCCOS: return false; - case NODE_ARCTAN: return false; - case NODE_POW: return false; - case NODE_LOG: return false; - case NODE_MAX: return false; - case NODE_MIN: return false; - case NODE_COMPARE: return false; - case NODE_TEXTURE: return false; - case NODE_TIME: return false; - case NODE_NOISE: return false; - case NODE_PASS: return false; - case NODE_VEC_IN: return true; - case NODE_VEC_OUT: return false; - case NODE_VEC_CONSTANT: return true; - case NODE_VEC_PARAMETER: return true; - case NODE_VEC_ADD: return true; - case NODE_VEC_SUB: return true; - case NODE_VEC_MUL: return true; - case NODE_VEC_DIV: return true; - case NODE_VEC_MOD: return true; - case NODE_VEC_CROSS: return true; - case NODE_VEC_DOT: return false; - case NODE_VEC_POW: return true; - case NODE_VEC_NORMALIZE: return true; - case NODE_VEC_INTERPOLATE: return true; - case NODE_VEC_SCREEN_TO_UV: return true; - case NODE_VEC_TRANSFORM3: return true; - case NODE_VEC_TRANSFORM4: return true; - case NODE_VEC_COMPARE: return true; - case NODE_VEC_TEXTURE_2D: return (p_input==0)?true:false; - case NODE_VEC_TEXTURE_CUBE: return (p_input==0)?true:false; - case NODE_VEC_NOISE: return true; - case NODE_VEC_0: return false; - case NODE_VEC_1: return false; - case NODE_VEC_2: return false; - case NODE_VEC_BUILD: return true; - case NODE_VEC_PASS: return true; - case NODE_COLOR_CONSTANT: return (p_input==0)?true:false; - case NODE_COLOR_PARAMETER: return (p_input==0)?true:false; - case NODE_TEXTURE_PARAMETER: return (p_input==0)?true:false; - case NODE_TEXTURE_2D_PARAMETER: return (p_input==0)?true:false; - case NODE_TEXTURE_CUBE_PARAMETER: return (p_input==0)?true:false; - case NODE_TRANSFORM_CONSTANT: return true; - case NODE_TRANSFORM_PARAMETER: return true; - case NODE_LABEL: return false; - - default: {} + /*print_line("VERTEX: \n"+code[0]); + print_line("FRAGMENT: \n"+code[1]); + print_line("LIGHT: \n"+code[2]);*/ + + if (all_ok) { + set_code(code[0],code[1],code[2]); } + //do shader here - ERR_FAIL_V(""); + _pending_update_shader=false; + emit_signal(SceneStringNames::get_singleton()->updated); } -#endif -#endif +void ShaderGraph::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d,uint8_t* p_heights,bool *p_useds) { + + float geometry[4][4]; + float tmp1[4][4]; + float tmp2[4][4]; + float deltas[4][4]; + double x, dx, dx2, dx3; + double y, dy, dy2, dy3; + double d, d2, d3; + int lastx, lasty; + int newx, newy; + int ntimes; + int i,j; + + int xmax=255; + int ymax=255; + + /* construct the geometry matrix from the segment */ + for (i = 0; i < 4; i++) { + geometry[i][2] = 0; + geometry[i][3] = 0; + } + + geometry[0][0] = (p_a[0] * xmax); + geometry[1][0] = (p_b[0] * xmax); + geometry[2][0] = (p_c[0] * xmax); + geometry[3][0] = (p_d[0] * xmax); + + geometry[0][1] = (p_a[1] * ymax); + geometry[1][1] = (p_b[1] * ymax); + geometry[2][1] = (p_c[1] * ymax); + geometry[3][1] = (p_d[1] * ymax); + + /* subdivide the curve ntimes (1000) times */ + ntimes = 4 * xmax; + /* ntimes can be adjusted to give a finer or coarser curve */ + d = 1.0 / ntimes; + d2 = d * d; + d3 = d * d * d; + + /* construct a temporary matrix for determining the forward differencing deltas */ + tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; + tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; + tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; + tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; + + /* compose the basis and geometry matrices */ + + static const float CR_basis[4][4] = + { + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, + }; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); + } + } + /* compose the above results to get the deltas matrix */ + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); + } + } + + + /* extract the x deltas */ + x = deltas[0][0]; + dx = deltas[1][0]; + dx2 = deltas[2][0]; + dx3 = deltas[3][0]; + + /* extract the y deltas */ + y = deltas[0][1]; + dy = deltas[1][1]; + dy2 = deltas[2][1]; + dy3 = deltas[3][1]; + + + lastx = CLAMP (x, 0, xmax); + lasty = CLAMP (y, 0, ymax); + + p_heights[lastx] = lasty; + p_useds[lastx] = true; + + /* loop over the curve */ + for (i = 0; i < ntimes; i++) + { + /* increment the x values */ + x += dx; + dx += dx2; + dx2 += dx3; + + /* increment the y values */ + y += dy; + dy += dy2; + dy2 += dy3; + + newx = CLAMP ((Math::round (x)), 0, xmax); + newy = CLAMP ((Math::round (y)), 0, ymax); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) + { + p_useds[newx]=true; + p_heights[newx]=newy; + } + + lastx = newx; + lasty = newy; + } +} + + +void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code) { + + + const char *typestr[4]={"float","vec3","mat4","texture"}; +#define OUTNAME(id,slot) (String(typestr[get_node_output_slot_type(get_mode(),p_type,p_node->type,slot)])+" "+("nd"+itos(id)+"sl"+itos(slot))) +#define OUTVAR(id,slot) ("nd"+itos(id)+"sl"+itos(slot)) + + switch(p_node->type) { + + case NODE_INPUT: { + + + }break; + case NODE_SCALAR_CONST: { + + double scalar = p_node->param1; + code+=OUTNAME(p_node->id,0)+"="+rtos(scalar)+";\n"; + }break; + case NODE_VEC_CONST: { + Vector3 vec = p_node->param1; + code+=OUTNAME(p_node->id,0)+"=vec3("+rtos(vec.x)+","+rtos(vec.y)+","+rtos(vec.z)+");\n"; + }break; + case NODE_RGB_CONST: { + Color col = p_node->param1; + code+=OUTNAME(p_node->id,0)+"=vec3("+rtos(col.r)+","+rtos(col.g)+","+rtos(col.b)+");\n"; + code+=OUTNAME(p_node->id,1)+"="+rtos(col.a)+";\n"; + }break; + case NODE_XFORM_CONST: { + + Transform xf = p_node->param1; + code+=OUTNAME(p_node->id,0)+"=mat4(\n"; + code+="\tvec4(vec3("+rtos(xf.basis.get_axis(0).x)+","+rtos(xf.basis.get_axis(0).y)+","+rtos(xf.basis.get_axis(0).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(xf.basis.get_axis(1).x)+","+rtos(xf.basis.get_axis(1).y)+","+rtos(xf.basis.get_axis(1).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(xf.basis.get_axis(2).x)+","+rtos(xf.basis.get_axis(2).y)+","+rtos(xf.basis.get_axis(2).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(xf.origin.x)+","+rtos(xf.origin.y)+","+rtos(xf.origin.z)+"),1)\n"; + code+=");"; + + }break; + case NODE_TIME: { + code+=OUTNAME(p_node->id,0)+"=TIME;\n"; + }break; + case NODE_SCREEN_TEX: { + code+=OUTNAME(p_node->id,0)+"=texscreen("+p_inputs[0]+".xy);\n"; + }break; + case NODE_SCALAR_OP: { + int op = p_node->param1; + String optxt; + switch(op) { + + case SCALAR_OP_ADD: optxt = p_inputs[0]+"+"+p_inputs[1]+";"; break; + case SCALAR_OP_SUB: optxt = p_inputs[0]+"-"+p_inputs[1]+";"; break; + case SCALAR_OP_MUL: optxt = p_inputs[0]+"*"+p_inputs[1]+";"; break; + case SCALAR_OP_DIV: optxt = p_inputs[0]+"/"+p_inputs[1]+";"; break; + case SCALAR_OP_MOD: optxt = "mod("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_MAX: optxt = "max("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_MIN: optxt = "min("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_ATAN2: optxt = "atan2("+p_inputs[0]+","+p_inputs[1]+");"; break; + + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n";; + + }break; + case NODE_VEC_OP: { + int op = p_node->param1; + String optxt; + switch(op) { + case VEC_OP_ADD: optxt = p_inputs[0]+"+"+p_inputs[1]+";"; break; + case VEC_OP_SUB: optxt = p_inputs[0]+"-"+p_inputs[1]+";"; break; + case VEC_OP_MUL: optxt = p_inputs[0]+"*"+p_inputs[1]+";"; break; + case VEC_OP_DIV: optxt = p_inputs[0]+"/"+p_inputs[1]+";"; break; + case VEC_OP_MOD: optxt = "mod("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_MAX: optxt = "max("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_MIN: optxt = "min("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_CROSS: optxt = "cross("+p_inputs[0]+","+p_inputs[1]+");"; break; + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n"; + + }break; + case NODE_VEC_SCALAR_OP: { + int op = p_node->param1; + String optxt; + switch(op) { + case VEC_SCALAR_OP_MUL: optxt = p_inputs[0]+"*"+p_inputs[1]+";"; break; + case VEC_SCALAR_OP_DIV: optxt = p_inputs[0]+"/"+p_inputs[1]+";"; break; + case VEC_SCALAR_OP_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n"; + + }break; + case NODE_RGB_OP: { + + int op = p_node->param1; + static const char*axisn[3]={"x","y","z"}; + switch(op) { + case RGB_OP_SCREEN: { + + code += OUTNAME(p_node->id,0)+"=vec3(1.0)-(vec3(1.0)-"+p_inputs[0]+")*(vec3(1.0)-"+p_inputs[1]+");\n"; + } break; + case RGB_OP_DIFFERENCE: { + + code += OUTNAME(p_node->id,0)+"=abs("+p_inputs[0]+"-"+p_inputs[1]+");\n"; + + } break; + case RGB_OP_DARKEN: { + + code += OUTNAME(p_node->id,0)+"=min("+p_inputs[0]+","+p_inputs[1]+");\n"; + } break; + case RGB_OP_LIGHTEN: { + + code += OUTNAME(p_node->id,0)+"=max("+p_inputs[0]+","+p_inputs[1]+");\n"; + + } break; + case RGB_OP_OVERLAY: { + + code += OUTNAME(p_node->id,0)+";\n"; + for(int i=0;i<3;i++) { + code += "{\n"; + code += "\tfloat base="+p_inputs[0]+"."+axisn[i]+";\n"; + code += "\tfloat blend="+p_inputs[1]+"."+axisn[i]+";\n"; + code += "\tif (base < 0.5) {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = 2.0 * base * blend;\n"; + code += "\t} else {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base);\n"; + code += "\t}\n"; + code += "}\n"; + } + + } break; + case RGB_OP_DODGE: { + + code += OUTNAME(p_node->id,0)+"=("+p_inputs[0]+")/(vec3(1.0)-"+p_inputs[1]+");\n"; + + } break; + case RGB_OP_BURN: { + + code += OUTNAME(p_node->id,0)+"=vec3(1.0)-(vec3(1.0)-"+p_inputs[0]+")/("+p_inputs[1]+");\n"; + } break; + case RGB_OP_SOFT_LIGHT: { + + code += OUTNAME(p_node->id,0)+";\n"; + for(int i=0;i<3;i++) { + code += "{\n"; + code += "\tfloat base="+p_inputs[0]+"."+axisn[i]+";\n"; + code += "\tfloat blend="+p_inputs[1]+"."+axisn[i]+";\n"; + code += "\tif (base < 0.5) {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (base * (blend+0.5));\n"; + code += "\t} else {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (1 - (1-base) * (1-(blend-0.5)));\n"; + code += "\t}\n"; + code += "}\n"; + } + + } break; + case RGB_OP_HARD_LIGHT: { + + code += OUTNAME(p_node->id,0)+";\n"; + for(int i=0;i<3;i++) { + code += "{\n"; + code += "\tfloat base="+p_inputs[0]+"."+axisn[i]+";\n"; + code += "\tfloat blend="+p_inputs[1]+"."+axisn[i]+";\n"; + code += "\tif (base < 0.5) {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (base * (2*blend));\n"; + code += "\t} else {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (1 - (1-base) * (1-2*(blend-0.5)));\n"; + code += "\t}\n"; + code += "}\n"; + } + + } break; + } + }break; + case NODE_XFORM_MULT: { + + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+"*"+p_inputs[1]+";\n"; + + }break; + case NODE_XFORM_VEC_MULT: { + + bool no_translation = p_node->param1; + if (no_translation) { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[0]+"*vec4("+p_inputs[1]+",0)).xyz;\n"; + } else { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[0]+"*vec4("+p_inputs[1]+",1)).xyz;\n"; + } + + }break; + case NODE_XFORM_VEC_INV_MULT: { + bool no_translation = p_node->param1; + if (no_translation) { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[1]+"*vec4("+p_inputs[0]+",0)).xyz;\n"; + } else { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[1]+"*vec4("+p_inputs[0]+",1)).xyz;\n"; + } + }break; + case NODE_SCALAR_FUNC: { + static const char*scalar_func_id[SCALAR_MAX_FUNC]={ + "sin($)", + "cos($)", + "tan($)", + "asin($)", + "acos($)", + "atan($)", + "sinh($)", + "cosh($)", + "tanh($)", + "log($)", + "exp($)", + "sqrt($)", + "abs($)", + "sign($)", + "floor($)", + "round($)", + "ceil($)", + "frac($)", + "min(max($,0),1)", + "-($)", + }; + + int func = p_node->param1; + ERR_FAIL_INDEX(func,SCALAR_MAX_FUNC); + code += OUTNAME(p_node->id,0)+"="+String(scalar_func_id[func]).replace("$",p_inputs[0])+";\n"; + + } break; + case NODE_VEC_FUNC: { + static const char*vec_func_id[VEC_MAX_FUNC]={ + "normalize($)", + "max(min($,vec3(1,1,1)),vec3(0,0,0))", + "-($)", + "1.0/($)", + "", + "", + }; + + + int func = p_node->param1; + ERR_FAIL_INDEX(func,VEC_MAX_FUNC); + if (func==VEC_FUNC_RGB2HSV) { + code += OUTNAME(p_node->id,0)+";\n"; + code+="{\n"; + code+="\tvec3 c = "+p_inputs[0]+";\n"; + code+="\tvec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; + code+="\tvec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"; + code+="\tvec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; + code+="\tfloat d = q.x - min(q.w, q.y);\n"; + code+="\tfloat e = 1.0e-10;\n"; + code+="\t"+OUTVAR(p_node->id,0)+"=vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; + code+="}\n"; + } else if (func==VEC_FUNC_HSV2RGB) { + code += OUTNAME(p_node->id,0)+";\n";; + code+="{\n"; + code+="\tvec3 c = "+p_inputs[0]+";\n"; + code+="\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; + code+="\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; + code+="\t"+OUTVAR(p_node->id,0)+"=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; + code+="}\n"; + + } else { + code += OUTNAME(p_node->id,0)+"="+String(vec_func_id[func]).replace("$",p_inputs[0])+";\n"; + } + }break; + case NODE_VEC_LEN: { + + code += OUTNAME(p_node->id,0)+"=length("+p_inputs[1]+");\n"; + + }break; + case NODE_DOT_PROD: { + code += OUTNAME(p_node->id,0)+"=dot("+p_inputs[1]+","+p_inputs[0]+");\n"; + + }break; + case NODE_VEC_TO_SCALAR: { + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+".x;\n"; + code += OUTNAME(p_node->id,1)+"="+p_inputs[0]+".y;\n"; + code += OUTNAME(p_node->id,2)+"="+p_inputs[0]+".z;\n"; + + }break; + case NODE_SCALAR_TO_VEC: { + code += OUTNAME(p_node->id,0)+"=vec3("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+""+");\n"; + + }break; + case NODE_VEC_TO_XFORM: { + code += OUTNAME(p_node->id,0)+"=xform("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+","+","+p_inputs[3]+");\n"; + + }break; + case NODE_XFORM_TO_VEC: { + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+".x;\n"; + code += OUTNAME(p_node->id,1)+"="+p_inputs[0]+".y;\n"; + code += OUTNAME(p_node->id,2)+"="+p_inputs[0]+".z;\n"; + code += OUTNAME(p_node->id,3)+"="+p_inputs[0]+".o;\n"; + }break; + case NODE_SCALAR_INTERP: { + + code += OUTNAME(p_node->id,0)+"=mix("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+");\n"; + + }break; + case NODE_VEC_INTERP: { + code += OUTNAME(p_node->id,0)+"=mix("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+");\n"; + + }break; + case NODE_COLOR_RAMP: { + + static const int color_ramp_len=512; + DVector<uint8_t> cramp; + cramp.resize(color_ramp_len*4); + { + + DVector<Color> colors=p_node->param1; + DVector<real_t> offsets=p_node->param2; + int cc =colors.size(); + DVector<uint8_t>::Write crw = cramp.write(); + DVector<Color>::Read cr = colors.read(); + DVector<real_t>::Read ofr = offsets.read(); + + int at=0; + Color color_at(0,0,0,1); + for(int i=0;i<=cc;i++) { + + int pos; + Color to; + if (i==cc) { + if (at==color_ramp_len) + break; + pos=color_ramp_len; + to=Color(1,1,1,1); + } else { + to=cr[i]; + pos= MIN(ofr[i]*color_ramp_len,color_ramp_len); + } + for(int j=at;j<pos;j++) { + float t = (j-at)/float(pos-at); + Color c = color_at.linear_interpolate(to,t); + crw[j*4+0]=Math::fast_ftoi( CLAMP(c.r*255.0,0,255) ); + crw[j*4+1]=Math::fast_ftoi( CLAMP(c.g*255.0,0,255) ); + crw[j*4+2]=Math::fast_ftoi( CLAMP(c.b*255.0,0,255) ); + crw[j*4+3]=Math::fast_ftoi( CLAMP(c.a*255.0,0,255) ); + } + + at=pos; + color_at=to; + } + } + + Image gradient(color_ramp_len,1,0,Image::FORMAT_RGBA,cramp); + Ref<ImageTexture> it = memnew( ImageTexture ); + it->create_from_image(gradient,Texture::FLAG_FILTER|Texture::FLAG_MIPMAPS); + + String crampname= "cramp_"+itos(p_node->id); + set_default_texture_param(crampname,it); + + code +="uniform texture "+crampname+";\n"; + code +="vec4 "+crampname+"_r=tex("+crampname+",vec2("+p_inputs[0]+",0));\n"; + code += OUTNAME(p_node->id,0)+"="+crampname+"_r.rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+crampname+"_r.a;\n"; + + }break; + case NODE_CURVE_MAP: { + static const int curve_map_len=256; + bool mapped[256]; + zeromem(mapped,sizeof(mapped)); + DVector<uint8_t> cmap; + cmap.resize(curve_map_len); + { + + DVector<Point2> points=p_node->param1; + int pc =points.size(); + DVector<uint8_t>::Write cmw = cmap.write(); + DVector<Point2>::Read pr = points.read(); + + Vector2 prev=Vector2(0,0); + Vector2 prev2=Vector2(0,0); + + for(int i=-1;i<pc;i++) { + + Vector2 next; + Vector2 next2; + if (i+1>=pc) { + next=Vector2(1,1); + } else { + next=Vector2(pr[i+1].x,pr[i+1].y); + } + + if (i+2>=pc) { + next2=Vector2(1,1); + } else { + next2=Vector2(pr[i+2].x,pr[i+2].y); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2,prev,next,next2,cmw.ptr(),mapped); + + prev2=prev; + prev=next; + } + + uint8_t pp=0; + for(int i=0;i<curve_map_len;i++) { + + if (!mapped[i]) { + cmw[i]=pp; + } else { + pp=cmw[i]; + } + } + } + + + + Image gradient(curve_map_len,1,0,Image::FORMAT_GRAYSCALE,cmap); + Ref<ImageTexture> it = memnew( ImageTexture ); + it->create_from_image(gradient,Texture::FLAG_FILTER|Texture::FLAG_MIPMAPS); + + String cmapname= "cmap_"+itos(p_node->id); + set_default_texture_param(cmapname,it); + + code +="uniform texture "+cmapname+";\n"; + code += OUTNAME(p_node->id,0)+"=tex("+cmapname+",vec2("+p_inputs[0]+",0)).r;\n"; + + }break; + case NODE_SCALAR_INPUT: { + String name = p_node->param1; + float dv=p_node->param2; + code +="uniform float "+name+"="+rtos(dv)+";\n"; + code += OUTNAME(p_node->id,0)+"="+name+";\n"; + }break; + case NODE_VEC_INPUT: { + + String name = p_node->param1; + Vector3 dv=p_node->param2; + code +="uniform float "+name+"=vec3("+rtos(dv.x)+","+rtos(dv.y)+","+rtos(dv.z)+");\n"; + code += OUTNAME(p_node->id,0)+"="+name+";\n"; + }break; + case NODE_RGB_INPUT: { + + String name = p_node->param1; + Color dv= p_node->param2; + + code +="uniform color "+name+"=vec4("+rtos(dv.r)+","+rtos(dv.g)+","+rtos(dv.g)+","+rtos(dv.a)+");\n"; + code += OUTNAME(p_node->id,0)+"="+name+".rgb;\n"; + + }break; + case NODE_XFORM_INPUT: { + + String name = p_node->param1; + Transform dv= p_node->param2; + + code +="uniform mat4 "+name+"=mat4(\n"; + code+="\tvec4(vec3("+rtos(dv.basis.get_axis(0).x)+","+rtos(dv.basis.get_axis(0).y)+","+rtos(dv.basis.get_axis(0).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(dv.basis.get_axis(1).x)+","+rtos(dv.basis.get_axis(1).y)+","+rtos(dv.basis.get_axis(1).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(dv.basis.get_axis(2).x)+","+rtos(dv.basis.get_axis(2).y)+","+rtos(dv.basis.get_axis(2).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(dv.origin.x)+","+rtos(dv.origin.y)+","+rtos(dv.origin.z)+"),1)\n"; + code+=");"; + + code += OUTNAME(p_node->id,0)+"="+name+";\n"; + + }break; + case NODE_TEXTURE_INPUT: { + String name = p_node->param1; + String rname="rt_read_tex"+itos(p_node->id); + code +="uniform texture "+name+";"; + code +="vec4 "+rname+"=tex("+name+","+p_inputs[0]+".xy);\n"; + code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; + + }break; + case NODE_CUBEMAP_INPUT: { + + String name = p_node->param1; + code +="uniform cubemap "+name+";"; + String rname="rt_read_tex"+itos(p_node->id); + code +="vec4 "+rname+"=texcube("+name+","+p_inputs[0]+".xy);\n"; + code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; + }break; + case NODE_DEFAULT_TEXTURE: { + + if (get_mode()==MODE_CANVAS_ITEM && p_type==SHADER_TYPE_FRAGMENT) { + + String rname="rt_default_tex"+itos(p_node->id); + code +="vec4 "+rname+"=tex(TEXTURE,"+p_inputs[0]+".xy);\n"; + code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; + + } else { + //not supported + code += OUTNAME(p_node->id,0)+"=vec3(0,0,0);\n"; + code += OUTNAME(p_node->id,1)+"=1.0;\n"; + + } + } break; + case NODE_OUTPUT: { + + + }break; + case NODE_COMMENT: { + + }break; + case NODE_TYPE_MAX: { + + } + } +} diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h index e20e010c6b..5c34bedadd 100644 --- a/scene/resources/shader_graph.h +++ b/scene/resources/shader_graph.h @@ -29,87 +29,57 @@ #ifndef SHADER_GRAPH_H #define SHADER_GRAPH_H -#if 0 + #include "map.h" #include "scene/resources/shader.h" -class ShaderGraph : public Resource { +class ShaderGraph : public Shader { - OBJ_TYPE( ShaderGraph, Resource ); + OBJ_TYPE( ShaderGraph, Shader ); RES_BASE_EXTENSION("sgp"); public: enum NodeType { - NODE_IN, ///< param 0: name - NODE_OUT, ///< param 0: name - NODE_CONSTANT, ///< param 0: value - NODE_PARAMETER, ///< param 0: name - NODE_ADD, - NODE_SUB, - NODE_MUL, - NODE_DIV, - NODE_MOD, - NODE_SIN, - NODE_COS, - NODE_TAN, - NODE_ARCSIN, - NODE_ARCCOS, - NODE_ARCTAN, - NODE_POW, - NODE_LOG, - NODE_MAX, - NODE_MIN, - NODE_COMPARE, - NODE_TEXTURE, ///< param 0: texture - NODE_TIME, ///< param 0: interval length - NODE_NOISE, - NODE_PASS, - NODE_VEC_IN, ///< param 0: name - NODE_VEC_OUT, ///< param 0: name - NODE_VEC_CONSTANT, ///< param 0: value - NODE_VEC_PARAMETER, ///< param 0: name - NODE_VEC_ADD, - NODE_VEC_SUB, - NODE_VEC_MUL, - NODE_VEC_DIV, - NODE_VEC_MOD, - NODE_VEC_CROSS, - NODE_VEC_DOT, - NODE_VEC_POW, - NODE_VEC_NORMALIZE, - NODE_VEC_INTERPOLATE, - NODE_VEC_SCREEN_TO_UV, - NODE_VEC_TRANSFORM3, - NODE_VEC_TRANSFORM4, - NODE_VEC_COMPARE, - NODE_VEC_TEXTURE_2D, - NODE_VEC_TEXTURE_CUBE, - NODE_VEC_NOISE, - NODE_VEC_0, - NODE_VEC_1, - NODE_VEC_2, - NODE_VEC_BUILD, - NODE_VEC_PASS, - NODE_COLOR_CONSTANT, - NODE_COLOR_PARAMETER, - NODE_TEXTURE_PARAMETER, - NODE_TEXTURE_2D_PARAMETER, - NODE_TEXTURE_CUBE_PARAMETER, - NODE_TRANSFORM_CONSTANT, - NODE_TRANSFORM_PARAMETER, - NODE_LABEL, + NODE_INPUT, // all inputs (shader type dependent) + NODE_SCALAR_CONST, //scalar constant + NODE_VEC_CONST, //vec3 constant + NODE_RGB_CONST, //rgb constant (shows a color picker instead) + NODE_XFORM_CONST, // 4x4 matrix constant + NODE_TIME, // time in seconds + NODE_SCREEN_TEX, // screen texture sampler (takes UV) (only usable in fragment shader) + NODE_SCALAR_OP, // scalar vs scalar op (mul, add, div, etc) + NODE_VEC_OP, // vec3 vs vec3 op (mul,ad,div,crossprod,etc) + NODE_VEC_SCALAR_OP, // vec3 vs scalar op (mul, add, div, etc) + NODE_RGB_OP, // vec3 vs vec3 rgb op (with scalar amount), like brighten, darken, burn, dodge, multiply, etc. + NODE_XFORM_MULT, // mat4 x mat4 + NODE_XFORM_VEC_MULT, // mat4 x vec3 mult (with no-translation option) + NODE_XFORM_VEC_INV_MULT, // mat4 x vec3 inverse mult (with no-translation option) + NODE_SCALAR_FUNC, // scalar function (sin, cos, etc) + NODE_VEC_FUNC, // vector function (normalize, negate, reciprocal, rgb2hsv, hsv2rgb, etc, etc) + NODE_VEC_LEN, // vec3 length + NODE_DOT_PROD, // vec3 . vec3 (dot product -> scalar output) + NODE_VEC_TO_SCALAR, // 1 vec3 input, 3 scalar outputs + NODE_SCALAR_TO_VEC, // 3 scalar input, 1 vec3 output + NODE_XFORM_TO_VEC, // 3 vec input, 1 xform output + NODE_VEC_TO_XFORM, // 3 vec input, 1 xform output + NODE_SCALAR_INTERP, // scalar interpolation (with optional curve) + NODE_VEC_INTERP, // vec3 interpolation (with optional curve) + NODE_COLOR_RAMP, //take scalar, output vec3 + NODE_CURVE_MAP, //take scalar, otput scalar + NODE_SCALAR_INPUT, // scalar uniform (assignable in material) + NODE_VEC_INPUT, // vec3 uniform (assignable in material) + NODE_RGB_INPUT, // color uniform (assignable in material) + NODE_XFORM_INPUT, // mat4 uniform (assignable in material) + NODE_TEXTURE_INPUT, // texture input (assignable in material) + NODE_CUBEMAP_INPUT, // cubemap input (assignable in material) + NODE_DEFAULT_TEXTURE, + NODE_OUTPUT, // output (shader type dependent) + NODE_COMMENT, // comment NODE_TYPE_MAX }; - enum ShaderType { - SHADER_VERTEX, - SHADER_FRAGMENT, - SHADER_LIGHT - }; - -private: struct Connection { @@ -119,70 +89,300 @@ private: int dst_slot; }; + enum SlotType { + + SLOT_TYPE_SCALAR, + SLOT_TYPE_VEC, + SLOT_TYPE_XFORM, + SLOT_TYPE_TEXTURE, + SLOT_MAX + }; + + enum ShaderType { + SHADER_TYPE_VERTEX, + SHADER_TYPE_FRAGMENT, + SHADER_TYPE_LIGHT, + SHADER_TYPE_MAX + }; + + enum SlotDir { + SLOT_IN, + SLOT_OUT + }; + + enum GraphError { + GRAPH_OK, + GRAPH_ERROR_CYCLIC, + GRAPH_ERROR_MISSING_CONNECTIONS + }; + +private: + + String _find_unique_name(const String& p_base); + + struct SourceSlot { + + int id; + int slot; + bool operator==(const SourceSlot& p_slot) const { + return id==p_slot.id && slot==p_slot.slot; + } + }; + struct Node { - int16_t x,y; + Vector2 pos; NodeType type; - Variant param; + Variant param1; + Variant param2; int id; mutable int order; // used for sorting - mutable bool out_valid; - mutable bool in_valid; + int sort_order; + Map<int,SourceSlot> connections; + }; struct ShaderData { Map<int,Node> node_map; - List<Connection> connections; + GraphError error; } shader[3]; - uint64_t version; -protected: -/* bool _set(const StringName& p_name, const Variant& p_value); - bool _get(const StringName& p_name,Variant &r_ret) const; - void _get_property_list( List<PropertyInfo> *p_list) const;*/ - static void _bind_methods(); + struct InOutParamInfo { + Mode shader_mode; + ShaderType shader_type; + const char *name; + const char *variable; + const char *postfix; + SlotType slot_type; + SlotDir dir; + }; + + static const InOutParamInfo inout_param_info[]; + + struct NodeSlotInfo { + + enum { MAX_INS=3, MAX_OUTS=3 }; + NodeType type; + const SlotType ins[MAX_INS]; + const SlotType outs[MAX_OUTS]; + }; + + static const NodeSlotInfo node_slot_info[]; - Array _get_connections_helper() const; + bool _pending_update_shader; + void _update_shader(); + void _request_update(); + + void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d,uint8_t* p_heights,bool *p_useds); + void _add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code); + + Array _get_node_list(ShaderType p_type) const; + Array _get_connections(ShaderType p_type) const; + + void _set_data(const Dictionary& p_data); + Dictionary _get_data() const; +protected: + + static void _bind_methods(); public: - void node_add(ShaderType p_which, NodeType p_type,int p_id); + void node_add(ShaderType p_type, NodeType p_node_type, int p_id); void node_remove(ShaderType p_which,int p_id); - void node_set_param(ShaderType p_which, int p_id, const Variant& p_value); void node_set_pos(ShaderType p_which,int p_id,const Point2& p_pos); - void node_change_type(ShaderType p_which,int p_id, NodeType p_type); Point2 node_get_pos(ShaderType p_which,int p_id) const; void get_node_list(ShaderType p_which,List<int> *p_node_list) const; NodeType node_get_type(ShaderType p_which,int p_id) const; - Variant node_get_param(ShaderType p_which,int p_id) const; - Error connect(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); - bool is_connected(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const; - void disconnect(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); + void scalar_const_node_set_value(ShaderType p_which,int p_id,float p_value); + float scalar_const_node_get_value(ShaderType p_which,int p_id) const; - void get_connections(ShaderType p_which,List<Connection> *p_connections) const; + void vec_const_node_set_value(ShaderType p_which,int p_id,const Vector3& p_value); + Vector3 vec_const_node_get_value(ShaderType p_which,int p_id) const; - void clear(); + void rgb_const_node_set_value(ShaderType p_which,int p_id,const Color& p_value); + Color rgb_const_node_get_value(ShaderType p_which,int p_id) const; - uint64_t get_version() const { return version; } + void xform_const_node_set_value(ShaderType p_which,int p_id,const Transform& p_value); + Transform xform_const_node_get_value(ShaderType p_which,int p_id) const; - static void get_default_input_nodes(Mode p_type,List<PropertyInfo> *p_inputs); - static void get_default_output_nodes(Mode p_type,List<PropertyInfo> *p_outputs); + void texture_node_set_filter_size(ShaderType p_which,int p_id,int p_size); + int texture_node_get_filter_size(ShaderType p_which,int p_id) const; - static PropertyInfo node_get_type_info(NodeType p_type); - static int get_input_count(NodeType p_type); - static int get_output_count(NodeType p_type); - static String get_input_name(NodeType p_type,int p_input); - static String get_output_name(NodeType p_type,int p_output); - static bool is_input_vector(NodeType p_type,int p_input); - static bool is_output_vector(NodeType p_type,int p_input); + void texture_node_set_filter_strength(ShaderType p_which,float p_id,float p_strength); + float texture_node_get_filter_strength(ShaderType p_which,float p_id) const; + enum ScalarOp { + SCALAR_OP_ADD, + SCALAR_OP_SUB, + SCALAR_OP_MUL, + SCALAR_OP_DIV, + SCALAR_OP_MOD, + SCALAR_OP_POW, + SCALAR_OP_MAX, + SCALAR_OP_MIN, + SCALAR_OP_ATAN2, + SCALAR_MAX_OP + }; + + void scalar_op_node_set_op(ShaderType p_which,float p_id,ScalarOp p_op); + ScalarOp scalar_op_node_get_op(ShaderType p_which,float p_id) const; + + enum VecOp { + VEC_OP_ADD, + VEC_OP_SUB, + VEC_OP_MUL, + VEC_OP_DIV, + VEC_OP_MOD, + VEC_OP_POW, + VEC_OP_MAX, + VEC_OP_MIN, + VEC_OP_CROSS, + VEC_MAX_OP + }; + + void vec_op_node_set_op(ShaderType p_which,float p_id,VecOp p_op); + VecOp vec_op_node_get_op(ShaderType p_which,float p_id) const; + + enum VecScalarOp { + VEC_SCALAR_OP_MUL, + VEC_SCALAR_OP_DIV, + VEC_SCALAR_OP_POW, + VEC_SCALAR_MAX_OP + }; + + void vec_scalar_op_node_set_op(ShaderType p_which,float p_id,VecScalarOp p_op); + VecScalarOp vec_scalar_op_node_get_op(ShaderType p_which,float p_id) const; + + enum RGBOp { + RGB_OP_SCREEN, + RGB_OP_DIFFERENCE, + RGB_OP_DARKEN, + RGB_OP_LIGHTEN, + RGB_OP_OVERLAY, + RGB_OP_DODGE, + RGB_OP_BURN, + RGB_OP_SOFT_LIGHT, + RGB_OP_HARD_LIGHT, + RGB_MAX_OP + }; - ShaderGraph(); + void rgb_op_node_set_op(ShaderType p_which,float p_id,RGBOp p_op); + RGBOp rgb_op_node_get_op(ShaderType p_which,float p_id) const; + + void xform_vec_mult_node_set_no_translation(ShaderType p_which,int p_id,bool p_no_translation); + bool xform_vec_mult_node_get_no_translation(ShaderType p_which,int p_id) const; + + enum ScalarFunc { + SCALAR_FUNC_SIN, + SCALAR_FUNC_COS, + SCALAR_FUNC_TAN, + SCALAR_FUNC_ASIN, + SCALAR_FUNC_ACOS, + SCALAR_FUNC_ATAN, + SCALAR_FUNC_SINH, + SCALAR_FUNC_COSH, + SCALAR_FUNC_TANH, + SCALAR_FUNC_LOG, + SCALAR_FUNC_EXP, + SCALAR_FUNC_SQRT, + SCALAR_FUNC_ABS, + SCALAR_FUNC_SIGN, + SCALAR_FUNC_FLOOR, + SCALAR_FUNC_ROUND, + SCALAR_FUNC_CEIL, + SCALAR_FUNC_FRAC, + SCALAR_FUNC_SATURATE, + SCALAR_FUNC_NEGATE, + SCALAR_MAX_FUNC + }; + + void scalar_func_node_set_function(ShaderType p_which,int p_id,ScalarFunc p_func); + ScalarFunc scalar_func_node_get_function(ShaderType p_which,int p_id) const; + + enum VecFunc { + VEC_FUNC_NORMALIZE, + VEC_FUNC_SATURATE, + VEC_FUNC_NEGATE, + VEC_FUNC_RECIPROCAL, + VEC_FUNC_RGB2HSV, + VEC_FUNC_HSV2RGB, + VEC_MAX_FUNC + }; + + void vec_func_node_set_function(ShaderType p_which,int p_id,VecFunc p_func); + VecFunc vec_func_node_get_function(ShaderType p_which,int p_id) const; + + void color_ramp_node_set_ramp(ShaderType p_which,int p_id,const DVector<Color>& p_colors, const DVector<real_t>& p_offsets); + DVector<Color> color_ramp_node_get_colors(ShaderType p_which,int p_id) const; + DVector<real_t> color_ramp_node_get_offsets(ShaderType p_which,int p_id) const; + + void curve_map_node_set_points(ShaderType p_which, int p_id, const DVector<Vector2>& p_points); + DVector<Vector2> curve_map_node_get_points(ShaderType p_which,int p_id) const; + + void input_node_set_name(ShaderType p_which,int p_id,const String& p_name); + String input_node_get_name(ShaderType p_which,int p_id); + + void scalar_input_node_set_value(ShaderType p_which,int p_id,float p_value); + float scalar_input_node_get_value(ShaderType p_which,int p_id) const; + + void vec_input_node_set_value(ShaderType p_which,int p_id,const Vector3& p_value); + Vector3 vec_input_node_get_value(ShaderType p_which,int p_id) const; + + void rgb_input_node_set_value(ShaderType p_which,int p_id,const Color& p_value); + Color rgb_input_node_get_value(ShaderType p_which,int p_id) const; + + void xform_input_node_set_value(ShaderType p_which,int p_id,const Transform& p_value); + Transform xform_input_node_get_value(ShaderType p_which,int p_id) const; + + void texture_input_node_set_value(ShaderType p_which,int p_id,const Ref<Texture>& p_texture); + Ref<Texture> texture_input_node_get_value(ShaderType p_which,int p_id) const; + + void cubemap_input_node_set_value(ShaderType p_which,int p_id,const Ref<CubeMap>& p_cubemap); + Ref<CubeMap> cubemap_input_node_get_value(ShaderType p_which,int p_id) const; + + void comment_node_set_text(ShaderType p_which,int p_id,const String& p_comment); + String comment_node_get_text(ShaderType p_which,int p_id) const; + + Error connect_node(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); + bool is_node_connected(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const; + void disconnect_node(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); + + void get_node_connections(ShaderType p_which,List<Connection> *p_connections) const; + + void clear(ShaderType p_which); + + Variant node_get_state(ShaderType p_type, int p_node) const; + void node_set_state(ShaderType p_type, int p_id, const Variant& p_state); + + GraphError get_graph_error(ShaderType p_type) const; + + static int get_type_input_count(NodeType p_type); + static int get_type_output_count(NodeType p_type); + static SlotType get_type_input_type(NodeType p_type,int p_idx); + static SlotType get_type_output_type(NodeType p_type,int p_idx); + static bool is_type_valid(Mode p_mode,ShaderType p_type); + + + struct SlotInfo { + String name; + SlotType type; + SlotDir dir; + }; + + static void get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List<SlotInfo> *r_slots); + + static int get_node_input_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type); + static int get_node_output_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type); + static SlotType get_node_input_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx); + static SlotType get_node_output_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx); + + + ShaderGraph(Mode p_mode); ~ShaderGraph(); }; @@ -192,6 +392,40 @@ public: VARIANT_ENUM_CAST( ShaderGraph::NodeType ); +VARIANT_ENUM_CAST( ShaderGraph::ShaderType ); +VARIANT_ENUM_CAST( ShaderGraph::SlotType ); +VARIANT_ENUM_CAST( ShaderGraph::ScalarOp ); +VARIANT_ENUM_CAST( ShaderGraph::VecOp ); +VARIANT_ENUM_CAST( ShaderGraph::VecScalarOp ); +VARIANT_ENUM_CAST( ShaderGraph::RGBOp ); +VARIANT_ENUM_CAST( ShaderGraph::ScalarFunc ); +VARIANT_ENUM_CAST( ShaderGraph::VecFunc ); +VARIANT_ENUM_CAST( ShaderGraph::GraphError ); + + +class MaterialShaderGraph : public ShaderGraph { + + OBJ_TYPE( MaterialShaderGraph, ShaderGraph ); + +public: + + + MaterialShaderGraph() : ShaderGraph(MODE_MATERIAL) { + + } +}; + +class CanvasItemShaderGraph : public ShaderGraph { + + OBJ_TYPE( CanvasItemShaderGraph, ShaderGraph ); + +public: + + + CanvasItemShaderGraph() : ShaderGraph(MODE_CANVAS_ITEM) { + + } +}; + -#endif #endif // SHADER_GRAPH_H diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index ca891920da..738b642d43 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -109,7 +109,7 @@ void Shape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide); ObjectTypeDB::bind_method(_MD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion); ObjectTypeDB::bind_method(_MD("collide_and_get_contacts:var","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts); - ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_and_get_contacts); + ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion_and_get_contacts); ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_solver_bias",PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_custom_solver_bias"),_SCS("get_custom_solver_bias")); } diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 316b5e91eb..ca4bd3d253 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -85,6 +85,12 @@ void StyleBox::_bind_methods() { ObjectTypeDB::bind_method(_MD("draw"),&StyleBox::draw); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/left", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_LEFT ); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/right", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_RIGHT ); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/top", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_TOP); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/bottom", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_BOTTOM ); + + } StyleBox::StyleBox() { diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index dd39205932..113fd8209d 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -650,8 +650,8 @@ void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fv Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); Vector2 v = varr[iFace*3+iVert]->get().uv; fvTexcOut[0]=v.x; - //fvTexcOut[1]=v.y; - fvTexcOut[1]=1.0-v.y; + fvTexcOut[1]=v.y; + //fvTexcOut[1]=1.0-v.y; } void SurfaceTool::mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert){ diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index dae055890b..8d3cbadd06 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -38,19 +38,19 @@ Size2 Texture::get_size() const { } -void Texture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const { +void Texture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, get_size()),get_rid(),false,p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, get_size()),get_rid(),false,p_modulate,p_transpose); } -void Texture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const { +void Texture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,get_rid(),p_tile,p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,get_rid(),p_tile,p_modulate,p_transpose); } -void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const{ +void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const{ - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate,p_transpose); } bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const { @@ -70,9 +70,9 @@ void Texture::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_alpha"),&Texture::has_alpha); ObjectTypeDB::bind_method(_MD("set_flags","flags"),&Texture::set_flags); ObjectTypeDB::bind_method(_MD("get_flags"),&Texture::get_flags); - ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate"),&Texture::draw,DEFVAL(Color(1,1,1))); - ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate"),&Texture::draw_rect,DEFVAL(Color(1,1,1))); - ObjectTypeDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1))); + ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false)); BIND_CONSTANT( FLAG_MIPMAPS ); BIND_CONSTANT( FLAG_REPEAT ); @@ -321,34 +321,40 @@ void ImageTexture::premultiply_alpha() { } } +void ImageTexture::normal_to_xy() { + + Image img = get_data(); + img.normalmap_to_xy(); + create_from_image(img,flags); +} + bool ImageTexture::has_alpha() const { return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA ); } -void ImageTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const { +void ImageTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { if ((w|h)==0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate,p_transpose); } -void ImageTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const { +void ImageTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { if ((w|h)==0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate,p_transpose); } -void ImageTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const{ +void ImageTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const{ if ((w|h)==0) return; - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate); + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate,p_transpose); } - void ImageTexture::set_size_override(const Size2& p_size) { Size2 s=p_size; @@ -406,9 +412,11 @@ void ImageTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality); ObjectTypeDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges); ObjectTypeDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha); + ObjectTypeDB::bind_method(_MD("normal_to_xy"),&ImageTexture::normal_to_xy); ObjectTypeDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::set_method_flags(get_type_static(),_SCS("normal_to_xy"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook); @@ -546,7 +554,7 @@ void AtlasTexture::_bind_methods() { -void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const { +void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { Rect2 rc=region; @@ -561,10 +569,10 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_m rc.size.height=atlas->get_height(); } - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,Rect2(p_pos+margin.pos,rc.size),atlas->get_rid(),rc,p_modulate); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,Rect2(p_pos+margin.pos,rc.size),atlas->get_rid(),rc,p_modulate,p_transpose); } -void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const { +void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { Rect2 rc=region; @@ -582,10 +590,10 @@ void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile, Vector2 scale = p_rect.size / (region.size+margin.size); Rect2 dr( p_rect.pos+margin.pos*scale,rc.size*scale ); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),rc,p_modulate); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),rc,p_modulate,p_transpose); } -void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const { +void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const { //this might not necesarily work well if using a rect, needs to be fixed properly Rect2 rc=region; @@ -615,7 +623,7 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const } Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale ); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate); + VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate,p_transpose); } bool AtlasTexture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const { @@ -801,15 +809,16 @@ void LargeTexture::_bind_methods() { -void LargeTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const { +void LargeTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { for(int i=0;i<pieces.size();i++) { - pieces[i].texture->draw(p_canvas_item,pieces[i].offset+p_pos,p_modulate); + // TODO + pieces[i].texture->draw(p_canvas_item,pieces[i].offset+p_pos,p_modulate,p_transpose); } } -void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const { +void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { //tiling not supported for this if (size.x==0 || size.y==0) @@ -819,11 +828,11 @@ void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile, for(int i=0;i<pieces.size();i++) { - pieces[i].texture->draw_rect(p_canvas_item,Rect2(pieces[i].offset*scale+p_rect.pos,pieces[i].texture->get_size()*scale),false,p_modulate); + // TODO + pieces[i].texture->draw_rect(p_canvas_item,Rect2(pieces[i].offset*scale+p_rect.pos,pieces[i].texture->get_size()*scale),false,p_modulate,p_transpose); } - } -void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const { +void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const { //tiling not supported for this @@ -834,6 +843,7 @@ void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const for(int i=0;i<pieces.size();i++) { + // TODO Rect2 rect( pieces[i].offset, pieces[i].texture->get_size()); if (!p_src_rect.intersects(rect)) continue; @@ -842,7 +852,7 @@ void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const target.size*=scale; target.pos=p_rect.pos+(p_src_rect.pos+rect.pos)*scale; local.pos-=rect.pos; - pieces[i].texture->draw_rect_region(p_canvas_item,target,local,p_modulate); + pieces[i].texture->draw_rect_region(p_canvas_item,target,local,p_modulate,p_transpose); } } @@ -935,21 +945,21 @@ float CubeMap::get_lossy_storage_quality() const { bool CubeMap::_set(const StringName& p_name, const Variant& p_value) { - if (p_name=="side/left") + if (p_name=="side/left") { set_side(SIDE_LEFT,p_value); - if (p_name=="side/right") + } else if (p_name=="side/right") { set_side(SIDE_RIGHT,p_value); - if (p_name=="side/bottom") + } else if (p_name=="side/bottom") { set_side(SIDE_BOTTOM,p_value); - if (p_name=="side/top") + } else if (p_name=="side/top") { set_side(SIDE_TOP,p_value); - if (p_name=="side/front") + } else if (p_name=="side/front") { set_side(SIDE_FRONT,p_value); - if (p_name=="side/back") + } else if (p_name=="side/back") { set_side(SIDE_BACK,p_value); - else if (p_name=="flags") + } else if (p_name=="flags") { set_flags(p_value); - else if (p_name=="storage") { + } else if (p_name=="storage") { storage=Storage(p_value.operator int()); } else if (p_name=="lossy_quality") { lossy_storage_quality=p_value; @@ -962,25 +972,25 @@ bool CubeMap::_set(const StringName& p_name, const Variant& p_value) { bool CubeMap::_get(const StringName& p_name,Variant &r_ret) const { - if (p_name=="side/left") + if (p_name=="side/left") { r_ret=get_side(SIDE_LEFT); - if (p_name=="side/right") + } else if (p_name=="side/right") { r_ret=get_side(SIDE_RIGHT); - if (p_name=="side/bottom") + } else if (p_name=="side/bottom") { r_ret=get_side(SIDE_BOTTOM); - if (p_name=="side/top") + } else if (p_name=="side/top") { r_ret=get_side(SIDE_TOP); - if (p_name=="side/front") + } else if (p_name=="side/front") { r_ret=get_side(SIDE_FRONT); - if (p_name=="side/back") + } else if (p_name=="side/back") { r_ret=get_side(SIDE_BACK); - else if (p_name=="flags") + } else if (p_name=="flags") { r_ret= flags; - else if (p_name=="storage") + } else if (p_name=="storage") { r_ret= storage; - else if (p_name=="lossy_quality") + } else if (p_name=="lossy_quality") { r_ret= lossy_storage_quality; - else + } else return false; return true; diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 4bb2f6d979..e853a4b05f 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -69,9 +69,9 @@ public: virtual void set_flags(uint32_t p_flags)=0; virtual uint32_t get_flags() const=0; - virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const; + virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const; @@ -135,10 +135,9 @@ public: virtual RID get_rid() const; bool has_alpha() const; - virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const; - + virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; void set_storage(Storage p_storage); Storage get_storage() const; @@ -147,6 +146,8 @@ public: void fix_alpha_edges(); void premultiply_alpha(); + void normal_to_xy(); + void set_size_override(const Size2& p_size); @@ -191,9 +192,9 @@ public: void set_margin(const Rect2& p_margin); Rect2 get_margin() const ; - virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const; + virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const; @@ -241,9 +242,9 @@ public: Vector2 get_piece_offset(int p_idx) const; Ref<Texture> get_piece_texture(int p_idx) const; - virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const; - virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const; + virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; LargeTexture(); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 208ba5bb66..338804e0e1 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -46,6 +46,8 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) { tile_set_texture(id,p_value); else if (what=="tex_offset") tile_set_texture_offset(id,p_value); + else if (what=="material") + tile_set_material(id,p_value); else if (what=="shape_offset") tile_set_shape_offset(id,p_value); else if (what=="region") @@ -54,6 +56,14 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) { tile_set_shape(id,p_value); else if (what=="shapes") _tile_set_shapes(id,p_value); + else if (what=="occluder") + tile_set_light_occluder(id,p_value); + else if (what=="occluder_offset") + tile_set_occluder_offset(id,p_value); + else if (what=="navigation") + tile_set_navigation_polygon(id,p_value); + else if (what=="navigation_offset") + tile_set_navigation_polygon_offset(id,p_value); else return false; @@ -79,6 +89,8 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{ r_ret=tile_get_texture(id); else if (what=="tex_offset") r_ret=tile_get_texture_offset(id); + else if (what=="material") + r_ret=tile_get_material(id); else if (what=="shape_offset") r_ret=tile_get_shape_offset(id); else if (what=="region") @@ -87,6 +99,14 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{ r_ret=tile_get_shape(id); else if (what=="shapes") r_ret=_tile_get_shapes(id); + else if (what=="occluder") + r_ret=tile_get_light_occluder(id); + else if (what=="occluder_offset") + r_ret=tile_get_occluder_offset(id); + else if (what=="navigation") + r_ret=tile_get_navigation_polygon(id); + else if (what=="navigation_offset") + r_ret=tile_get_navigation_polygon_offset(id); else return false; @@ -103,8 +123,13 @@ void TileSet::_get_property_list( List<PropertyInfo> *p_list) const{ p_list->push_back(PropertyInfo(Variant::STRING,pre+"name")); p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture")); p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"tex_offset")); - p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"material",PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemMaterial")); p_list->push_back(PropertyInfo(Variant::RECT2,pre+"region")); + p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"occluder_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D")); + p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"navigation_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"navigation",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon")); + p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset")); p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_EDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY,pre+"shapes",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); } @@ -134,6 +159,22 @@ Ref<Texture> TileSet::tile_get_texture(int p_id) const { } + +void TileSet::tile_set_material(int p_id,const Ref<CanvasItemMaterial> &p_material) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].material=p_material; + emit_changed(); + +} + +Ref<CanvasItemMaterial> TileSet::tile_get_material(int p_id) const{ + + ERR_FAIL_COND_V(!tile_map.has(p_id),Ref<CanvasItemMaterial>()); + return tile_map[p_id].material; +} + + void TileSet::tile_set_texture_offset(int p_id,const Vector2 &p_offset) { ERR_FAIL_COND(!tile_map.has(p_id)); @@ -210,6 +251,58 @@ Ref<Shape2D> TileSet::tile_get_shape(int p_id) const { } +void TileSet::tile_set_light_occluder(int p_id,const Ref<OccluderPolygon2D> &p_light_occluder) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].occluder=p_light_occluder; + +} + +Ref<OccluderPolygon2D> TileSet::tile_get_light_occluder(int p_id) const{ + + ERR_FAIL_COND_V(!tile_map.has(p_id),Ref<OccluderPolygon2D>()); + return tile_map[p_id].occluder; + +} + +void TileSet::tile_set_navigation_polygon_offset(int p_id,const Vector2& p_offset) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].navigation_polygon_offset=p_offset; + +} + +Vector2 TileSet::tile_get_navigation_polygon_offset(int p_id) const{ + ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2()); + return tile_map[p_id].navigation_polygon_offset; +} + +void TileSet::tile_set_navigation_polygon(int p_id,const Ref<NavigationPolygon> &p_navigation_polygon) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].navigation_polygon=p_navigation_polygon; + +} + +Ref<NavigationPolygon> TileSet::tile_get_navigation_polygon(int p_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id),Ref<NavigationPolygon>()); + return tile_map[p_id].navigation_polygon; + +} + +void TileSet::tile_set_occluder_offset(int p_id,const Vector2& p_offset) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].occluder_offset=p_offset; + +} + +Vector2 TileSet::tile_get_occluder_offset(int p_id) const{ + ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2()); + return tile_map[p_id].occluder_offset; +} + void TileSet::tile_set_shapes(int p_id,const Vector<Ref<Shape2D> > &p_shapes) { ERR_FAIL_COND(!tile_map.has(p_id)); @@ -319,6 +412,8 @@ void TileSet::_bind_methods() { ObjectTypeDB::bind_method(_MD("tile_get_name","id"),&TileSet::tile_get_name); ObjectTypeDB::bind_method(_MD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture); ObjectTypeDB::bind_method(_MD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture); + ObjectTypeDB::bind_method(_MD("tile_set_material","id","material:CanvasItemMaterial"),&TileSet::tile_set_material); + ObjectTypeDB::bind_method(_MD("tile_get_material:CanvasItemMaterial","id"),&TileSet::tile_get_material); ObjectTypeDB::bind_method(_MD("tile_set_texture_offset","id","texture_offset"),&TileSet::tile_set_texture_offset); ObjectTypeDB::bind_method(_MD("tile_get_texture_offset","id"),&TileSet::tile_get_texture_offset); ObjectTypeDB::bind_method(_MD("tile_set_shape_offset","id","shape_offset"),&TileSet::tile_set_shape_offset); @@ -329,6 +424,15 @@ void TileSet::_bind_methods() { ObjectTypeDB::bind_method(_MD("tile_get_shape:Shape2D","id"),&TileSet::tile_get_shape); ObjectTypeDB::bind_method(_MD("tile_set_shapes","id","shapes"),&TileSet::_tile_set_shapes); ObjectTypeDB::bind_method(_MD("tile_get_shapes","id"),&TileSet::_tile_get_shapes); + ObjectTypeDB::bind_method(_MD("tile_set_navigation_polygon","id","navigation_polygon:NavigationPolygon"),&TileSet::tile_set_navigation_polygon); + ObjectTypeDB::bind_method(_MD("tile_get_navigation_polygon:NavigationPolygon","id"),&TileSet::tile_get_navigation_polygon); + ObjectTypeDB::bind_method(_MD("tile_set_navigation_polygon_offset","id","navigation_polygon_offset"),&TileSet::tile_set_navigation_polygon_offset); + ObjectTypeDB::bind_method(_MD("tile_get_navigation_polygon_offset","id"),&TileSet::tile_get_navigation_polygon_offset); + ObjectTypeDB::bind_method(_MD("tile_set_light_occluder","id","light_occluder:OccluderPolygon2D"),&TileSet::tile_set_light_occluder); + ObjectTypeDB::bind_method(_MD("tile_get_light_occluder:OccluderPolygon2D","id"),&TileSet::tile_get_light_occluder); + ObjectTypeDB::bind_method(_MD("tile_set_occluder_offset","id","occluder_offset"),&TileSet::tile_set_occluder_offset); + ObjectTypeDB::bind_method(_MD("tile_get_occluder_offset","id"),&TileSet::tile_get_occluder_offset); + ObjectTypeDB::bind_method(_MD("remove_tile","id"),&TileSet::remove_tile); ObjectTypeDB::bind_method(_MD("clear"),&TileSet::clear); ObjectTypeDB::bind_method(_MD("get_last_unused_tile_id"),&TileSet::get_last_unused_tile_id); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index ddbb1b59a6..0234755a53 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -32,6 +32,8 @@ #include "resource.h" #include "scene/resources/shape_2d.h" #include "scene/resources/texture.h" +#include "scene/2d/light_occluder_2d.h" +#include "scene/2d/navigation_polygon.h" class TileSet : public Resource { @@ -45,6 +47,11 @@ class TileSet : public Resource { Vector2 shape_offset; Rect2i region; Vector<Ref<Shape2D> > shapes; + Vector2 occluder_offset; + Ref<OccluderPolygon2D> occluder; + Vector2 navigation_polygon_offset; + Ref<NavigationPolygon> navigation_polygon; + Ref<CanvasItemMaterial> material; }; Map<int,Data> tile_map; @@ -84,6 +91,21 @@ public: void tile_set_shape(int p_id,const Ref<Shape2D> &p_shape); Ref<Shape2D> tile_get_shape(int p_id) const; + void tile_set_material(int p_id,const Ref<CanvasItemMaterial> &p_material); + Ref<CanvasItemMaterial> tile_get_material(int p_id) const; + + void tile_set_occluder_offset(int p_id,const Vector2& p_offset); + Vector2 tile_get_occluder_offset(int p_id) const; + + void tile_set_light_occluder(int p_id,const Ref<OccluderPolygon2D> &p_light_occluder); + Ref<OccluderPolygon2D> tile_get_light_occluder(int p_id) const; + + void tile_set_navigation_polygon_offset(int p_id,const Vector2& p_offset); + Vector2 tile_get_navigation_polygon_offset(int p_id) const; + + void tile_set_navigation_polygon(int p_id,const Ref<NavigationPolygon> &p_navigation_polygon); + Ref<NavigationPolygon> tile_get_navigation_polygon(int p_id) const; + void tile_set_shapes(int p_id,const Vector<Ref<Shape2D> > &p_shapes); Vector<Ref<Shape2D> > tile_get_shapes(int p_id) const; diff --git a/scene/resources/video_stream.cpp b/scene/resources/video_stream.cpp index fffe1ad7fa..2bbae37510 100644 --- a/scene/resources/video_stream.cpp +++ b/scene/resources/video_stream.cpp @@ -33,6 +33,7 @@ void VideoStream::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_pending_frame_count"),&VideoStream::get_pending_frame_count); ObjectTypeDB::bind_method(_MD("pop_frame"),&VideoStream::pop_frame); ObjectTypeDB::bind_method(_MD("peek_frame"),&VideoStream::peek_frame); + ObjectTypeDB::bind_method(_MD("set_audio_track","idx"),&VideoStream::set_audio_track); }; diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index eafacce159..18f0cc3d05 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -30,7 +30,7 @@ #define VIDEO_STREAM_H #include "audio_stream_resampled.h" - +#include "scene/resources/texture.h" class VideoStream : public Resource { @@ -59,9 +59,11 @@ public: virtual void seek_pos(float p_time)=0; virtual int get_pending_frame_count() const=0; - virtual Image pop_frame()=0; + virtual void pop_frame(Ref<ImageTexture> p_tex)=0; virtual Image peek_frame() const=0; + virtual void set_audio_track(int p_idx) =0; + virtual void update(float p_time)=0; VideoStream(); diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index 880a3a32e3..30cf58bdd8 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -307,6 +307,11 @@ Ref<Environment> World::get_environment() const { } +PhysicsDirectSpaceState *World::get_direct_space_state() { + + return PhysicsServer::get_singleton()->space_get_direct_state(space); +} + void World::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_space"),&World::get_space); @@ -314,6 +319,7 @@ void World::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_sound_space"),&World::get_sound_space); ObjectTypeDB::bind_method(_MD("set_environment","env:Environment"),&World::set_environment); ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&World::get_environment); + ObjectTypeDB::bind_method(_MD("get_direct_space_state:PhysicsDirectSpaceState"),&World::get_direct_space_state); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),_SCS("set_environment"),_SCS("get_environment")); } diff --git a/scene/resources/world.h b/scene/resources/world.h index 60b3b99ab0..b10cadd6e0 100644 --- a/scene/resources/world.h +++ b/scene/resources/world.h @@ -75,6 +75,8 @@ public: void set_environment(const Ref<Environment>& p_environment); Ref<Environment> get_environment() const; + PhysicsDirectSpaceState *get_direct_space_state(); + World(); ~World(); diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index aee7ddde00..43a7af4bfd 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -352,8 +352,17 @@ void World2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_canvas"),&World2D::get_canvas); ObjectTypeDB::bind_method(_MD("get_space"),&World2D::get_space); ObjectTypeDB::bind_method(_MD("get_sound_space"),&World2D::get_sound_space); + + ObjectTypeDB::bind_method(_MD("get_direct_space_state:Physics2DDirectSpaceState"),&World2D::get_direct_space_state); + +} + +Physics2DDirectSpaceState *World2D::get_direct_space_state() { + + return Physics2DServer::get_singleton()->space_get_direct_state(space); } + World2D::World2D() { canvas = VisualServer::get_singleton()->canvas_create(); @@ -364,12 +373,12 @@ World2D::World2D() { Physics2DServer::get_singleton()->space_set_active(space,true); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics_2d/default_gravity",98)); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics_2d/default_gravity_vector",Vector2(0,1))); - Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_DENSITY,GLOBAL_DEF("physics_2d/default_density",0.1)); + Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_LINEAR_DAMP,GLOBAL_DEF("physics_2d/default_density",0.1)); + Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_ANGULAR_DAMP,GLOBAL_DEF("physics_2d/default_density",1)); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS,1.0); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_MAX_SEPARATION,1.5); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION,0.3); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD,2); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO,20); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,0.2); indexer = memnew( SpatialIndexer2D ); diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index 3feb23495d..865ec28fe9 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -30,7 +30,7 @@ #define WORLD_2D_H #include "resource.h" - +#include "servers/physics_2d_server.h" class SpatialIndexer2D; class VisibilityNotifier2D; @@ -68,6 +68,8 @@ public: RID get_space(); RID get_sound_space(); + Physics2DDirectSpaceState *get_direct_space_state(); + World2D(); ~World2D(); }; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 1d99eb6d1f..76cb5929cf 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -41,8 +41,10 @@ SceneStringNames::SceneStringNames() { visibility_changed=StaticCString::create("visibility_changed"); input_event=StaticCString::create("input_event"); shader_shader=StaticCString::create("shader/shader"); - enter_scene=StaticCString::create("enter_scene"); - exit_scene=StaticCString::create("exit_scene"); + shader_unshaded=StaticCString::create("shader/unshaded"); + shading_mode=StaticCString::create("shader/shading_mode"); + enter_tree=StaticCString::create("enter_tree"); + exit_tree=StaticCString::create("exit_tree"); item_rect_changed=StaticCString::create("item_rect_changed"); size_flags_changed=StaticCString::create("size_flags_changed"); minimum_size_changed=StaticCString::create("minimum_size_changed"); @@ -63,10 +65,14 @@ SceneStringNames::SceneStringNames() { body_exit_shape = StaticCString::create("body_exit_shape"); body_exit = StaticCString::create("body_exit"); + area_enter_shape = StaticCString::create("area_enter_shape"); + area_exit_shape = StaticCString::create("area_exit_shape"); + idle=StaticCString::create("idle"); iteration=StaticCString::create("iteration"); update=StaticCString::create("update"); + updated=StaticCString::create("updated"); _get_gizmo_geometry=StaticCString::create("_get_gizmo_geometry"); _can_gizmo_scale=StaticCString::create("_can_gizmo_scale"); @@ -74,8 +80,8 @@ SceneStringNames::SceneStringNames() { _fixed_process=StaticCString::create("_fixed_process"); _process=StaticCString::create("_process"); - _enter_scene=StaticCString::create("_enter_scene"); - _exit_scene=StaticCString::create("_exit_scene"); + _enter_tree=StaticCString::create("_enter_tree"); + _exit_tree=StaticCString::create("_exit_tree"); _enter_world=StaticCString::create("_enter_world"); _exit_world=StaticCString::create("_exit_world"); _ready=StaticCString::create("_ready"); @@ -98,8 +104,11 @@ SceneStringNames::SceneStringNames() { enter_camera=StaticCString::create("enter_camera"); exit_camera=StaticCString::create("exit_camera"); - _body_enter_scene = StaticCString::create("_body_enter_scene"); - _body_exit_scene = StaticCString::create("_body_exit_scene"); + _body_enter_tree = StaticCString::create("_body_enter_tree"); + _body_exit_tree = StaticCString::create("_body_exit_tree"); + + _area_enter_tree = StaticCString::create("_area_enter_tree"); + _area_exit_tree = StaticCString::create("_area_exit_tree"); _input_event=StaticCString::create("_input_event"); @@ -147,4 +156,9 @@ SceneStringNames::SceneStringNames() { _mouse_enter=StaticCString::create("_mouse_enter"); _mouse_exit=StaticCString::create("_mouse_exit"); + _pressed=StaticCString::create("_pressed"); + _toggled=StaticCString::create("_toggled"); + + frame_changed=StaticCString::create("frame_changed"); + } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index dd4f8789c2..a69e8ba0b5 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -56,13 +56,16 @@ public: StringName _input_event; StringName item_rect_changed; StringName shader_shader; - StringName enter_scene; - StringName exit_scene; + StringName shader_unshaded; + StringName shading_mode; + StringName enter_tree; + StringName exit_tree; StringName size_flags_changed; StringName minimum_size_changed; StringName idle; StringName iteration; StringName update; + StringName updated; StringName line_separation; @@ -81,6 +84,10 @@ public: StringName body_exit_shape; StringName body_exit; + StringName area_enter_shape; + StringName area_exit_shape; + + StringName _get_gizmo_geometry; StringName _can_gizmo_scale; @@ -89,12 +96,15 @@ public: StringName _process; StringName _enter_world; StringName _exit_world; - StringName _enter_scene; - StringName _exit_scene; + StringName _enter_tree; + StringName _exit_tree; StringName _draw; StringName _input; StringName _ready; + StringName _pressed; + StringName _toggled; + StringName _update_scroll; StringName _update_xform; @@ -116,8 +126,11 @@ public: StringName enter_camera; StringName exit_camera; - StringName _body_enter_scene; - StringName _body_exit_scene; + StringName _body_enter_tree; + StringName _body_exit_tree; + + StringName _area_enter_tree; + StringName _area_exit_tree; StringName changed; StringName _shader_changed; @@ -155,6 +168,7 @@ public: StringName _mouse_enter; StringName _mouse_exit; + StringName frame_changed; }; diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp index f50813731e..55dde1b35b 100644 --- a/servers/audio/audio_server_sw.cpp +++ b/servers/audio/audio_server_sw.cpp @@ -332,6 +332,7 @@ void AudioServerSW::driver_process_chunk(int p_frames,int32_t *p_buffer) { void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) { + _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate()); //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE int todo=p_frames; while(todo) { @@ -795,6 +796,8 @@ void AudioServerSW::init() { mixer = memnew( AudioMixerSW( sample_manager, latency, AudioDriverSW::get_singleton()->get_mix_rate(),mix_chans,mixer_use_fx,mixer_interp,_mixer_callback,this ) ); mixer_step_usecs=mixer->get_step_usecs(); + _output_delay=0; + stream_volume=0.3; // start the audio driver if (AudioDriverSW::get_singleton()) @@ -911,6 +914,11 @@ float AudioServerSW::get_event_voice_global_volume_scale() const { return event_voice_volume_scale; } +double AudioServerSW::get_output_delay() const { + + return _output_delay; +} + double AudioServerSW::get_mix_time() const { return AudioDriverSW::get_singleton()->get_mix_time(); diff --git a/servers/audio/audio_server_sw.h b/servers/audio/audio_server_sw.h index d137c15633..d47c1b4b3f 100644 --- a/servers/audio/audio_server_sw.h +++ b/servers/audio/audio_server_sw.h @@ -92,6 +92,8 @@ class AudioServerSW : public AudioServer { float peak_left,peak_right; uint32_t max_peak; + double _output_delay; + VoiceRBSW voice_rb; bool exit_update_thread; @@ -206,6 +208,9 @@ public: virtual double get_mix_time() const; //useful for video -> audio sync + virtual double get_output_delay() const; + + AudioServerSW(SampleManagerSW *p_sample_manager); ~AudioServerSW(); diff --git a/servers/audio_server.h b/servers/audio_server.h index 85289de58a..511340678a 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -274,6 +274,7 @@ public: static AudioServer *get_singleton(); virtual double get_mix_time() const=0; //useful for video -> audio sync + virtual double get_output_delay() const=0; AudioServer(); virtual ~AudioServer(); diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index bca6a9fa72..5847b942fb 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -172,10 +172,57 @@ void BodyPairSW::validate_contacts() { } } + +bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) { + + + + Vector3 motion = p_A->get_linear_velocity()*p_step; + real_t mlen = motion.length(); + if (mlen<CMP_EPSILON) + return false; + + Vector3 mnormal = motion / mlen; + + real_t min,max; + p_A->get_shape(p_shape_A)->project_range(mnormal,p_xform_A,min,max); + bool fast_object = mlen > (max-min)*0.3; //going too fast in that direction + + if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis + return false; + } + + //cast a segment from support in motion normal, in the same direction of motion by motion length + //support is the worst case collision point, so real collision happened before + int a; + Vector3 s=p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform(mnormal).normalized()); + Vector3 from = p_xform_A.xform(s); + Vector3 to = from + motion; + + Transform from_inv = p_xform_B.affine_inverse(); + + Vector3 local_from = from_inv.xform(from-mnormal*mlen*0.1); //start from a little inside the bounding box + Vector3 local_to = from_inv.xform(to); + + Vector3 rpos,rnorm; + if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from,local_to,rpos,rnorm)) { + return false; + } + + //shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough + Vector3 hitpos = p_xform_B.xform(rpos); + + float newlen = hitpos.distance_to(from)-(max-min)*0.01; + p_A->set_linear_velocity((mnormal*newlen)/p_step); + + return true; +} + + bool BodyPairSW::setup(float p_step) { //cannot collide - if (A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) { + if ((A->get_layer_mask()&B->get_layer_mask())==0 || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) { collided=false; return false; } @@ -198,8 +245,21 @@ bool BodyPairSW::setup(float p_step) { bool collided = CollisionSolverSW::solve_static(shape_A_ptr,xform_A,shape_B_ptr,xform_B,_contact_added_callback,this,&sep_axis); this->collided=collided; - if (!collided) + + if (!collided) { + + //test ccd (currently just a raycast) + + if (A->is_continuous_collision_detection_enabled() && A->get_mode()>PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC) { + _test_ccd(p_step,A,shape_A,xform_A,B,shape_B,xform_B); + } + + if (B->is_continuous_collision_detection_enabled() && B->get_mode()>PhysicsServer::BODY_MODE_KINEMATIC && A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC) { + _test_ccd(p_step,B,shape_B,xform_B,A,shape_A,xform_A); + } + return false; + } diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h index 937c295c63..e64464e2c1 100644 --- a/servers/physics/body_pair_sw.h +++ b/servers/physics/body_pair_sw.h @@ -82,6 +82,7 @@ class BodyPairSW : public ConstraintSW { void contact_added_callback(const Vector3& p_point_A,const Vector3& p_point_B); void validate_contacts(); + bool _test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B); SpaceSW *space; diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 725a440b59..5682ad8498 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -358,10 +358,10 @@ void BodySW::_compute_area_gravity(const AreaSW *p_area) { if (p_area->is_gravity_point()) { - gravity = (p_area->get_gravity_vector() - get_transform().get_origin()).normalized() * p_area->get_gravity(); + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); } else { - gravity = p_area->get_gravity_vector() * p_area->get_gravity(); + gravity += p_area->get_gravity_vector() * p_area->get_gravity(); } } @@ -371,23 +371,29 @@ void BodySW::integrate_forces(real_t p_step) { if (mode==PhysicsServer::BODY_MODE_STATIC) return; - AreaSW *current_area = get_space()->get_default_area(); - ERR_FAIL_COND(!current_area); + AreaSW *def_area = get_space()->get_default_area(); + ERR_FAIL_COND(!def_area); - int prio = current_area->get_priority(); int ac = areas.size(); + bool replace = false; + gravity=Vector3(0,0,0); if (ac) { + areas.sort(); const AreaCMP *aa = &areas[0]; - for(int i=0;i<ac;i++) { - if (aa[i].area->get_priority() > prio) { - current_area=aa[i].area; - prio=current_area->get_priority(); + density = aa[ac-1].area->get_density(); + for(int i=ac-1;i>=0;i--) { + _compute_area_gravity(aa[i].area); + if (aa[i].area->get_space_override_mode() == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE) { + replace = true; + break; } } + } else { + density=def_area->get_density(); + } + if( !replace ) { + _compute_area_gravity(def_area); } - - _compute_area_gravity(current_area); - density=current_area->get_density(); Vector3 motion; bool do_motion=false; @@ -455,7 +461,7 @@ void BodySW::integrate_forces(real_t p_step) { } - current_area=NULL; // clear the area, so it is set in the next frame + def_area=NULL; // clear the area, so it is set in the next frame contact_count=0; } diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index ee3c76e455..021245fe50 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -84,13 +84,13 @@ class BodySW : public CollisionObjectSW { struct AreaCMP { AreaSW *area; - _FORCE_INLINE_ bool operator<(const AreaCMP& p_cmp) const { return area->get_self() < p_cmp.area->get_self() ; } + _FORCE_INLINE_ bool operator==(const AreaCMP& p_cmp) const { return area->get_self() == p_cmp.area->get_self();} + _FORCE_INLINE_ bool operator<(const AreaCMP a) const { return area->get_priority() < a.area->get_priority();} _FORCE_INLINE_ AreaCMP() {} _FORCE_INLINE_ AreaCMP(AreaSW *p_area) { area=p_area;} }; - - VSet<AreaCMP> areas; + Vector<AreaCMP> areas; struct Contact { @@ -134,8 +134,7 @@ public: void set_force_integration_callback(ObjectID p_id,const StringName& p_method,const Variant& p_udata=Variant()); - - _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.insert(AreaCMP(p_area)); } + _FORCE_INLINE_ void add_area(AreaSW *p_area) { areas.ordered_insert(AreaCMP(p_area)); } _FORCE_INLINE_ void remove_area(AreaSW *p_area) { areas.erase(AreaCMP(p_area)); } _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; if (mode==PhysicsServer::BODY_MODE_KINEMATIC && p_size) set_active(true);} diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 56f2784145..86e3b679f2 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -275,6 +275,44 @@ void CollisionSolverSW::concave_distance_callback(void *p_userdata, ShapeSW *p_c } + +bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B) { + + const PlaneShapeSW *plane = static_cast<const PlaneShapeSW*>(p_shape_A); + if (p_shape_B->get_type()==PhysicsServer::SHAPE_PLANE) + return false; + Plane p = p_transform_A.xform(plane->get_plane()); + + static const int max_supports = 16; + Vector3 supports[max_supports]; + int support_count; + + p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(),max_supports,supports,support_count); + + bool collided=false; + Vector3 closest; + float closest_d; + + + for(int i=0;i<support_count;i++) { + + supports[i] = p_transform_B.xform( supports[i] ); + real_t d = p.distance_to(supports[i]); + if (i==0 || d<closest_d) { + closest=supports[i]; + closest_d=d; + if (d<=0) + collided=true; + } + + } + + r_point_A=p.project(closest); + r_point_B=closest; + + return collided; +} + bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis) { if (p_shape_A->is_concave()) @@ -282,7 +320,11 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& if (p_shape_B->get_type()==PhysicsServer::SHAPE_PLANE) { - return false; //unsupported + Vector3 a,b; + bool col = solve_distance_plane(p_shape_B,p_transform_B,p_shape_A,p_transform_A,a,b); + r_point_A=b; + r_point_B=a; + return !col; } else if (p_shape_B->is_concave()) { diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h index 430f057c7c..764c32926c 100644 --- a/servers/physics/collision_solver_sw.h +++ b/servers/physics/collision_solver_sw.h @@ -42,6 +42,7 @@ private: static bool solve_ray(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result); static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A=0,float p_margin_B=0); static void concave_distance_callback(void *p_userdata, ShapeSW *p_convex); + static bool solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B); public: diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 510a6ea93f..cfe5a73ce1 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -770,7 +770,7 @@ void PhysicsServerSW::body_remove_collision_exception(RID p_body, RID p_body_b) BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); - body->remove_exception(p_body); + body->remove_exception(p_body_b); }; diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h index cdb21556b8..bcf8fbdc8d 100644 --- a/servers/physics/shape_sw.h +++ b/servers/physics/shape_sw.h @@ -438,7 +438,7 @@ struct MotionShapeSW : public ShapeSW { } return support; } - virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const {} + virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; } bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { return false; } Vector3 get_moment_of_inertia(float p_mass) const { return Vector3(); } diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 4e8b60b86b..3fc34889f2 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -77,7 +77,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
continue;
- if (!(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
+ if (!(static_cast<CollisionObjectSW*>(space->intersection_query_results[i])->is_ray_pickable()))
continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self()))
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 8be583c235..65f3b80dd3 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -31,6 +31,7 @@ #include "body_2d_sw.h" Area2DSW::BodyKey::BodyKey(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; } +Area2DSW::BodyKey::BodyKey(Area2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; } void Area2DSW::_shapes_changed() { @@ -57,6 +58,7 @@ void Area2DSW::set_space(Space2DSW *p_space) { } monitored_bodies.clear(); + monitored_areas.clear(); _set_space(p_space); } @@ -76,11 +78,31 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) { monitor_callback_method=p_method; monitored_bodies.clear(); + monitored_areas.clear(); _shape_changed(); } +void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) { + + + if (p_id==area_monitor_callback_id) { + area_monitor_callback_method=p_method; + return; + } + + _unregister_shapes(); + + area_monitor_callback_id=p_id; + area_monitor_callback_method=p_method; + + monitored_bodies.clear(); + monitored_areas.clear(); + + _shape_changed(); + +} void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode) { @@ -99,7 +121,8 @@ void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; - case Physics2DServer::AREA_PARAM_DENSITY: density=p_value; ; break; + case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; + case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; case Physics2DServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; } @@ -114,7 +137,8 @@ Variant Area2DSW::get_param(Physics2DServer::AreaParameter p_param) const { case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; - case Physics2DServer::AREA_PARAM_DENSITY: return density; + case Physics2DServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case Physics2DServer::AREA_PARAM_PRIORITY: return priority; } @@ -132,6 +156,15 @@ void Area2DSW::_queue_monitor_update() { } +void Area2DSW::set_monitorable(bool p_monitorable) { + + if (monitorable==p_monitorable) + return; + + monitorable=p_monitorable; + _set_static(!monitorable); +} + void Area2DSW::call_queries() { if (monitor_callback_id && !monitored_bodies.empty()) { @@ -168,22 +201,61 @@ void Area2DSW::call_queries() { monitored_bodies.clear(); + if (area_monitor_callback_id && !monitored_areas.empty()) { + + + Variant res[5]; + Variant *resptr[5]; + for(int i=0;i<5;i++) + resptr[i]=&res[i]; + + Object *obj = ObjectDB::get_instance(area_monitor_callback_id); + if (!obj) { + monitored_areas.clear(); + area_monitor_callback_id=0; + return; + } + + + + for (Map<BodyKey,BodyState>::Element *E=monitored_areas.front();E;E=E->next()) { + + if (E->get().state==0) + continue; //nothing happened + + res[0]=E->get().state>0 ? Physics2DServer::AREA_BODY_ADDED : Physics2DServer::AREA_BODY_REMOVED; + res[1]=E->key().rid; + res[2]=E->key().instance_id; + res[3]=E->key().body_shape; + res[4]=E->key().area_shape; + + + Variant::CallError ce; + obj->call(area_monitor_callback_method,(const Variant**)resptr,5,ce); + } + } + + monitored_areas.clear(); + //get_space()->area_remove_from_monitor_query_list(&monitor_query_list); } Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this), moved_list(this) { - _set_static(true); //areas are never active + _set_static(true); //areas are not active by default space_override_mode=Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED; gravity=9.80665; gravity_vector=Vector2(0,-1); gravity_is_point=false; point_attenuation=1; - density=0.1; + angular_damp=1.0; + linear_damp=0.1; priority=0; monitor_callback_id=0; + area_monitor_callback_id=0; + monitorable=false; } diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 0eda1050fa..26b7b2516c 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -47,12 +47,17 @@ class Area2DSW : public CollisionObject2DSW{ Vector2 gravity_vector; bool gravity_is_point; float point_attenuation; - float density; + float linear_damp; + float angular_damp; int priority; + bool monitorable; ObjectID monitor_callback_id; StringName monitor_callback_method; + ObjectID area_monitor_callback_id; + StringName area_monitor_callback_method; + SelfList<Area2DSW> monitor_query_list; SelfList<Area2DSW> moved_list; @@ -79,6 +84,7 @@ class Area2DSW : public CollisionObject2DSW{ _FORCE_INLINE_ BodyKey() {} BodyKey(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); + BodyKey(Area2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); }; struct BodyState { @@ -90,6 +96,7 @@ class Area2DSW : public CollisionObject2DSW{ }; Map<BodyKey,BodyState> monitored_bodies; + Map<BodyKey,BodyState> monitored_areas; //virtual void shape_changed_notify(Shape2DSW *p_shape); //virtual void shape_deleted_notify(Shape2DSW *p_shape); @@ -107,9 +114,16 @@ public: void set_monitor_callback(ObjectID p_id, const StringName& p_method); _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id; } + void set_area_monitor_callback(ObjectID p_id, const StringName& p_method); + _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id; } + + _FORCE_INLINE_ void add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); _FORCE_INLINE_ void remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); + _FORCE_INLINE_ void add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape); + _FORCE_INLINE_ void remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape); + void set_param(Physics2DServer::AreaParameter p_param, const Variant& p_value); Variant get_param(Physics2DServer::AreaParameter p_param) const; @@ -128,8 +142,11 @@ public: _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } - _FORCE_INLINE_ void set_density(float p_density) { density=p_density; } - _FORCE_INLINE_ float get_density() const { return density; } + _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; } + _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; } + + _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; } + _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; } _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } @@ -138,6 +155,9 @@ public: _FORCE_INLINE_ void remove_constraint( Constraint2DSW* p_constraint) { constraints.erase(p_constraint); } _FORCE_INLINE_ const Set<Constraint2DSW*>& get_constraints() const { return constraints; } + void set_monitorable(bool p_monitorable); + _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } + void set_transform(const Matrix32& p_transform); void set_space(Space2DSW *p_space); @@ -164,6 +184,24 @@ void Area2DSW::remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape,ui _queue_monitor_update(); } +void Area2DSW::add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) { + + + BodyKey bk(p_area,p_area_shape,p_self_shape); + monitored_areas[bk].inc(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); + + +} +void Area2DSW::remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) { + + + BodyKey bk(p_area,p_area_shape,p_self_shape); + monitored_areas[bk].dec(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); +} diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp index 1c7f73db5e..ed2e34c972 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/area_pair_2d_sw.cpp @@ -94,3 +94,72 @@ AreaPair2DSW::~AreaPair2DSW() { body->remove_constraint(this); area->remove_constraint(this); } + + +////////////////////////////////// + + + +bool Area2Pair2DSW::setup(float p_step) { + + bool result = CollisionSolver2DSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this); + + if (result!=colliding) { + + if (result) { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->add_area_to_query(area_a,shape_a,shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->add_area_to_query(area_b,shape_b,shape_a); + + } else { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->remove_area_from_query(area_a,shape_a,shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->remove_area_from_query(area_b,shape_b,shape_a); + } + + colliding=result; + + } + + return false; //never do any post solving +} + +void Area2Pair2DSW::solve(float p_step) { + + +} + + +Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b) { + + + area_a=p_area_a; + area_b=p_area_b; + shape_a=p_shape_a; + shape_b=p_shape_b; + colliding=false; + area_a->add_constraint(this); + area_b->add_constraint(this); + +} + +Area2Pair2DSW::~Area2Pair2DSW() { + + if (colliding) { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->remove_area_from_query(area_a,shape_a,shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->remove_area_from_query(area_b,shape_b,shape_a); + } + + area_a->remove_constraint(this); + area_b->remove_constraint(this); +} diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h index 5dad8c7a12..575490b109 100644 --- a/servers/physics_2d/area_pair_2d_sw.h +++ b/servers/physics_2d/area_pair_2d_sw.h @@ -49,5 +49,23 @@ public: ~AreaPair2DSW(); }; + +class Area2Pair2DSW : public Constraint2DSW { + + Area2DSW *area_a; + Area2DSW *area_b; + int shape_a; + int shape_b; + bool colliding; +public: + + bool setup(float p_step); + void solve(float p_step); + + Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b); + ~Area2Pair2DSW(); +}; + + #endif // AREA_PAIR_2D_SW_H diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index fbad19f6be..06d466ace8 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -65,7 +65,13 @@ void Body2DSW::update_inertias() { float mass = area * this->mass / total_area; - _inertia += shape->get_moment_of_inertia(mass) + mass * get_shape_transform(i).get_origin().length_squared(); + Matrix32 mtx = get_shape_transform(i); + Vector2 scale = mtx.get_scale(); + _inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared(); + //Rect2 ab = get_shape_aabb(i); + //_inertia+=mass*ab.size.dot(ab.size)/12.0f; + + } @@ -150,6 +156,17 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) _update_inertia(); } break; + case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { + gravity_scale=p_value; + } break; + case Physics2DServer::BODY_PARAM_LINEAR_DAMP: { + + linear_damp=p_value; + } break; + case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: { + + angular_damp=p_value; + } break; default:{} } } @@ -168,6 +185,17 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { case Physics2DServer::BODY_PARAM_MASS: { return mass; } break; + case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { + return gravity_scale; + } break; + case Physics2DServer::BODY_PARAM_LINEAR_DAMP: { + + return linear_damp; + } break; + case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: { + + return angular_damp; + } break; default:{} } @@ -351,11 +379,13 @@ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) { if (p_area->is_gravity_point()) { - gravity = (p_area->get_transform().get_origin()+p_area->get_gravity_vector() - get_transform().get_origin()).normalized() * p_area->get_gravity(); + gravity = (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); } else { gravity = p_area->get_gravity_vector() * p_area->get_gravity(); } + + gravity*=gravity_scale; } void Body2DSW::integrate_forces(real_t p_step) { @@ -379,7 +409,16 @@ void Body2DSW::integrate_forces(real_t p_step) { } _compute_area_gravity(current_area); - density=current_area->get_density(); + + if (angular_damp>=0) + area_angular_damp=angular_damp; + else + area_angular_damp=current_area->get_angular_damp(); + + if (linear_damp>=0) + area_linear_damp=linear_damp; + else + area_linear_damp=current_area->get_linear_damp(); Vector2 motion; bool do_motion=false; @@ -408,12 +447,12 @@ void Body2DSW::integrate_forces(real_t p_step) { force+=applied_force; real_t torque=applied_torque; - real_t damp = 1.0 - p_step * density; + real_t damp = 1.0 - p_step * area_linear_damp; if (damp<0) // reached zero in the given time damp=0; - real_t angular_damp = 1.0 - p_step * density * get_space()->get_body_angular_velocity_damp_ratio(); + real_t angular_damp = 1.0 - p_step * area_angular_damp; if (angular_damp<0) // reached zero in the given time angular_damp=0; @@ -602,8 +641,13 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti island_list_next=NULL; _set_static(false); first_time_kinematic=false; - density=0; + linear_damp=-1; + angular_damp=-1; + area_angular_damp=0; + area_linear_damp=0; contact_count=0; + gravity_scale=1.0; + one_way_collision_max_depth=0.1; still_time=0; continuous_cd_mode=Physics2DServer::CCD_MODE_DISABLED; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 789fb1cfee..3b87be2737 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -47,6 +47,10 @@ class Body2DSW : public CollisionObject2DSW { Vector2 linear_velocity; real_t angular_velocity; + real_t linear_damp; + real_t angular_damp; + real_t gravity_scale; + real_t mass; real_t bounce; real_t friction; @@ -55,13 +59,17 @@ class Body2DSW : public CollisionObject2DSW { real_t _inv_inertia; Vector2 gravity; - real_t density; + real_t area_linear_damp; + real_t area_angular_damp; real_t still_time; Vector2 applied_force; real_t applied_torque; + Vector2 one_way_collision_direction; + float one_way_collision_max_depth; + SelfList<Body2DSW> active_list; SelfList<Body2DSW> inertia_update_list; @@ -211,6 +219,12 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode=p_mode; } _FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } + void set_one_way_collision_direction(const Vector2& p_dir) { one_way_collision_direction=p_dir; } + Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; } + + void set_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; } + float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; } + void set_space(Space2DSW *p_space); void update_inertias(); @@ -219,8 +233,10 @@ public: _FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; } _FORCE_INLINE_ real_t get_friction() const { return friction; } _FORCE_INLINE_ Vector2 get_gravity() const { return gravity; } - _FORCE_INLINE_ real_t get_density() const { return density; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } + _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } + _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } + void integrate_forces(real_t p_step); void integrate_velocities(real_t p_step); @@ -306,7 +322,8 @@ public: real_t step; virtual Vector2 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area - virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area + virtual float get_total_angular_damp() const { return body->get_angular_damp(); } // get density of this body space/area + virtual float get_total_linear_damp() const { return body->get_linear_damp(); } // get density of this body space/area virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 9abdd01791..c4d6abe5ac 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -190,7 +190,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat p_A->get_shape(p_shape_A)->project_rangev(mnormal,p_xform_A,min,max); bool fast_object = mlen > (max-min)*0.3; //going too fast in that direction - if (fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis + if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis return false; } diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index d0443f8110..eefc598b39 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -228,4 +228,5 @@ CollisionObject2DSW::CollisionObject2DSW(Type p_type) { instance_id=0; user_mask=0; layer_mask=1; + pickable=true; } diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 00ad361245..0c91237876 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -47,6 +47,7 @@ private: Type type; RID self; ObjectID instance_id; + bool pickable; struct Shape { @@ -129,6 +130,9 @@ public: _FORCE_INLINE_ bool is_static() const { return _static; } + void set_pickable(bool p_pickable) { pickable=p_pickable; } + _FORCE_INLINE_ bool is_pickable() const { return pickable; } + virtual ~CollisionObject2DSW() {} }; diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index f73ed5732e..9ed594e0eb 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -1086,6 +1086,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri SeparatorAxisTest2D<RectangleShape2DSW,ConvexPolygonShape2DSW,castA,castB,withMargin> separator(rectangle_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B); + if (!separator.test_previous_axis()) return; diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index ab85f5e1d6..883acd0200 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -138,6 +138,21 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p if (cbk->max==0) return; + if (cbk->valid_dir!=Vector2()) { + if (p_point_A.distance_squared_to(p_point_B)>cbk->valid_depth*cbk->valid_depth) { + return; + } + if (cbk->valid_dir.dot((p_point_A-p_point_B).normalized())<0.7071) { +/* print_line("A: "+p_point_A); + print_line("B: "+p_point_B); + print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B)))); + print_line("resnorm: "+(p_point_A-p_point_B).normalized()); + print_line("distance: "+rtos(p_point_A.distance_to(p_point_B))); +*/ + return; + } + } + if (cbk->amount == cbk->max) { //find least deep float min_depth=1e20; @@ -448,6 +463,24 @@ Matrix32 Physics2DServerSW::area_get_transform(RID p_area) const { return area->get_transform(); }; +void Physics2DServerSW::area_set_pickable(RID p_area,bool p_pickable) { + + Area2DSW *area = area_owner.get(p_area); + ERR_FAIL_COND(!area); + area->set_pickable(p_pickable); + +} + +void Physics2DServerSW::area_set_monitorable(RID p_area,bool p_monitorable) { + + Area2DSW *area = area_owner.get(p_area); + ERR_FAIL_COND(!area); + + area->set_monitorable(p_monitorable); + +} + + void Physics2DServerSW::area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) { Area2DSW *area = area_owner.get(p_area); @@ -458,6 +491,14 @@ void Physics2DServerSW::area_set_monitor_callback(RID p_area,Object *p_receiver, } +void Physics2DServerSW::area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) { + + + Area2DSW *area = area_owner.get(p_area); + ERR_FAIL_COND(!area); + + area->set_area_monitor_callback(p_receiver?p_receiver->get_instance_ID():0,p_method); +} /* BODY API */ @@ -860,6 +901,37 @@ int Physics2DServerSW::body_get_max_contacts_reported(RID p_body) const { return body->get_max_contacts_reported(); } +void Physics2DServerSW::body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_one_way_collision_direction(p_direction); +} + +Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) const{ + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,Vector2()); + return body->get_one_way_collision_direction(); + +} + +void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_max_depth) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_one_way_collision_max_depth(p_max_depth); + +} + +float Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body,0); + return body->get_one_way_collision_max_depth(); + +} + void Physics2DServerSW::body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata) { @@ -879,6 +951,13 @@ bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_s } +void Physics2DServerSW::body_set_pickable(RID p_body,bool p_pickable) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + body->set_pickable(p_pickable); + +} /* JOINT API */ diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 9edd4eee11..58fc4eeb33 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -71,6 +71,8 @@ public: struct CollCbkData { + Vector2 valid_dir; + float valid_depth; int max; int amount; Vector2 *ptr; @@ -131,8 +133,12 @@ public: virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const; virtual Matrix32 area_get_transform(RID p_area) const; + virtual void area_set_monitorable(RID p_area,bool p_monitorable); virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method); + virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method); + + virtual void area_set_pickable(RID p_area,bool p_pickable); /* BODY API */ @@ -205,9 +211,18 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); virtual int body_get_max_contacts_reported(RID p_body) const; + virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction); + virtual Vector2 body_get_one_way_collision_direction(RID p_body) const; + + virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth); + virtual float body_get_one_way_collision_max_depth(RID p_body) const; + + virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant()); virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count); + virtual void body_set_pickable(RID p_body,bool p_pickable); + /* JOINT API */ virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 012c4ed404..9a4b52d563 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -106,6 +106,11 @@ void LineShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,int r_amount=0; } +bool LineShape2DSW::contains_point(const Vector2& p_point) const { + + return normal.dot(p_point) < d; +} + bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { Vector2 segment= p_begin - p_end; @@ -131,11 +136,12 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en return true; } -real_t LineShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { return 0; } + void LineShape2DSW::set_data(const Variant& p_data) { ERR_FAIL_COND(p_data.get_type()!=Variant::ARRAY); @@ -174,13 +180,18 @@ void RayShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,int } +bool RayShape2DSW::contains_point(const Vector2& p_point) const { + + return false; +} + bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { return false; //rays can't be intersected } -real_t RayShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { return 0; //rays are mass-less } @@ -222,6 +233,11 @@ void SegmentShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports, } +bool SegmentShape2DSW::contains_point(const Vector2& p_point) const { + + return false; +} + bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { if (!Geometry::segment_intersects_segment_2d(p_begin,p_end,a,b,&r_point)) @@ -237,10 +253,12 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return true; } -real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { - real_t l = b.distance_to(a); - Vector2 ofs = (a+b)*0.5; + Vector2 s[2]={a*p_scale,b*p_scale}; + + real_t l = s[1].distance_to(s[0]); + Vector2 ofs = (s[0]+s[1])*0.5; return p_mass*(l*l/12.0f + ofs.length_squared()); } @@ -285,6 +303,13 @@ void CircleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,i } + +bool CircleShape2DSW::contains_point(const Vector2& p_point) const { + + return p_point.length_squared() < radius*radius; +} + + bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { @@ -312,9 +337,10 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_ return true; } -real_t CircleShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { + + return (radius*radius)*(p_scale.x*0.5+p_scale.y*0.5); - return radius*radius; } void CircleShape2DSW::set_data(const Variant& p_data) { @@ -371,15 +397,20 @@ void RectangleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_support } +bool RectangleShape2DSW::contains_point(const Vector2& p_point) const { + + return Math::abs(p_point.x)<half_extents.x && Math::abs(p_point.y)<half_extents.y; +} + bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal); } -real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { - Vector2 he2=half_extents*2; + Vector2 he2=half_extents*2*p_scale; return p_mass*he2.dot(he2)/12.0f; } @@ -435,6 +466,17 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports, } } +bool CapsuleShape2DSW::contains_point(const Vector2& p_point) const { + + Vector2 p = p_point; + p.y=Math::abs(p.y); + p.y-=height*0.5; + if (p.y<0) + p.y=0; + + return p.length_squared() < radius*radius; +} + bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { @@ -499,9 +541,9 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return collided; //todo } -real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { - Vector2 he2(radius*2,height+radius*2); + Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale; return p_mass*he2.dot(he2)/12.0f; } @@ -570,6 +612,25 @@ void ConvexPolygonShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_sup } + +bool ConvexPolygonShape2DSW::contains_point(const Vector2& p_point) const { + + bool out=false; + bool in=false; + + for(int i=0;i<point_count;i++) { + + float d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos); + if (d>0) + out=true; + else + in=true; + } + + return (in && !out) || (!in && out); +} + + bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { Vector2 n = (p_end-p_begin).normalized(); @@ -610,16 +671,16 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect return inters; //todo } -real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass) const { +real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { Rect2 aabb; - aabb.pos=points[0].pos; + aabb.pos=points[0].pos*p_scale; for(int i=0;i<point_count;i++) { - aabb.expand_to(points[i].pos); + aabb.expand_to(points[i].pos*p_scale); } - return p_mass*aabb.size.dot(aabb.size)/12.0f; + return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared(); } void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { @@ -730,6 +791,12 @@ void ConcavePolygonShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_su } +bool ConcavePolygonShape2DSW::contains_point(const Vector2& p_point) const { + + return false; //sorry +} + + bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const{ uint32_t* stack = (uint32_t*)alloca(sizeof(int)*bvh_depth); diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 8500a6194f..05ea5b21cd 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -78,14 +78,15 @@ public: virtual bool is_concave() const { return false; } + virtual bool contains_point(const Vector2& p_point) const=0; + virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0; virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0; virtual Vector2 get_support(const Vector2& p_normal) const; virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0; - virtual real_t get_moment_of_inertia(float p_mass) const=0; - + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0; virtual void set_data(const Variant& p_data)=0; virtual Variant get_data() const=0; @@ -172,8 +173,9 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -214,8 +216,9 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -261,8 +264,9 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -298,8 +302,9 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -337,21 +342,27 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { // no matter the angle, the box is mirrored anyway - Vector2 local_normal=p_transform.basis_xform_inv(p_normal); + r_max=-1e20; + r_min=1e20; + for(int i=0;i<4;i++) { - float length = local_normal.abs().dot(half_extents); - float distance = p_normal.dot( p_transform.get_origin() ); + real_t d=p_normal.dot(p_transform.xform(Vector2( ((i&1)*2-1)*half_extents.x, ((i>>1)*2-1)*half_extents.y ))); + + if (d>r_max) + r_max=d; + if (d<r_min) + r_min=d; - r_min = distance - length; - r_max = distance + length; + } } @@ -419,8 +430,9 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -481,8 +493,9 @@ public: virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const; + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -568,9 +581,10 @@ public: virtual void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; + virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass) const { return 0; } + virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; } virtual void set_data(const Variant& p_data); virtual Variant get_data() const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 8b72436936..5aaf9a7613 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -45,6 +45,57 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec } + +int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { + + if (p_result_max<=0) + return 0; + + Rect2 aabb; + aabb.pos=p_point-Vector2(0.00001,0.00001); + aabb.size=Vector2(0.00002,0.00002); + + int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); + + int cc=0; + + for(int i=0;i<amount;i++) { + + if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) + continue; + + if (p_exclude.has( space->intersection_query_results[i]->get_self())) + continue; + + const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; + + if (!col_obj->is_pickable()) + continue; + + int shape_idx=space->intersection_query_subindex_results[i]; + + Shape2DSW * shape = col_obj->get_shape(shape_idx); + + Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point); + + if (!shape->contains_point(local_point)) + continue; + + r_results[cc].collider_id=col_obj->get_instance_id(); + if (r_results[cc].collider_id!=0) + r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); + r_results[cc].rid=col_obj->get_self(); + r_results[cc].shape=shape_idx; + r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx); + + cc++; + } + + return cc; + + +} + bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { @@ -98,7 +149,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) { - //print_line("inters sgment!"); + Matrix32 xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point=xform.xform(shape_point); @@ -217,6 +268,16 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 int shape_idx=space->intersection_query_subindex_results[i]; + /*if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + if (body->get_one_way_collision_direction()!=Vector2() && p_motion.dot(body->get_one_way_collision_direction())<=CMP_EPSILON) { + print_line("failed in motion dir"); + continue; + } + }*/ + + Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) { @@ -227,6 +288,14 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 //test initial overlap if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) { + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + //if one way collision direction ignore initial overlap + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + if (body->get_one_way_collision_direction()!=Vector2()) { + continue; + } + } + return false; } @@ -253,6 +322,29 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 } } + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + if (body->get_one_way_collision_direction()!=Vector2()) { + + Vector2 cd[2]; + Physics2DServerSW::CollCbkData cbk; + cbk.max=1; + cbk.amount=0; + cbk.ptr=cd; + cbk.valid_dir=body->get_one_way_collision_direction(); + cbk.valid_depth=body->get_one_way_collision_max_depth(); + + Vector2 sep=mnormal; //important optimization for this to work fast enough + bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*(hi+space->contact_max_allowed_penetration),col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),Physics2DServerSW::_shape_col_cbk,&cbk,&sep,p_margin); + if (!collided || cbk.amount==0) { + continue; + } + + } + } + + if (low<best_safe) { best_safe=low; best_unsafe=hi; @@ -311,14 +403,23 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_s if (p_exclude.has( col_obj->get_self() )) continue; - + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + cbk.valid_dir=body->get_one_way_collision_direction(); + cbk.valid_depth=body->get_one_way_collision_max_depth(); + } else { + cbk.valid_dir=Vector2(); + cbk.valid_depth=0; + } if (CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),cbkres,cbkptr,NULL,p_margin)) { - collided=true; + collided=p_result_max==0 || cbk.amount>0; } } + r_result_count=cbk.amount; return collided; @@ -334,6 +435,8 @@ struct _RestCallbackData2D { Vector2 best_contact; Vector2 best_normal; float best_len; + Vector2 valid_dir; + float valid_depth; }; static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) { @@ -341,11 +444,23 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v _RestCallbackData2D *rd=(_RestCallbackData2D*)p_userdata; + if (rd->valid_dir!=Vector2()) { + + if (rd->valid_dir!=Vector2()) { + if (p_point_A.distance_squared_to(p_point_B)>rd->valid_depth*rd->valid_depth) + return; + if (rd->valid_dir.dot((p_point_A-p_point_B).normalized())<Math_PI*0.25) + return; + } + + } + Vector2 contact_rel = p_point_B - p_point_A; float len = contact_rel.length(); if (len <= rd->best_len) return; + rd->best_len=len; rd->best_contact=p_point_B; rd->best_normal=contact_rel/len; @@ -385,6 +500,17 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape if (p_exclude.has( col_obj->get_self() )) continue; + if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) { + + const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); + rcd.valid_dir=body->get_one_way_collision_direction(); + rcd.valid_depth=body->get_one_way_collision_max_depth(); + } else { + rcd.valid_dir=Vector2(); + rcd.valid_depth=0; + } + + rcd.object=col_obj; rcd.shape=shape_idx; bool sc = CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2() ,_rest_cbk_result,&rcd,NULL,p_margin); @@ -437,6 +563,7 @@ Physics2DDirectSpaceStateSW::Physics2DDirectSpaceStateSW() { void* Space2DSW::_broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,CollisionObject2DSW *B,int p_subindex_B,void *p_self) { + CollisionObject2DSW::Type type_A=A->get_type(); CollisionObject2DSW::Type type_B=B->get_type(); if (type_A>type_B) { @@ -451,14 +578,20 @@ void* Space2DSW::_broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,Collis if (type_A==CollisionObject2DSW::TYPE_AREA) { - - ERR_FAIL_COND_V(type_B!=CollisionObject2DSW::TYPE_BODY,NULL); Area2DSW *area=static_cast<Area2DSW*>(A); - Body2DSW *body=static_cast<Body2DSW*>(B); + if (type_B==CollisionObject2DSW::TYPE_AREA) { + + Area2DSW *area_b=static_cast<Area2DSW*>(B); + Area2Pair2DSW *area2_pair = memnew(Area2Pair2DSW(area_b,p_subindex_B,area,p_subindex_A) ); + return area2_pair; + } else { + + Body2DSW *body=static_cast<Body2DSW*>(B); + AreaPair2DSW *area_pair = memnew(AreaPair2DSW(body,p_subindex_B,area,p_subindex_A) ); + return area_pair; + } - AreaPair2DSW *area_pair = memnew(AreaPair2DSW(body,p_subindex_B,area,p_subindex_A) ); - return area_pair; } else { @@ -606,8 +739,7 @@ void Space2DSW::set_param(Physics2DServer::SpaceParameter p_param, real_t p_valu case Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: contact_max_allowed_penetration=p_value; break; case Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD: body_linear_velocity_sleep_treshold=p_value; break; case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_TRESHOLD: body_angular_velocity_sleep_treshold=p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep=p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio=p_value; break; + case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep=p_value; break; case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias=p_value; break; } } @@ -622,7 +754,6 @@ real_t Space2DSW::get_param(Physics2DServer::SpaceParameter p_param) const { case Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD: return body_linear_velocity_sleep_treshold; case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_TRESHOLD: return body_angular_velocity_sleep_treshold; case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; - case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio; case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; } return 0; @@ -664,7 +795,6 @@ Space2DSW::Space2DSW() { body_linear_velocity_sleep_treshold=0.01; body_angular_velocity_sleep_treshold=(8.0 / 180.0 * Math_PI); body_time_to_sleep=0.5; - body_angular_velocity_damp_ratio=15; broadphase = BroadPhase2DSW::create_func(); diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index c638a0c45b..05b55fe807 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -46,6 +46,7 @@ public: Space2DSW *space; + virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); @@ -93,7 +94,6 @@ class Space2DSW { float body_linear_velocity_sleep_treshold; float body_angular_velocity_sleep_treshold; float body_time_to_sleep; - float body_angular_velocity_damp_ratio; bool locked; @@ -142,7 +142,7 @@ public: _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_treshold() const { return body_linear_velocity_sleep_treshold; } _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_treshold() const { return body_angular_velocity_sleep_treshold; } _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; } - _FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; } + void update(); diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index cfa79e917d..098f890222 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -39,20 +39,24 @@ void Physics2DDirectBodyState::integrate_forces() { real_t av = get_angular_velocity(); - float damp = 1.0 - step * get_total_density(); + float damp = 1.0 - step * get_total_linear_damp(); if (damp<0) // reached zero in the given time damp=0; lv*=damp; + + damp = 1.0 - step * get_total_angular_damp(); + + if (damp<0) // reached zero in the given time + damp=0; + av*=damp; set_linear_velocity(lv); set_angular_velocity(av); - - } Object* Physics2DDirectBodyState::get_contact_collider_object(int p_contact_idx) const { @@ -70,7 +74,8 @@ Physics2DServer * Physics2DServer::get_singleton() { void Physics2DDirectBodyState::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity); - ObjectTypeDB::bind_method(_MD("get_total_density"),&Physics2DDirectBodyState::get_total_density); + ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp); + ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp); ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass); ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia); @@ -284,6 +289,36 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam return ret; } + +Array Physics2DDirectSpaceState::_intersect_point(const Vector2& p_point,int p_max_results,const Vector<RID>& p_exclude,uint32_t p_layers,uint32_t p_object_type_mask) { + + Set<RID> exclude; + for(int i=0;i<p_exclude.size();i++) + exclude.insert(p_exclude[i]); + + Vector<ShapeResult> ret; + ret.resize(p_max_results); + + int rc = intersect_point(p_point,ret.ptr(),ret.size(),exclude,p_layers,p_object_type_mask); + if (rc==0) + return Array(); + + Array r; + r.resize(rc); + for(int i=0;i<rc;i++) { + + Dictionary d; + d["rid"]=ret[i].rid; + d["collider_id"]=ret[i].collider_id; + d["collider"]=ret[i].collider; + d["shape"]=ret[i].shape; + d["metadata"]=ret[i].metadata; + r[i]=d; + } + return r; + +} + Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryParameters> &psq, int p_max_results){ Vector<Vector2> ret; @@ -331,6 +366,7 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() { void Physics2DDirectSpaceState::_bind_methods() { + ObjectTypeDB::bind_method(_MD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); ObjectTypeDB::bind_method(_MD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32)); ObjectTypeDB::bind_method(_MD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion); @@ -416,8 +452,8 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode); ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_set_shape,DEFVAL(Matrix32())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_get_shape); + ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Matrix32())); + ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape); ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform); ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count); @@ -495,6 +531,13 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported); ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported); + ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","normal"),&Physics2DServer::body_set_one_way_collision_direction); + ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction"),&Physics2DServer::body_get_one_way_collision_direction); + + ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_max_depth","normal"),&Physics2DServer::body_set_one_way_collision_max_depth); + ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth"),&Physics2DServer::body_get_one_way_collision_max_depth); + + ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration); ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration); @@ -514,7 +557,7 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type); - ObjectTypeDB::bind_method(_MD("free","rid"),&Physics2DServer::free); + ObjectTypeDB::bind_method(_MD("free_rid","rid"),&Physics2DServer::free); ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active); @@ -538,7 +581,8 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY_VECTOR ); BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); - BIND_CONSTANT( AREA_PARAM_DENSITY ); + BIND_CONSTANT( AREA_PARAM_LINEAR_DAMP); + BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP); BIND_CONSTANT( AREA_PARAM_PRIORITY ); BIND_CONSTANT( AREA_SPACE_OVERRIDE_COMBINE ); @@ -553,6 +597,9 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( BODY_PARAM_BOUNCE ); BIND_CONSTANT( BODY_PARAM_FRICTION ); BIND_CONSTANT( BODY_PARAM_MASS ); + BIND_CONSTANT( BODY_PARAM_GRAVITY_SCALE ); + BIND_CONSTANT( BODY_PARAM_LINEAR_DAMP); + BIND_CONSTANT( BODY_PARAM_ANGULAR_DAMP); BIND_CONSTANT( BODY_PARAM_MAX ); BIND_CONSTANT( BODY_STATE_TRANSFORM ); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 20d7c3ad28..01670ace7e 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -43,7 +43,8 @@ protected: public: virtual Vector2 get_total_gravity() const=0; // get gravity vector working on this body space/area - virtual float get_total_density() const=0; // get density of this body space/area + virtual float get_total_linear_damp() const=0; // get density of this body space/area + virtual float get_total_angular_damp() const=0; // get density of this body space/area virtual float get_inverse_mass() const=0; // get the mass virtual real_t get_inverse_inertia() const=0; // get density of this body space @@ -136,6 +137,7 @@ class Physics2DDirectSpaceState : public Object { Dictionary _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + Array _intersect_point(const Vector2& p_point,int p_max_results=32,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query,int p_max_results=32); Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query); Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query,int p_max_results=32); @@ -180,6 +182,8 @@ public: }; + virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; @@ -277,7 +281,6 @@ public: SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD, SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_TRESHOLD, SPACE_PARAM_BODY_TIME_TO_SLEEP, - SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO, SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, }; @@ -301,7 +304,8 @@ public: AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_POINT_ATTENUATION, - AREA_PARAM_DENSITY, + AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY }; @@ -340,7 +344,11 @@ public: virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const=0; virtual Matrix32 area_get_transform(RID p_area) const=0; + virtual void area_set_monitorable(RID p_area,bool p_monitorable)=0; + virtual void area_set_pickable(RID p_area,bool p_pickable)=0; + virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0; + virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0; /* BODY API */ @@ -401,6 +409,9 @@ public: BODY_PARAM_BOUNCE, BODY_PARAM_FRICTION, BODY_PARAM_MASS, ///< unused for static, always infinite + BODY_PARAM_GRAVITY_SCALE, + BODY_PARAM_LINEAR_DAMP, + BODY_PARAM_ANGULAR_DAMP, BODY_PARAM_MAX, }; @@ -414,7 +425,7 @@ public: BODY_STATE_LINEAR_VELOCITY, BODY_STATE_ANGULAR_VELOCITY, BODY_STATE_SLEEPING, - BODY_STATE_CAN_SLEEP + BODY_STATE_CAN_SLEEP, }; virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant)=0; @@ -438,6 +449,12 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts)=0; virtual int body_get_max_contacts_reported(RID p_body) const=0; + virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction)=0; + virtual Vector2 body_get_one_way_collision_direction(RID p_body) const=0; + + virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth)=0; + virtual float body_get_one_way_collision_max_depth(RID p_body) const=0; + //missing remove virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold)=0; virtual float body_get_contacts_reported_depth_treshold(RID p_body) const=0; @@ -449,6 +466,8 @@ public: virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0; + virtual void body_set_pickable(RID p_body,bool p_pickable)=0; + /* JOINT API */ enum JointType { diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index fbed5779ff..79de253d3b 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -440,8 +440,8 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode); ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_set_shape,DEFVAL(Transform())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_get_shape); + ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform())); + ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape); ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform); ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count); @@ -452,8 +452,8 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes); - ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_get_param); - ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_get_transform); + ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_set_param); + ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform); ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&PhysicsServer::area_get_param); ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&PhysicsServer::area_get_transform); @@ -506,7 +506,7 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity); ObjectTypeDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock); - ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_set_axis_lock); + ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock); ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception); ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception); @@ -655,7 +655,7 @@ void PhysicsServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type); */ - ObjectTypeDB::bind_method(_MD("free","rid"),&PhysicsServer::free); + ObjectTypeDB::bind_method(_MD("free_rid","rid"),&PhysicsServer::free); ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active); diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index 5e81bc960a..5088000022 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -79,7 +79,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { if (texcoords_used&(1<<VS::FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM)) { code+="uniform mat4 fmp_uv_xform;\n"; - code+="vec2 uv_xform = fmp_uv_xform * UV;\n"; + code+="vec2 uv_xform = (fmp_uv_xform * vec4(UV,0,1)).xy;\n"; } /* HANDLE NORMAL MAPPING */ @@ -91,7 +91,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { scode+="uniform float fmp_normal;\n"; scode+="uniform texture fmp_normal_tex;\n"; String uv_str; - if ((p_key.texcoord_mask>>(VS::FIXED_MATERIAL_PARAM_NORMAL*2))&0x3==VS::FIXED_MATERIAL_TEXCOORD_SPHERE) { + if (((p_key.texcoord_mask>>(VS::FIXED_MATERIAL_PARAM_NORMAL*2))&0x3)==VS::FIXED_MATERIAL_TEXCOORD_SPHERE) { uv_str="uv"; //sorry not supported } else { uv_str=_TEXUVSTR(VS::FIXED_MATERIAL_PARAM_NORMAL); @@ -568,8 +568,9 @@ void Rasterizer::_update_fixed_materials() { } material_set_param(fm.self,_fixed_material_uv_xform_name,fm.uv_xform); - if (fm.use_pointsize) + if (fm.use_pointsize) { material_set_param(fm.self,_fixed_material_point_size_name,fm.point_size); + } } fixed_material_dirty_list.remove(fixed_material_dirty_list.first()); @@ -620,6 +621,8 @@ Rasterizer::Rasterizer() { _fixed_material_uv_xform_name="fmp_uv_xform"; _fixed_material_point_size_name="fmp_point_size"; + draw_viewport_func=NULL; + ERR_FAIL_COND( sizeof(FixedMaterialShaderKey)!=4); } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index dc970383b6..62563a0771 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -40,6 +40,9 @@ class Rasterizer { protected: + + typedef void (*CanvasItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); + RID create_default_material(); RID create_overdraw_debug_material(); @@ -187,6 +190,7 @@ public: virtual bool texture_has_alpha(RID p_texture) const=0; virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0; + virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const=0; /* SHADER API */ @@ -203,6 +207,11 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name)=0; + /* COMMON MATERIAL API */ virtual RID material_create()=0; @@ -503,6 +512,7 @@ public: VS::BakedLightMode mode; RID octree_texture; + RID light_texture; float color_multiplier; //used for both lightmaps and octree Transform octree_transform; Map<int,RID> lightmaps; @@ -514,6 +524,7 @@ public: float lightmap_multiplier; int octree_steps; Vector2 octree_tex_pixel_size; + Vector2 light_tex_pixel_size; }; struct InstanceData { @@ -521,6 +532,7 @@ public: Transform transform; RID skeleton; RID material_override; + RID sampled_light; Vector<RID> light_instances; Vector<float> morph_values; BakedLightData *baked_light; @@ -552,9 +564,364 @@ public: CANVAS_RECT_REGION=1, CANVAS_RECT_TILE=2, CANVAS_RECT_FLIP_H=4, - CANVAS_RECT_FLIP_V=8 + CANVAS_RECT_FLIP_V=8, + CANVAS_RECT_TRANSPOSE=16 }; - + + + struct CanvasLight { + + + + bool enabled; + Color color; + Matrix32 xform; + float height; + float energy; + float scale; + int z_min; + int z_max; + int layer_min; + int layer_max; + int item_mask; + int item_shadow_mask; + VS::CanvasLightMode mode; + RID texture; + Vector2 texture_offset; + RID canvas; + RID shadow_buffer; + int shadow_buffer_size; + float shadow_esm_mult; + + + void *texture_cache; // implementation dependent + Rect2 rect_cache; + Matrix32 xform_cache; + float radius_cache; //used for shadow far plane + CameraMatrix shadow_matrix_cache; + + Matrix32 light_shader_xform; + Vector2 light_shader_pos; + + CanvasLight *shadows_next_ptr; + CanvasLight *filter_next_ptr; + CanvasLight *next_ptr; + + CanvasLight() { + enabled=true; + color=Color(1,1,1); + height=0; + z_min=-1024; + z_max=1024; + layer_min=0; + layer_max=0; + item_mask=1; + scale=1.0; + energy=1.0; + item_shadow_mask=-1; + mode=VS::CANVAS_LIGHT_MODE_ADD; + texture_cache=NULL; + next_ptr=NULL; + filter_next_ptr=NULL; + shadow_buffer_size=2048; + shadow_esm_mult=80; + + } + }; + + struct CanvasItem; + + struct CanvasItemMaterial { + + RID shader; + Map<StringName,Variant> shader_param; + uint32_t shader_version; + Set<CanvasItem*> owners; + VS::CanvasItemShadingMode shading_mode; + + CanvasItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; } + }; + + struct CanvasItem { + + struct Command { + + enum Type { + + TYPE_LINE, + TYPE_RECT, + TYPE_STYLE, + TYPE_PRIMITIVE, + TYPE_POLYGON, + TYPE_POLYGON_PTR, + TYPE_CIRCLE, + TYPE_TRANSFORM, + TYPE_BLEND_MODE, + TYPE_CLIP_IGNORE, + }; + + Type type; + }; + + struct CommandLine : public Command { + + Point2 from,to; + Color color; + float width; + CommandLine() { type = TYPE_LINE; } + }; + + struct CommandRect : public Command { + + Rect2 rect; + RID texture; + Color modulate; + Rect2 source; + uint8_t flags; + + CommandRect() { flags=0; type = TYPE_RECT; } + }; + + struct CommandStyle : public Command { + + Rect2 rect; + RID texture; + float margin[4]; + float draw_center; + Color color; + CommandStyle() { draw_center=true; type = TYPE_STYLE; } + }; + + struct CommandPrimitive : public Command { + + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + float width; + + CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;} + }; + + struct CommandPolygon : public Command { + + Vector<int> indices; + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + int count; + + CommandPolygon() { type = TYPE_POLYGON; count = 0; } + }; + + struct CommandPolygonPtr : public Command { + + const int* indices; + const Point2* points; + const Point2* uvs; + const Color* colors; + RID texture; + int count; + + CommandPolygonPtr() { type = TYPE_POLYGON_PTR; count = 0; } + }; + + struct CommandCircle : public Command { + + Point2 pos; + float radius; + Color color; + CommandCircle() { type = TYPE_CIRCLE; } + }; + + struct CommandTransform : public Command { + + Matrix32 xform; + CommandTransform() { type = TYPE_TRANSFORM; } + }; + + struct CommandBlendMode : public Command { + + VS::MaterialBlendMode blend_mode; + CommandBlendMode() { type = TYPE_BLEND_MODE; blend_mode = VS::MATERIAL_BLEND_MODE_MIX; } + }; + struct CommandClipIgnore : public Command { + + bool ignore; + CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; } + }; + + + struct ViewportRender { + VisualServer*owner; + void* udata; + Rect2 rect; + }; + + Matrix32 xform; + bool clip; + bool visible; + bool ontop; + VS::MaterialBlendMode blend_mode; + int light_mask; + Vector<Command*> commands; + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + CanvasItem*next; + CanvasItemMaterial* material; + struct CopyBackBuffer { + Rect2 rect; + Rect2 screen_rect; + bool full; + }; + CopyBackBuffer *copy_back_buffer; + + + float final_opacity; + Matrix32 final_transform; + Rect2 final_clip_rect; + CanvasItem* final_clip_owner; + CanvasItem* material_owner; + ViewportRender *vp_render; + bool distance_field; + + Rect2 global_rect_cache; + + const Rect2& get_rect() const { + if (custom_rect || !rect_dirty) + return rect; + + //must update rect + int s=commands.size(); + if (s==0) { + + rect=Rect2(); + rect_dirty=false; + return rect; + } + + Matrix32 xf; + bool found_xform=false; + bool first=true; + + const CanvasItem::Command * const *cmd = &commands[0]; + + + for (int i=0;i<s;i++) { + + const CanvasItem::Command *c=cmd[i]; + Rect2 r; + + switch(c->type) { + case CanvasItem::Command::TYPE_LINE: { + + const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); + r.pos=line->from; + r.expand_to(line->to); + } break; + case CanvasItem::Command::TYPE_RECT: { + + const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); + r=crect->rect; + + } break; + case CanvasItem::Command::TYPE_STYLE: { + + const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); + r=style->rect; + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); + r.pos=primitive->points[0]; + for(int i=1;i<primitive->points.size();i++) { + + r.expand_to(primitive->points[i]); + + } + } break; + case CanvasItem::Command::TYPE_POLYGON: { + + const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); + int l = polygon->points.size(); + const Point2*pp=&polygon->points[0]; + r.pos=pp[0]; + for(int i=1;i<l;i++) { + + r.expand_to(pp[i]); + + } + } break; + + case CanvasItem::Command::TYPE_POLYGON_PTR: { + + const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); + int l = polygon->count; + if (polygon->indices != NULL) { + + r.pos=polygon->points[polygon->indices[0]]; + for (int i=1; i<polygon->count; i++) { + + r.expand_to(polygon->points[polygon->indices[i]]); + }; + } else { + r.pos=polygon->points[0]; + for (int i=1; i<polygon->count; i++) { + + r.expand_to(polygon->points[i]); + }; + }; + } break; + case CanvasItem::Command::TYPE_CIRCLE: { + + const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); + r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; + r.size=Point2(circle->radius*2.0,circle->radius*2.0); + } break; + case CanvasItem::Command::TYPE_TRANSFORM: { + + const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); + xf=transform->xform; + found_xform=true; + continue; + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + } break; + case CanvasItem::Command::TYPE_CLIP_IGNORE: { + + } break; + } + + if (found_xform) { + r = xf.xform(r); + found_xform=false; + } + + + if (first) { + rect=r; + first=false; + } else + rect=rect.merge(r); + } + + rect_dirty=false; + return rect; + } + + void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL;} + CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; } + virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } + }; + + + CanvasItemDrawViewportFunc draw_viewport_func; + + + virtual void begin_canvas_bg()=0; virtual void canvas_begin()=0; virtual void canvas_disable_blending()=0; virtual void canvas_set_opacity(float p_opacity)=0; @@ -568,7 +935,39 @@ public: virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width)=0; virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0; virtual void canvas_set_transform(const Matrix32& p_transform)=0; - + + virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0; + virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0; + /* LIGHT SHADOW MAPPING */ + + virtual RID canvas_light_occluder_create()=0; + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0; + + + virtual RID canvas_light_shadow_buffer_create(int p_width)=0; + + struct CanvasLightOccluderInstance { + + + bool enabled; + RID canvas; + RID polygon; + RID polygon_buffer; + Rect2 aabb_cache; + Matrix32 xform; + Matrix32 xform_cache; + int light_mask; + VS::CanvasOccluderPolygonCullMode cull_cache; + + CanvasLightOccluderInstance *next; + + CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + }; + + + + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; + /* ENVIRONMENT */ @@ -586,6 +985,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0; virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height)=0; + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0; + /*MISC*/ @@ -603,6 +1006,8 @@ public: virtual bool is_environment(const RID& p_rid) const=0; virtual bool is_shader(const RID& p_rid) const=0; + virtual bool is_canvas_light_occluder(const RID& p_rid) const=0; + virtual void free(const RID& p_rid)=0; virtual void init()=0; diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp index 637c251cf1..45b29f5484 100644 --- a/servers/visual/rasterizer_dummy.cpp +++ b/servers/visual/rasterizer_dummy.cpp @@ -221,6 +221,21 @@ void RasterizerDummy::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_ } + +void RasterizerDummy::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + +} + +RID RasterizerDummy::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const { + + return RID(); +} + +Variant RasterizerDummy::shader_get_default_param(RID p_shader, const StringName& p_name) { + + return Variant(); +} + /* COMMON MATERIAL API */ @@ -1530,9 +1545,36 @@ void RasterizerDummy::end_frame() { } +RID RasterizerDummy::canvas_light_occluder_create() { + return RID(); +} + +void RasterizerDummy::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) { + + +} + +RID RasterizerDummy::canvas_light_shadow_buffer_create(int p_width) { + + return RID(); +} + +void RasterizerDummy::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) { + + +} + +void RasterizerDummy::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) { + + +} + /* CANVAS API */ +void RasterizerDummy::begin_canvas_bg() { + +} void RasterizerDummy::canvas_begin() { @@ -1607,6 +1649,11 @@ void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) { } +void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) { + + +} + /* ENVIRONMENT */ RID RasterizerDummy::environment_create() { @@ -1679,6 +1726,18 @@ Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + +RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) { + + return sampled_light_owner.make_rid(memnew(SampledLight)); +} + +void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { + + +} + + /*MISC*/ bool RasterizerDummy::is_texture(const RID& p_rid) const { @@ -1729,6 +1788,11 @@ bool RasterizerDummy::is_environment(const RID& p_rid) const { return environment_owner.owns(p_rid); } +bool RasterizerDummy::is_canvas_light_occluder(const RID& p_rid) const { + + return false; +} + bool RasterizerDummy::is_shader(const RID& p_rid) const { return false; @@ -1816,6 +1880,14 @@ void RasterizerDummy::free(const RID& p_rid) { Environment *env = environment_owner.get( p_rid ); environment_owner.free(p_rid); memdelete( env ); + } else if (sampled_light_owner.owns(p_rid)) { + + SampledLight *sampled_light = sampled_light_owner.get( p_rid ); + ERR_FAIL_COND(!sampled_light); + + sampled_light_owner.free(p_rid); + memdelete( sampled_light ); + }; } diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index 373564249e..99c76a1917 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/servers/visual/rasterizer_dummy.h @@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -422,6 +429,12 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); + /* COMMON MATERIAL API */ virtual RID material_create(); @@ -683,6 +696,7 @@ public: /* CANVAS API */ + virtual void begin_canvas_bg(); virtual void canvas_begin(); virtual void canvas_disable_blending(); virtual void canvas_set_opacity(float p_opacity); @@ -697,6 +711,16 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); virtual void canvas_set_transform(const Matrix32& p_transform); + virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light); + + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines); + + virtual RID canvas_light_shadow_buffer_create(int p_width); + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache); + + virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow); + /* ENVIRONMENT */ virtual RID environment_create(); @@ -713,6 +737,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height); + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); + /*MISC*/ @@ -728,6 +756,7 @@ public: virtual bool is_particles_instance(const RID& p_rid) const; virtual bool is_skeleton(const RID& p_rid) const; virtual bool is_environment(const RID& p_rid) const; + virtual bool is_canvas_light_occluder(const RID& p_rid) const; virtual bool is_shader(const RID& p_rid) const; diff --git a/servers/visual/shader_graph.h b/servers/visual/shader_graph.h index 5c5079202f..fe305f3955 100644 --- a/servers/visual/shader_graph.h +++ b/servers/visual/shader_graph.h @@ -26,8 +26,6 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_GRAPH_H -#define SHADER_GRAPH_H #if 0 @@ -109,4 +107,3 @@ public: }; #endif -#endif diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index ca219b13a4..4ad8aa6c71 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -56,6 +56,7 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "TYPE_VEC2", "TYPE_VEC3", "TYPE_VEC4", + "TYPE_MAT2", "TYPE_MAT3", "TYPE_MAT4", "TYPE_TEXTURE", @@ -403,9 +404,9 @@ ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_le {TK_TYPE_TEXTURE,"texture"}, {TK_TYPE_CUBEMAP,"cubemap"}, {TK_TYPE_COLOR,"color"}, - /* + {TK_TYPE_MAT2,"mat2"}, - {TK_TYPE_MAT3,"mat3"}, + /*{TK_TYPE_MAT3,"mat3"}, {TK_TYPE_MAT4,"mat3"},*/ {TK_TYPE_MAT3,"mat3"}, {TK_TYPE_MAT4,"mat4"}, @@ -436,7 +437,10 @@ ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_le return Token(TK_INDENTIFIER,str); } - return Token(TK_ERROR,"Unknown character"); + if (GETCHAR(0)>32) + return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'"); + else + return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))); } break; } @@ -463,9 +467,9 @@ Error ShaderLanguage::tokenize(const String& p_text,Vector<Token> *p_tokens,Stri if (t.type==TK_ERROR) { if (r_error) { - return ERR_COMPILATION_FAILED; *r_error=t.text; *r_err_line=line; + return ERR_COMPILATION_FAILED; } } @@ -508,6 +512,7 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) { (p_type==TK_TYPE_VEC3) || (p_type==TK_TYPE_VEC4) || (p_type==TK_TYPE_COLOR) || + (p_type==TK_TYPE_MAT2) || (p_type==TK_TYPE_MAT3) || (p_type==TK_TYPE_MAT4) || (p_type==TK_TYPE_CUBEMAP) || @@ -526,6 +531,7 @@ ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { case TK_TYPE_VEC3: return TYPE_VEC3; case TK_TYPE_VEC4: return TYPE_VEC4; case TK_TYPE_COLOR: return TYPE_VEC4; + case TK_TYPE_MAT2: return TYPE_MAT2; case TK_TYPE_MAT3: return TYPE_MAT3; case TK_TYPE_MAT4: return TYPE_MAT4; case TK_TYPE_TEXTURE: return TYPE_TEXTURE; @@ -547,6 +553,7 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_VEC2: return "vec2"; case TYPE_VEC3: return "vec3"; case TYPE_VEC4: return "vec4"; + case TYPE_MAT2: return "mat2"; case TYPE_MAT3: return "mat3"; case TYPE_MAT4: return "mat4"; case TYPE_TEXTURE: return "texture"; @@ -567,6 +574,7 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) { (p_type==TK_TYPE_VEC3) || (p_type==TK_TYPE_VEC4) || (p_type==TK_TYPE_COLOR) || + (p_type==TK_TYPE_MAT2) || (p_type==TK_TYPE_MAT3) || (p_type==TK_TYPE_MAT4) || (p_type==TK_TYPE_TEXTURE) || @@ -765,16 +773,21 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ //constructors {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_VOID}}, {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC2,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC2,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"mat2",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"mat3",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"mat4",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, //intrinsics - trigonometry @@ -853,6 +866,9 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, @@ -890,6 +906,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"normalize",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"normalize",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, {"reflect",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"refract",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, //intrinsics - texture {"tex",TYPE_VEC4,{TYPE_TEXTURE,TYPE_VEC2,TYPE_VOID}}, {"texcube",TYPE_VEC4,{TYPE_CUBEMAP,TYPE_VEC3,TYPE_VOID}}, @@ -907,6 +924,7 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ {OP_ASSIGN,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, {OP_ASSIGN,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, + {OP_ASSIGN,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}}, {OP_ASSIGN,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}}, {OP_ASSIGN,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}}, {OP_ADD,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, @@ -922,6 +940,8 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}}, {OP_MUL,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}}, {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT3}}, + {OP_MUL,TYPE_VEC2,{TYPE_MAT2,TYPE_VEC2}}, + {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT2}}, {OP_MUL,TYPE_VEC2,{TYPE_MAT3,TYPE_VEC2}}, {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT4}}, {OP_MUL,TYPE_VEC2,{TYPE_MAT4,TYPE_VEC2}}, @@ -936,6 +956,7 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ {OP_MUL,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}}, {OP_MUL,TYPE_VEC4,{TYPE_MAT4,TYPE_VEC4}}, {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_MAT4}}, + {OP_MUL,TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2}}, {OP_MUL,TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3}}, {OP_MUL,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, {OP_DIV,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, @@ -952,22 +973,28 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, + {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, + {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, + {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, + {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, + {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, + {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_VEC2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_VEC2}}, + {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_MAT2}}, + {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}}, + {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT3}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_VEC3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_VEC3}}, + {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT4}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_VEC4}}, + {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_MAT4}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}}, {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}}, {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, @@ -1038,7 +1065,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={ { "VERTEX", TYPE_VEC3}, - { "POSITION", TYPE_VEC3}, + { "POSITION", TYPE_VEC4}, { "NORMAL", TYPE_VEC3}, { "TANGENT", TYPE_VEC3}, { "BINORMAL", TYPE_VEC3}, @@ -1089,6 +1116,72 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={ }; + + +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={ + + { "SRC_VERTEX", TYPE_VEC2}, + { "VERTEX", TYPE_VEC2}, + { "WORLD_VERTEX", TYPE_VEC2}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "POINT_SIZE", TYPE_FLOAT}, + + //builtins + { "WORLD_MATRIX", TYPE_MAT4}, + { "PROJECTION_MATRIX", TYPE_MAT4}, + { "EXTRA_MATRIX", TYPE_MAT4}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID}, +}; +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={ + + { "SRC_COLOR", TYPE_VEC4}, + { "POSITION", TYPE_VEC4}, + { "NORMAL", TYPE_VEC3}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "TEXTURE", TYPE_TEXTURE}, + { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "SCREEN_UV", TYPE_VEC2}, + { "POINT_COORD", TYPE_VEC2}, + +// { "SCREEN_POS", TYPE_VEC2}, +// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID} + +}; + +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ + + { "POSITION", TYPE_VEC4}, + { "NORMAL", TYPE_VEC3}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "TEXTURE", TYPE_TEXTURE}, + { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "SCREEN_UV", TYPE_VEC2}, + { "LIGHT_VEC", TYPE_VEC2}, + { "LIGHT_HEIGHT", TYPE_FLOAT}, + { "LIGHT_COLOR", TYPE_VEC4}, + { "LIGHT_UV", TYPE_VEC2}, + { "LIGHT", TYPE_VEC4}, + { "SHADOW", TYPE_VEC4}, + { "POINT_COORD", TYPE_VEC2}, +// { "SCREEN_POS", TYPE_VEC2}, +// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID} + +}; + const ShaderLanguage::BuiltinsDef ShaderLanguage::postprocess_fragment_builtins_defs[]={ { "IN_COLOR", TYPE_VEC3}, @@ -1201,9 +1294,25 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper Variant data; switch(p_func->return_cache) { case TYPE_FLOAT: data = cdata[0]; break; - case TYPE_VEC2: data = Vector2(cdata[0],cdata[1]); break; - case TYPE_VEC3: data = Vector3(cdata[0],cdata[1],cdata[2]); break; - case TYPE_VEC4: data = Plane(cdata[0],cdata[1],cdata[2],cdata[3]); break; + case TYPE_VEC2: + if (cdata.size()==1) + data = Vector2(cdata[0],cdata[0]); + else + data = Vector2(cdata[0],cdata[1]); + + break; + case TYPE_VEC3: + if (cdata.size()==1) + data = Vector3(cdata[0],cdata[0],cdata[0]); + else + data = Vector3(cdata[0],cdata[1],cdata[2]); + break; + case TYPE_VEC4: + if (cdata.size()==1) + data = Plane(cdata[0],cdata[0],cdata[0],cdata[0]); + else + data = Plane(cdata[0],cdata[1],cdata[2],cdata[3]); + break; } cn->datatype=p_func->return_cache; @@ -1469,6 +1578,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex case TYPE_VEC2: name="vec2"; break; case TYPE_VEC3: name="vec3"; break; case TYPE_VEC4: name="vec4"; break; + case TYPE_MAT2: name="mat2"; break; case TYPE_MAT3: name="mat3"; break; case TYPE_MAT4: name="mat4"; break; default: ERR_FAIL_V(ERR_BUG); @@ -1763,6 +1873,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex } } break; + case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break; case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break; case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break; default: {} @@ -1970,7 +2081,9 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex at+=get_datatype_name(compute_node_type(op->arguments[i])); } - parser.set_error("Invalid arguments to operator "+String(token_names[op->op])+": "+at); + static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"}; + + parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at); return ERR_PARSE_ERROR; } expression.remove(next_op); @@ -2147,6 +2260,7 @@ Error ShaderLanguage::parse_variable_declaration(Parser& parser,BlockNode *p_blo case TYPE_VEC2: con->value=Vector2(); break; case TYPE_VEC3: con->value=Vector3(); break; case TYPE_VEC4: con->value=iscolor?Variant(Color()):Variant(Plane()); break; + case TYPE_MAT2: con->value=Matrix32(); break; case TYPE_MAT3: con->value=Matrix3(); break; case TYPE_MAT4: con->value=Transform(); break; case TYPE_TEXTURE: @@ -2439,6 +2553,27 @@ Error ShaderLanguage::parse(const Vector<Token>& p_tokens,ShaderType p_type,Comp idx++; } } break; + case SHADER_CANVAS_ITEM_VERTEX: { + int idx=0; + while (ci_vertex_builtins_defs[idx].name) { + parser.program->builtin_variables[ci_vertex_builtins_defs[idx].name]=ci_vertex_builtins_defs[idx].type; + idx++; + } + } break; + case SHADER_CANVAS_ITEM_FRAGMENT: { + int idx=0; + while (ci_fragment_builtins_defs[idx].name) { + parser.program->builtin_variables[ci_fragment_builtins_defs[idx].name]=ci_fragment_builtins_defs[idx].type; + idx++; + } + } break; + case SHADER_CANVAS_ITEM_LIGHT: { + int idx=0; + while (ci_light_builtins_defs[idx].name) { + parser.program->builtin_variables[ci_light_builtins_defs[idx].name]=ci_light_builtins_defs[idx].type; + idx++; + } + } break; case SHADER_POST_PROCESS: { int idx=0; while (postprocess_fragment_builtins_defs[idx].name) { @@ -2485,6 +2620,9 @@ Error ShaderLanguage::compile(const String& p_code,ShaderType p_type,CompileFunc uint64_t t = OS::get_singleton()->get_ticks_usec(); Error err = tokenize(p_code,&tokens,r_error,r_err_line,r_err_column); + if (err!=OK) { + print_line("tokenizer error!"); + } double tf = (OS::get_singleton()->get_ticks_usec()-t)/1000.0; //print_line("tokenize time: "+rtos(tf)); @@ -2505,12 +2643,20 @@ void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keyword int idx=0; + p_keywords->push_back("uniform"); + p_keywords->push_back("texture"); + p_keywords->push_back("cubemap"); + p_keywords->push_back("color"); + p_keywords->push_back("if"); + p_keywords->push_back("else"); + while(intrinsic_func_defs[idx].name) { p_keywords->push_back(intrinsic_func_defs[idx].name); idx++; } + switch(p_type) { case SHADER_MATERIAL_VERTEX: { idx=0; @@ -2533,6 +2679,28 @@ void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keyword idx++; } } break; + case SHADER_CANVAS_ITEM_VERTEX: { + idx=0; + while (ci_vertex_builtins_defs[idx].name) { + p_keywords->push_back(ci_vertex_builtins_defs[idx].name); + idx++; + } + } break; + case SHADER_CANVAS_ITEM_FRAGMENT: { + idx=0; + while (ci_fragment_builtins_defs[idx].name) { + p_keywords->push_back(ci_fragment_builtins_defs[idx].name); + idx++; + } + } break; + case SHADER_CANVAS_ITEM_LIGHT: { + idx=0; + while (ci_light_builtins_defs[idx].name) { + p_keywords->push_back(ci_light_builtins_defs[idx].name); + idx++; + } + } break; + case SHADER_POST_PROCESS: { idx=0; while (postprocess_fragment_builtins_defs[idx].name) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 7e01368dd5..7777c8bcf3 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -56,6 +56,7 @@ public: TK_TYPE_VEC2, TK_TYPE_VEC3, TK_TYPE_VEC4, + TK_TYPE_MAT2, TK_TYPE_MAT3, TK_TYPE_MAT4, TK_TYPE_TEXTURE, @@ -105,6 +106,9 @@ public: SHADER_MATERIAL_VERTEX, SHADER_MATERIAL_FRAGMENT, SHADER_MATERIAL_LIGHT, + SHADER_CANVAS_ITEM_VERTEX, + SHADER_CANVAS_ITEM_FRAGMENT, + SHADER_CANVAS_ITEM_LIGHT, SHADER_POST_PROCESS, }; @@ -115,6 +119,7 @@ public: TYPE_VEC2, TYPE_VEC3, TYPE_VEC4, + TYPE_MAT2, TYPE_MAT3, TYPE_MAT4, TYPE_TEXTURE, @@ -376,6 +381,12 @@ private: static const BuiltinsDef vertex_builtins_defs[]; static const BuiltinsDef fragment_builtins_defs[]; static const BuiltinsDef light_builtins_defs[]; + + static const BuiltinsDef ci_vertex_builtins_defs[]; + static const BuiltinsDef ci_fragment_builtins_defs[]; + static const BuiltinsDef ci_light_builtins_defs[]; + + static const BuiltinsDef postprocess_fragment_builtins_defs[]; static DataType get_token_datatype(TokenType p_type); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 8250e4c08f..7a9db4ba11 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -157,6 +157,16 @@ void VisualServerRaster::shader_get_param_list(RID p_shader, List<PropertyInfo> } +void VisualServerRaster::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + + rasterizer->shader_set_default_texture_param(p_shader,p_name,p_texture); +} + +RID VisualServerRaster::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + + return rasterizer->shader_get_default_texture_param(p_shader,p_name); +} + /* Material */ @@ -1109,8 +1119,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< int tex_w; int tex_h; + int light_tex_w; + int light_tex_h; bool is16; + bool has_light_tex=false; { + DVector<uint8_t>::Read r=p_octree.read(); tex_w = decode_uint32(&r[0]); tex_h = decode_uint32(&r[4]); @@ -1123,7 +1137,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< baked_light->data.octree_steps=decode_uint32(&r[16]); baked_light->data.octree_tex_pixel_size.x=1.0/tex_w; baked_light->data.octree_tex_pixel_size.y=1.0/tex_h; + baked_light->data.texture_multiplier=decode_uint32(&r[20]); + light_tex_w=decode_uint16(&r[24]); + light_tex_h=decode_uint16(&r[26]); + print_line("ltexw "+itos(light_tex_w)); + print_line("ltexh "+itos(light_tex_h)); + + if (light_tex_w>0 && light_tex_h>0) { + baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w; + baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h; + has_light_tex=true; + } else { + baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size; + + } + baked_light->octree_aabb.pos.x=decode_float(&r[32]); @@ -1141,12 +1170,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< rasterizer->free(baked_light->data.octree_texture); baked_light->data.octree_texture=RID(); + baked_light->octree_tex_size.x=0; + baked_light->octree_tex_size.y=0; + } + } + + if (baked_light->data.light_texture.is_valid()) { + if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) { + rasterizer->free(baked_light->data.light_texture); + baked_light->data.light_texture=RID(); + baked_light->light_tex_size.x=0; + baked_light->light_tex_size.y=0; } } if (!baked_light->data.octree_texture.is_valid()) { baked_light->data.octree_texture=rasterizer->texture_create(); rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->octree_tex_size.x=tex_w; + baked_light->octree_tex_size.y=tex_h; + } + + if (!baked_light->data.light_texture.is_valid() && has_light_tex) { + baked_light->data.light_texture=rasterizer->texture_create(); + rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + baked_light->light_tex_size.x=light_tex_w; + baked_light->light_tex_size.y=light_tex_h; + } Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); @@ -1159,6 +1209,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< } + DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ @@ -1174,6 +1225,67 @@ DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) c } } +void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) { + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + ERR_FAIL_COND(p_light.size()==0); + + int tex_w=baked_light->light_tex_size.x; + int tex_h=baked_light->light_tex_size.y; + + ERR_FAIL_COND(tex_w==0 && tex_h==0); + ERR_FAIL_COND(!baked_light->data.light_texture.is_valid()); + + + + print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size())); + + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light); + rasterizer->texture_set_data(baked_light->data.light_texture,img); + + + +} + +DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>()); + + if (rasterizer->is_texture(baked_light->data.light_texture)) { + + Image img = rasterizer->texture_get_data(baked_light->data.light_texture); + return img.get_data(); + } else { + return DVector<uint8_t>(); + } +} + + + +void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + + baked_light->sampler=p_sampler; + + + +} + +DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<int>()); + + return baked_light->sampler; + +} + + void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){ VS_CHANGED; @@ -1192,6 +1304,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){ } +/* BAKED LIGHT SAMPLER */ + +RID VisualServerRaster::baked_light_sampler_create() { + + BakedLightSampler * blsamp = memnew( BakedLightSampler ); + RID rid = baked_light_sampler_owner.make_rid(blsamp); + _update_baked_light_sampler_dp_cache(blsamp); + return rid; +} + +void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){ + + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX); + blsamp->params[p_param]=p_value; + _dependency_queue_update(p_baked_light_sampler,true); +} + +float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{ + + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0); + return blsamp->params[p_param]; +} + +void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) { + + int res = blsamp->resolution; + blsamp->dp_cache.resize(res*res*2); + Vector3 *dp_normals=blsamp->dp_cache.ptr(); + + for(int p=0;p<2;p++) { + float sign = p==0?1:-1; + int ofs = res*res*p; + for(int i=0;i<res;i++) { + for(int j=0;j<res;j++) { + + Vector2 v( + (i/float(res))*2.0-1.0, + (j/float(res))*2.0-1.0 + ); + + float l=v.length(); + if (l>1.0) { + v/=l; + l=1.0; //clamp to avoid imaginary + } + v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function + Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z + n.y*=sign; + dp_normals[j*res+i+ofs]=n; + } + } + } + +} + +void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>64); + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + blsamp->resolution=p_resolution; + _update_baked_light_sampler_dp_cache(blsamp); + +} +int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{ + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + return blsamp->resolution; +} + /* CAMERA API */ RID VisualServerRaster::camera_create() { @@ -1386,6 +1576,15 @@ void VisualServerRaster::viewport_set_render_target_vflip(RID p_viewport,bool p_ } +void VisualServerRaster::viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable) { + + Viewport *viewport = viewport_owner.get( p_viewport ); + ERR_FAIL_COND(!viewport); + + viewport->render_target_clear_on_new_frame=p_enable; + +} + void VisualServerRaster::viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect) { Viewport *viewport = viewport_owner.get( p_viewport ); @@ -1404,6 +1603,23 @@ bool VisualServerRaster::viewport_get_render_target_vflip(RID p_viewport) const{ } +bool VisualServerRaster::viewport_get_render_target_clear_on_new_frame(RID p_viewport) const{ + + const Viewport *viewport = viewport_owner.get( p_viewport ); + ERR_FAIL_COND_V(!viewport,false); + + return viewport->render_target_clear_on_new_frame; + +} + +void VisualServerRaster::viewport_render_target_clear(RID p_viewport) { + + Viewport *viewport = viewport_owner.get( p_viewport ); + ERR_FAIL_COND(!viewport); + + viewport->render_target_clear=true; + +} void VisualServerRaster::viewport_queue_screen_capture(RID p_viewport) { @@ -1477,6 +1693,17 @@ void VisualServerRaster::viewport_set_hide_canvas(RID p_viewport,bool p_hide) { } +void VisualServerRaster::viewport_set_disable_environment(RID p_viewport,bool p_disable) { + + VS_CHANGED; + + Viewport *viewport=NULL; + viewport = viewport_owner.get( p_viewport ); + ERR_FAIL_COND(!viewport); + viewport->disable_environment=p_disable; + +} + void VisualServerRaster::viewport_attach_camera(RID p_viewport,RID p_camera) { VS_CHANGED; @@ -1943,6 +2170,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { } + if (instance->baked_light_sampler_info) { + + while (instance->baked_light_sampler_info->owned_instances.size()) { + + instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->baked_light_sampler_info->sampled_light); + } + memdelete( instance->baked_light_sampler_info ); + instance->baked_light_sampler_info=NULL; + } + instance->data.morph_values.clear(); } @@ -1992,6 +2233,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { //instance->portal_info = memnew(Instance::PortalInfo); //instance->portal_info->portal=portal_owner.get(p_base); + } else if (baked_light_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER; + instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->baked_light_sampler_info->sampler=baked_light_sampler_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + } else { ERR_EXPLAIN("Invalid base RID for instance!") ERR_FAIL(); @@ -2607,11 +2858,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{ const Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND_V( !instance,RID() ); if (instance->baked_light) - instance->baked_light->self; + return instance->baked_light->self; return RID(); } + +void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->sampled_light) { + instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); + instance->data.sampled_light=RID(); + } + + if(p_baked_light_sampler.is_valid()) { + Instance *sampler_instance = instance_owner.get( p_baked_light_sampler ); + ERR_FAIL_COND( !sampler_instance ); + ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER ); + instance->sampled_light=sampler_instance; + instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance); + } else { + instance->sampled_light=NULL; + } + + instance->data.sampled_light=RID(); + +} + +RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const { + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,RID() ); + + if (instance->sampled_light) + return instance->sampled_light->self; + else + return RID(); + +} + + void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){ VS_CHANGED; @@ -2747,6 +3037,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { pairable=true; } + if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) { + + pairable_mask=(1<<INSTANCE_BAKED_LIGHT); + pairable=true; + } + + if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { base_type|=INSTANCE_ROOMLESS_MASK; @@ -2859,6 +3156,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) { new_aabb=baked_light->octree_aabb; } break; + case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: { + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid ); + ERR_FAIL_COND(!baked_light_sampler); + float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; + default: {} } @@ -2925,6 +3232,7 @@ RID VisualServerRaster::canvas_create() { return rid; } + void VisualServerRaster::canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring) { Canvas * canvas = canvas_owner.get(p_canvas); @@ -2950,6 +3258,14 @@ Point2 VisualServerRaster::canvas_get_item_mirroring(RID p_canvas,RID p_item) co return canvas->child_items[idx].mirror; } +void VisualServerRaster::canvas_set_modulate(RID p_canvas,const Color& p_color) { + + Canvas * canvas = canvas_owner.get(p_canvas); + ERR_FAIL_COND(!canvas); + canvas->modulate=p_color; +} + + RID VisualServerRaster::canvas_item_create() { @@ -3035,14 +3351,27 @@ bool VisualServerRaster::canvas_item_is_visible(RID p_item) const { } +void VisualServerRaster::canvas_item_set_light_mask(RID p_canvas_item,int p_mask) { + + VS_CHANGED; + + CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item ); + ERR_FAIL_COND(!canvas_item); + + if (canvas_item->light_mask==p_mask) + return; + VS_CHANGED; + + canvas_item->light_mask=p_mask; + +} + + void VisualServerRaster::canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend) { VS_CHANGED; CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item ); - if (!canvas_item) { - printf("!canvas_item\n"); - }; ERR_FAIL_COND(!canvas_item); if (canvas_item->blend_mode==p_blend) @@ -3082,130 +3411,15 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) { canvas_item->clip=p_clip; } -const Rect2& VisualServerRaster::CanvasItem::get_rect() const { - - if (custom_rect || !rect_dirty) - return rect; - - //must update rect - int s=commands.size(); - if (s==0) { - - rect=Rect2(); - rect_dirty=false; - return rect; - } - - Matrix32 xf; - bool found_xform=false; - bool first=true; - - const CanvasItem::Command * const *cmd = &commands[0]; - - - for (int i=0;i<s;i++) { - - const CanvasItem::Command *c=cmd[i]; - Rect2 r; - - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); - r.pos=line->from; - r.expand_to(line->to); - } break; - case CanvasItem::Command::TYPE_RECT: { - - const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); - r=crect->rect; - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); - r=style->rect; - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); - r.pos=primitive->points[0]; - for(int i=1;i<primitive->points.size();i++) { - - r.expand_to(primitive->points[i]); - - } - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); - int l = polygon->points.size(); - const Point2*pp=&polygon->points[0]; - r.pos=pp[0]; - for(int i=1;i<l;i++) { - - r.expand_to(pp[i]); - - } - } break; - - case CanvasItem::Command::TYPE_POLYGON_PTR: { - - const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); - int l = polygon->count; - if (polygon->indices != NULL) { - - r.pos=polygon->points[polygon->indices[0]]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[polygon->indices[i]]); - }; - } else { - r.pos=polygon->points[0]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[i]); - }; - }; - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); - r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; - r.size=Point2(circle->radius*2.0,circle->radius*2.0); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); - xf=transform->xform; - found_xform=true; - continue; - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - } break; - } - - if (found_xform) { - r = xf.xform(r); - found_xform=false; - } - - - if (first) { - rect=r; - first=false; - } else - rect=rect.merge(r); - } +void VisualServerRaster::canvas_item_set_distance_field_mode(RID p_item, bool p_distance_field) { + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); - rect_dirty=false; - return rect; + canvas_item->distance_field=p_distance_field; } + void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) { VS_CHANGED; @@ -3323,7 +3537,7 @@ void VisualServerRaster::canvas_item_add_circle(RID p_item, const Point2& p_pos, } -void VisualServerRaster::canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile,const Color& p_modulate) { +void VisualServerRaster::canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile,const Color& p_modulate,bool p_transpose) { VS_CHANGED; CanvasItem *canvas_item = canvas_item_owner.get( p_item ); ERR_FAIL_COND(!canvas_item); @@ -3346,12 +3560,16 @@ void VisualServerRaster::canvas_item_add_texture_rect(RID p_item, const Rect2& p rect->flags|=Rasterizer::CANVAS_RECT_FLIP_V; rect->rect.size.y = -rect->rect.size.y; } + if (p_transpose) { + rect->flags|=Rasterizer::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } rect->texture=p_texture; canvas_item->rect_dirty=true; canvas_item->commands.push_back(rect); } -void VisualServerRaster::canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate) { +void VisualServerRaster::canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate,bool p_transpose) { VS_CHANGED; CanvasItem *canvas_item = canvas_item_owner.get( p_item ); ERR_FAIL_COND(!canvas_item); @@ -3374,12 +3592,17 @@ void VisualServerRaster::canvas_item_add_texture_rect_region(RID p_item, const R rect->flags|=Rasterizer::CANVAS_RECT_FLIP_V; rect->rect.size.y = -rect->rect.size.y; } + if (p_transpose) { + rect->flags|=Rasterizer::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } canvas_item->rect_dirty=true; canvas_item->commands.push_back(rect); } + void VisualServerRaster::canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center,const Color& p_modulate) { VS_CHANGED; @@ -3542,6 +3765,72 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen canvas_item->commands.push_back(bm); }; +void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { + + ERR_FAIL_COND(p_z<CANVAS_ITEM_Z_MIN || p_z>CANVAS_ITEM_Z_MAX); + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z=p_z; + +} + +void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z_relative=p_enable; + +} + +void VisualServerRaster::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2& p_rect) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) { + if (p_enable) { + canvas_item->copy_back_buffer = memnew( Rasterizer::CanvasItem::CopyBackBuffer ); + } else { + memdelete(canvas_item->copy_back_buffer); + canvas_item->copy_back_buffer=NULL; + } + } + + if (p_enable) { + canvas_item->copy_back_buffer->rect=p_rect; + canvas_item->copy_back_buffer->full=p_rect==Rect2(); + } + +} + +void VisualServerRaster::canvas_item_set_use_parent_material(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->use_parent_material=p_enable; + +} + +void VisualServerRaster::canvas_item_set_material(RID p_item, RID p_material) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + + if (canvas_item->material) + canvas_item->material->owners.erase(canvas_item); + + canvas_item->material=NULL; + + if (canvas_item_material_owner.owns(p_material)) { + canvas_item->material=canvas_item_material_owner.get(p_material); + canvas_item->material->owners.insert(canvas_item); + } +} + void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { VS_CHANGED; @@ -3604,6 +3893,399 @@ void VisualServerRaster::canvas_item_raise(RID p_item) { } +/***** CANVAS LIGHT *******/ + +RID VisualServerRaster::canvas_light_create() { + + Rasterizer::CanvasLight *clight = memnew( Rasterizer::CanvasLight ); + return canvas_light_owner.make_rid(clight); +} + +void VisualServerRaster::canvas_light_attach_to_canvas(RID p_light,RID p_canvas){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(clight->canvas); + canvas->lights.erase(clight); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas=RID(); + clight->canvas=p_canvas; + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(clight->canvas); + canvas->lights.insert(clight); + } + + + +} +void VisualServerRaster::canvas_light_set_enabled(RID p_light, bool p_enabled){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->enabled=p_enabled; + +} +void VisualServerRaster::canvas_light_set_transform(RID p_light, const Matrix32& p_transform){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->xform=p_transform; + +} +void VisualServerRaster::canvas_light_set_scale(RID p_light, float p_scale) { + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->scale=p_scale; + +} + + +void VisualServerRaster::canvas_light_set_texture(RID p_light, RID p_texture){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->texture=p_texture; + +} +void VisualServerRaster::canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->texture_offset=p_offset; + +} +void VisualServerRaster::canvas_light_set_color(RID p_light, const Color& p_color){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->color=p_color; + + +} +void VisualServerRaster::canvas_light_set_height(RID p_light, float p_height){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->height=p_height; + +} + +void VisualServerRaster::canvas_light_set_energy(RID p_light, float p_energy){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->energy=p_energy; + +} + +void VisualServerRaster::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->z_min=p_min_z; + clight->z_max=p_max_z; + +} + +void VisualServerRaster::canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer) { + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->layer_min=p_min_layer; + clight->layer_max=p_max_layer; + +} + +void VisualServerRaster::canvas_light_set_item_mask(RID p_light, int p_mask){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->item_mask=p_mask; + +} + +void VisualServerRaster::canvas_light_set_item_shadow_mask(RID p_light, int p_mask){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->item_shadow_mask=p_mask; + +} + + +void VisualServerRaster::canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) { + + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->mode=p_mode; + +} +void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + if (clight->shadow_buffer.is_valid()==p_enabled) + return; + if (p_enabled) { + clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); + } else { + rasterizer->free(clight->shadow_buffer); + clight->shadow_buffer=RID(); + + } + +} + +void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + ERR_FAIL_COND(p_size<32 || p_size>16384); + + clight->shadow_buffer_size=nearest_power_of_2(p_size); + + + if (clight->shadow_buffer.is_valid()) { + rasterizer->free(clight->shadow_buffer); + clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); + } + +} + +void VisualServerRaster::canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier) { + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->shadow_esm_mult=p_multiplier; + +} + +/****** CANVAS LIGHT OCCLUDER ******/ + +RID VisualServerRaster::canvas_light_occluder_create() { + + Rasterizer::CanvasLightOccluderInstance *occluder = memnew( Rasterizer::CanvasLightOccluderInstance ); + + return canvas_light_occluder_owner.make_rid( occluder ); + +} + +void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas) { + + Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas=RID(); + + occluder->canvas=p_canvas; + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.insert(occluder); + } +} + +void VisualServerRaster::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled){ + + Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->enabled=p_enabled; + +} + +void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) { + + Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->polygon.is_valid()) { + CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + } + + occluder->polygon=p_polygon; + occluder->polygon_buffer=RID(); + + if (occluder->polygon.is_valid()) { + CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); + if (!occluder_poly) + occluder->polygon=RID(); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->owners.insert(occluder); + occluder->polygon_buffer=occluder_poly->occluder; + occluder->aabb_cache=occluder_poly->aabb; + occluder->cull_cache=occluder_poly->cull_mode; + } + +} + + + + +void VisualServerRaster::canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform) { + + Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->xform=p_xform; + +} + +void VisualServerRaster::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) { + + Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->light_mask=p_mask; + +} + + +RID VisualServerRaster::canvas_occluder_polygon_create() { + + CanvasLightOccluderPolygon * occluder_poly = memnew( CanvasLightOccluderPolygon ); + occluder_poly->occluder=rasterizer->canvas_light_occluder_create(); + return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); + +} + +void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector<Vector2>& p_shape, bool p_close){ + + if (p_shape.size()<3) { + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape); + return; + } + + DVector<Vector2> lines; + int lc = p_shape.size()*2; + + lines.resize(lc-(p_close?0:2)); + { + DVector<Vector2>::Write w = lines.write(); + DVector<Vector2>::Read r = p_shape.read(); + + int max=lc/2; + if (!p_close) { + max--; + } + for(int i=0;i<max;i++) { + + Vector2 a = r[i]; + Vector2 b = r[(i+1)%(lc/2)]; + w[i*2+0]=a; + w[i*2+1]=b; + } + + } + + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines); +} + +void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) { + + CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + ERR_FAIL_COND(p_shape.size()&1); + + int lc = p_shape.size(); + occluder_poly->aabb=Rect2(); + { + DVector<Vector2>::Read r = p_shape.read(); + for(int i=0;i<lc;i++) { + if (i==0) + occluder_poly->aabb.pos=r[i]; + else + occluder_poly->aabb.expand_to(r[i]); + } + } + + rasterizer->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape); + for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) { + E->get()->aabb_cache=occluder_poly->aabb; + } +} + +void VisualServerRaster::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode) { + + CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->cull_mode=p_mode; + for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) { + E->get()->cull_cache=p_mode; + } + +} + +RID VisualServerRaster::canvas_item_material_create() { + + Rasterizer::CanvasItemMaterial *material = memnew( Rasterizer::CanvasItemMaterial ); + return canvas_item_material_owner.make_rid(material); + +} + +void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_shader){ + + VS_CHANGED; + Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + ERR_FAIL_COND(!material); + material->shader=p_shader; + +} +void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value){ + + VS_CHANGED; + Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + ERR_FAIL_COND(!material); + if (p_value.get_type()==Variant::NIL) + material->shader_param.erase(p_param); + else + material->shader_param[p_param]=p_value; + + +} +Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const{ + Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,Variant()); + if (!material->shader_param.has(p_param)) { + ERR_FAIL_COND_V(!material->shader.is_valid(),Variant()); + return rasterizer->shader_get_default_param(material->shader,p_param); + } + + return material->shader_param[p_param]; +} + +void VisualServerRaster::canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode) { + + VS_CHANGED; + Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + ERR_FAIL_COND(!material); + material->shading_mode=p_mode; + +} + + /******** CANVAS *********/ @@ -3762,6 +4444,17 @@ void VisualServerRaster::free( RID p_rid ) { baked_light_owner.free(p_rid); memdelete(baked_light); + } else if (baked_light_sampler_owner.owns(p_rid)) { + + _free_attached_instances(p_rid); + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid); + ERR_FAIL_COND(!baked_light_sampler); + //if (baked_light->data.octree_texture.is_valid()) + // rasterizer->free(baked_light->data.octree_texture); + baked_light_sampler_owner.free(p_rid); + memdelete(baked_light_sampler); + } else if (camera_owner.owns(p_rid)) { // delete te camera @@ -3813,7 +4506,9 @@ void VisualServerRaster::free( RID p_rid ) { instance_set_room(p_rid,RID()); instance_set_scenario(p_rid,RID()); instance_geometry_set_baked_light(p_rid,RID()); + instance_geometry_set_baked_light_sampler(p_rid,RID()); instance_set_base(p_rid,RID()); + if (instance->data.skeleton.is_valid()) instance_attach_skeleton(p_rid,RID()); @@ -3841,7 +4536,17 @@ void VisualServerRaster::free( RID p_rid ) { canvas->child_items[i].item->parent=RID(); } - + + for (Set<Rasterizer::CanvasLight*>::Element *E=canvas->lights.front();E;E=E->next()) { + + E->get()->canvas=RID(); + } + + for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) { + + E->get()->canvas=RID(); + } + canvas_owner.free( p_rid ); memdelete( canvas ); @@ -3870,9 +4575,82 @@ void VisualServerRaster::free( RID p_rid ) { canvas_item->child_items[i]->parent=RID(); } + if (canvas_item->material) { + canvas_item->material->owners.erase(canvas_item); + } + canvas_item_owner.free( p_rid ); memdelete( canvas_item ); + + } else if (canvas_item_material_owner.owns(p_rid)) { + + Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get(p_rid); + ERR_FAIL_COND(!material); + for(Set<Rasterizer::CanvasItem*>::Element *E=material->owners.front();E;E=E->next()) { + + E->get()->material=NULL; + } + + canvas_item_material_owner.free(p_rid); + memdelete(material); + + } else if (canvas_light_owner.owns(p_rid)) { + + Rasterizer::CanvasLight *canvas_light = canvas_light_owner.get(p_rid); + ERR_FAIL_COND(!canvas_light); + + if (canvas_light->canvas.is_valid()) { + Canvas* canvas = canvas_owner.get(canvas_light->canvas); + if (canvas) + canvas->lights.erase(canvas_light); + } + + if (canvas_light->shadow_buffer.is_valid()) + rasterizer->free(canvas_light->shadow_buffer); + + canvas_light_owner.free( p_rid ); + memdelete( canvas_light ); + + } else if (canvas_light_occluder_owner.owns(p_rid)) { + + Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid); + ERR_FAIL_COND(!occluder); + + if (occluder->polygon.is_valid()) { + + CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + + } + + if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + + } + + canvas_light_occluder_owner.free( p_rid ); + memdelete(occluder); + + } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) { + + CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid); + ERR_FAIL_COND(!occluder_poly); + rasterizer->free(occluder_poly->occluder); + + while(occluder_poly->owners.size()) { + + occluder_poly->owners.front()->get()->polygon=RID(); + occluder_poly->owners.erase( occluder_poly->owners.front() ); + } + + canvas_light_occluder_polygon_owner.free( p_rid ); + memdelete(occluder_poly); + } else if (scenario_owner.owns(p_rid)) { Scenario *scenario=scenario_owner.get(p_rid); @@ -4957,6 +5735,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance //attempt to conncet portal A (will go through B anyway) //this is a little hackish, but works fine in practice + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL); + B->baked_light_sampler_info->baked_lights.insert(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5006,6 +5793,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance self->_portal_attempt_connect(A); self->_portal_attempt_connect(B); + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER); + B->baked_light_sampler_info->baked_lights.erase(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5197,6 +5993,322 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance } +void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) { + + + BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler; + int res = sampler_opts->resolution; + int dp_size = res*res*2; + Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors + Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals + const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr(); + + + if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) { + if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light); + } + + p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution; + p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2); + + + } + + + zeromem(dp_map,sizeof(Color)*dp_size); + bool valid=false; + int samples=0; + + + for(Set<Instance*>::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) { + + Instance *bl = E->get(); + if (bl->baked_light_info->baked_light->sampler.size()==0) + continue; //not usable + + + Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse(); + for(int i=0;i<dp_size;i++) { + dp_normals[i]=norm_xform.xform(dp_src_normals[i]).normalized(); + } + + //normals in place + + + //sample octree + + float r = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION]; + float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH]; + Vector3 s = p_sampled_light->data.transform.basis.get_scale(); + + r*=MAX(MAX(s.x,s.y),s.z); + AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2))); + //ok got octree local AABB + + DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read(); + const int *rptr = rp.ptr(); + + int first = rptr[1]; + int depth = rptr[2]; + bool islinear = rptr[3]&1; + depth+=1; + + AABB aabb; + aabb.pos.x=decode_float((const uint8_t*)&rptr[4]); + aabb.pos.y=decode_float((const uint8_t*)&rptr[5]); + aabb.pos.z=decode_float((const uint8_t*)&rptr[6]); + aabb.size.x=decode_float((const uint8_t*)&rptr[7]); + aabb.size.y=decode_float((const uint8_t*)&rptr[8]); + aabb.size.z=decode_float((const uint8_t*)&rptr[9]); + + uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t)); + int *stack_ptr=(int*)alloca(depth*sizeof(int)); + AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB)); + + stack[0]=0; + stack_ptr[0]=first; + aabb_stack[0]=aabb; + Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5; + + + int stack_pos=0; + Color max_col; + + //int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]; + + int lalimit = sample_aabb.get_longest_axis_index(); + float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit]; + + + while(true) { + + + bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0; + + if (aabb_stack[stack_pos].size[lalimit]<limit) { + leaf=true; + } + + + if (leaf) { + + Vector3 from = aabb_stack[stack_pos].pos + aabb_stack[stack_pos].size * 0.5; + Vector3 norm = (from-center).normalized(); + + + Color col; + col.r = ((rptr[ stack_ptr[stack_pos] ]&0xFFFF)/256.0); + col.g = ((rptr[ stack_ptr[stack_pos]+1 ]>>16)/256.0); + col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0); + + + max_col.r = MAX(max_col.r,col.r); + max_col.g = MAX(max_col.g,col.g); + max_col.b = MAX(max_col.b,col.b); + + if (!islinear && p_linear_colorspace) { + col=col.to_linear(); + } + + float distance; + + if (aabb_stack[stack_pos].has_point(center)) { + distance=0; + } else { + + Vector3 support = aabb_stack[stack_pos].get_support(norm); + distance = Math::absf(norm.dot(support)-norm.dot(center)); + + } + + if (distance>r) + distance=r; + + float mult = Math::pow(1.0-distance/r,att)*str; + if (mult>0) { + col.r*=mult; + col.g*=mult; + col.b*=mult; + + + + for(int i=0;i<dp_size;i++) { + float mult2 = norm.dot(dp_normals[i]); + if (mult2<0) + mult2=0; + Color col2(col.r*mult2,col.g*mult2,col.b*mult2,1.0); + dp_map[i].r=MAX(dp_map[i].r,col2.r); + dp_map[i].g=MAX(dp_map[i].g,col2.g); + dp_map[i].b=MAX(dp_map[i].b,col2.b); + } + + } + + samples++; + //nothing is valid unless you hit a leaf + valid=true; + stack_pos--; + } else if ((stack[stack_pos]&0xFF)<8) { + + int i = stack[stack_pos]&0xFF; + int base = (stack[stack_pos]>>8); + + if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<<i))) { + //no bit, no test + stack[stack_pos]=(base<<8)+(i+1); + continue; + } + + stack[stack_pos]=((base+1)<<8)+(i+1); + + AABB child_aabb = aabb_stack[stack_pos]; + child_aabb.size*=0.5; + if (i&1) + child_aabb.pos.x+=child_aabb.size.x; + if (i&2) + child_aabb.pos.y+=child_aabb.size.y; + if (i&4) + child_aabb.pos.z+=child_aabb.size.z; + + if (!child_aabb.intersects(sample_aabb)) { + continue; + } + + if (child_aabb.encloses(sample_aabb)) { + stack[stack_pos]=(base<<8)|8; //don't test the rest + } + + stack_pos++; + ERR_FAIL_COND(stack_pos>=depth); + + stack[stack_pos]=0; + stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ]; + aabb_stack[stack_pos]=child_aabb; + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + + } + + //print_line("samples "+itos(samples) ); + + if (valid) { + + for(int i=0;i<res;i++) { + //average seams to avoid aliasing + { + //top + int ofs1 = i; + int ofs2 = dp_size-res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //bottom + int ofs1 = res*res-res+i; + int ofs2 = res*res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //left + int ofs1 = i*res; + int ofs2 = res*res+(res-i-1)*res; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //right + int ofs1 = i*res+(res-1); + int ofs2 = res*res+(res-i-1)*res+(res-1); + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + + } + + rasterizer->sampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0); + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light; + } + + + } else { + + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=RID(); //do not use because nothing close + } + } + + + + +/* + highp vec3 vtx = vertex_interp; + vtx.z*=dual_paraboloid.y; //side to affect + vtx.z+=0.01; + dp_clip=vtx.z; + highp float len=length( vtx ); + vtx=normalize(vtx); + vtx.xy/=1.0+vtx.z; + vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near); + vtx+=normalize(vtx)*0.025; + vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace + vertex_interp=vtx; +*/ + + + + +} + + +void VisualServerRaster::_render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { + RID environment; + if (p_scenario->environment.is_valid()) + environment=p_scenario->environment; + else + environment=p_scenario->fallback_environment; + + rasterizer->set_camera(Transform(),CameraMatrix()); + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); + rasterizer->set_viewport(viewport_rect); + rasterizer->end_scene(); +} + + void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { @@ -5248,6 +6360,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 2 - CULL */ int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); light_cull_count=0; + light_samplers_culled=0; /* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); @@ -5408,6 +6521,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S keep=true; } + + } @@ -5420,6 +6535,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S cull_range.min=min; if (max>cull_range.max) cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->baked_light_sampler_info->last_pass!=render_pass) { + if (light_samplers_culled<MAX_LIGHT_SAMPLERS) { + light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light; + ins->sampled_light->baked_light_sampler_info->last_pass=render_pass; + } + } } } @@ -5499,7 +6621,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } - { + { //this should eventually change to //assign shadows by distance to camera SortArray<Instance*,_InstanceLightsort> sorter; sorter.sort(light_cull_result,light_cull_count); @@ -5520,10 +6642,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } } + /* ENVIRONMENT */ - - /* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/ - RID environment; if (p_camera->env.is_valid()) //camera has more environment priority environment=p_camera->env; @@ -5532,6 +6652,22 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S else environment=p_scenario->fallback_environment; + + /* STEP 6 - SAMPLE BAKED LIGHT */ + + bool islinear =false; + if (environment.is_valid()) { + islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB); + } + + for(int i=0;i<light_samplers_culled;i++) { + + _process_sampled_light(p_camera->transform,light_sampler_cull_result[i],islinear); + } + + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); rasterizer->set_viewport(viewport_rect); @@ -5573,7 +6709,41 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S rasterizer->end_scene(); } -void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity) { + +void VisualServerRaster::_render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color& p_modulate, Rasterizer::CanvasLight *p_lights) { + + + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + + + _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_modulate,p_lights); + } + +} + + +void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect) { + + VisualServerRaster *self=(VisualServerRaster*)(p_self); + Viewport *vp=(Viewport*)p_vp; + self->_draw_viewport(vp,p_rect.pos.x,p_rect.pos.y,p_rect.size.x,p_rect.size.y); + self->rasterizer->canvas_begin(); + +} + +void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_material_owner) { CanvasItem *ci = p_canvas_item; @@ -5592,24 +6762,39 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat if (global_rect.intersects(p_clip_rect) && ci->viewport.is_valid() && viewport_owner.owns(ci->viewport)) { - Viewport *vp = viewport_owner.get(ci->viewport); + Viewport *vp = viewport_owner.get(ci->viewport); Point2i from = xform.get_origin() + Point2(viewport_rect.x,viewport_rect.y); Point2i size = rect.size; size.x *= xform[0].length(); size.y *= xform[1].length(); + ci->vp_render = memnew( Rasterizer::CanvasItem::ViewportRender ); + ci->vp_render->owner=this; + ci->vp_render->udata=vp; + ci->vp_render->rect=Rect2(from.x, + from.y, + size.x, + size.y); +/* _draw_viewport(vp, from.x, from.y, size.x, size.y); +*/ + //rasterizer->canvas_begin(); + } else { + ci->vp_render=NULL; + } - rasterizer->canvas_begin(); + if (ci->use_parent_material && p_material_owner) + ci->material_owner=p_material_owner; + else { + p_material_owner=ci; + ci->material_owner=NULL; } - int s = ci->commands.size(); - bool reclip=false; float opacity = ci->opacity * p_opacity; @@ -5619,8 +6804,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*)); if (ci->clip) { - rasterizer->canvas_set_clip(true,global_rect); - canvas_clip=global_rect; + ci->final_clip_rect=global_rect; + ci->final_clip_owner=ci; + + } else { + ci->final_clip_owner=p_canvas_clip; } if (ci->sort_y) { @@ -5629,197 +6817,137 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat sorter.sort(child_items,child_item_count); } + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,CANVAS_ITEM_Z_MIN,CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; for(int i=0;i<child_item_count;i++) { if (child_items[i]->ontop) continue; - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity); + _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner); } + if (ci->copy_back_buffer) { - if (s!=0) { - - //Rect2 rect( ci->rect.pos + p_ofs, ci->rect.size); - - if (p_clip_rect.intersects(global_rect)) { - - rasterizer->canvas_begin_rect(xform); - rasterizer->canvas_set_opacity( opacity * ci->self_opacity ); - rasterizer->canvas_set_blend_mode( ci->blend_mode ); - - CanvasItem::Command **commands = &ci->commands[0]; - - for (int i=0;i<s;i++) { - - CanvasItem::Command *c=commands[i]; - - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); - rasterizer->canvas_draw_line(line->from,line->to,line->color,line->width); - } break; - case CanvasItem::Command::TYPE_RECT: { + ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); + } - CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); -// rasterizer->canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); -#if 0 - int flags=0; + if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) { + //something to draw? + ci->final_transform=xform; + ci->final_opacity=opacity * ci->self_opacity; + ci->global_rect_cache=global_rect; - if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { - flags|=Rasterizer::CANVAS_RECT_REGION; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { - flags|=Rasterizer::CANVAS_RECT_TILE; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { + int zidx = p_z-CANVAS_ITEM_Z_MIN; - flags|=Rasterizer::CANVAS_RECT_FLIP_H; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; - flags|=Rasterizer::CANVAS_RECT_FLIP_V; - } -#else + } else { + z_list[zidx]=ci; + z_last_list[zidx]=ci; + } - int flags=rect->flags; -#endif - rasterizer->canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate); - } break; - case CanvasItem::Command::TYPE_STYLE: { - CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c); - rasterizer->canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); + ci->next=NULL; - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { + } - CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c); - rasterizer->canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width); - } break; - case CanvasItem::Command::TYPE_POLYGON: { + for(int i=0;i<child_item_count;i++) { - CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); + if (!child_items[i]->ontop) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner); + } - } break; +} - case CanvasItem::Command::TYPE_POLYGON_PTR: { +void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights) { - CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false); - } break; - case CanvasItem::Command::TYPE_CIRCLE: { + rasterizer->canvas_begin(); - CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); - static const int numpoints=32; - Vector2 points[numpoints+1]; - points[numpoints]=circle->pos; - int indices[numpoints*3]; + int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci=p_canvas->child_items.ptr(); - for(int i=0;i<numpoints;i++) { + bool has_mirror=false; + for(int i=0;i<l;i++) { + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror=true; + break; + } + } - points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; - indices[i*3+0]=i; - indices[i*3+1]=(i+1)%numpoints; - indices[i*3+2]=numpoints; - } - rasterizer->canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); - //rasterizer->canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); - rasterizer->canvas_set_transform(transform->xform); - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); - rasterizer->canvas_set_blend_mode(bm->blend_mode); - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); - if (canvas_clip!=Rect2()) { - - if (ci->ignore!=reclip) { - if (ci->ignore) { - - rasterizer->canvas_set_clip(false,Rect2()); - reclip=true; - } else { - rasterizer->canvas_set_clip(true,canvas_clip); - reclip=false; - } - } - } + Rect2 clip_rect(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height); + if (!has_mirror) { + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + for(int i=0;i<l;i++) { + _render_canvas_item(ci[i].item,p_transform,clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); + } - } break; - } - } - rasterizer->canvas_end_rect(); + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights); } - } + } else { + for(int i=0;i<l;i++) { - if (reclip) { + Canvas::ChildItem& ci=p_canvas->child_items[i]; + _render_canvas_item_tree(ci.item,p_transform,clip_rect,p_canvas->modulate,p_lights); - rasterizer->canvas_set_clip(true,canvas_clip); - } + //mirroring (useful for scrolling backgrounds) + if (ci.mirror.x!=0) { - for(int i=0;i<child_item_count;i++) { + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); + _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0) { - if (!child_items[i]->ontop) - continue; - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity); - } + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); + _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0 && ci.mirror.x!=0) { + Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); + _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights); + } - if (ci->clip) { - rasterizer->canvas_set_clip(false,Rect2()); - canvas_clip=Rect2(); + } } } -void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform) { - rasterizer->canvas_begin(); +void VisualServerRaster::_draw_viewport_camera(Viewport *p_viewport,bool p_ignore_camera) { - int l = p_canvas->child_items.size(); - for(int i=0;i<l;i++) { + Camera *camera=NULL; + if (camera_owner.owns( p_viewport->camera )) + camera=camera_owner.get( p_viewport->camera ); + Scenario *scenario = scenario_owner.get( p_viewport->scenario ); - Canvas::ChildItem& ci=p_canvas->child_items[i]; - _render_canvas_item(ci.item,p_transform,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - - //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - } - if (ci.mirror.y!=0) { + _update_instances(); // check dirty instances before rendering - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - } - if (ci.mirror.y!=0 && ci.mirror.x!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - } - - } + if (p_ignore_camera) + _render_no_camera(p_viewport, camera,scenario ); + else + _render_camera(p_viewport, camera,scenario ); } - void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ofs_y,int p_parent_w,int p_parent_h) { ViewportRect desired_rect=p_viewport->rect; @@ -5838,6 +6966,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ desired_rect.x+=p_ofs_x; desired_rect.y+=p_ofs_y; + // if the viewport is different than the actual one, change it if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x || @@ -5847,25 +6976,53 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ viewport_rect=desired_rect; - rasterizer->set_viewport(viewport_rect); + rasterizer->set_viewport(viewport_rect); } /* Camera should always be BEFORE any other 3D */ - if (!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario)) { + bool scenario_draw_canvas_bg=false; + int scenario_canvas_max_layer=0; - Camera *camera = camera_owner.get( p_viewport->camera ); - Scenario *scenario = scenario_owner.get( p_viewport->scenario ); + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) { - _update_instances(); // check dirty instances before rendering + Scenario *scenario=scenario_owner.get(p_viewport->scenario); + if (scenario->environment.is_valid()) { + if (rasterizer->is_environment(scenario->environment)) { + scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS; + scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER); + } + } + } - _render_camera(p_viewport, camera,scenario ); + bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario); + + + if (scenario_draw_canvas_bg) { + + rasterizer->begin_canvas_bg(); + } + + if (!scenario_draw_canvas_bg && can_draw_3d) { + + _draw_viewport_camera(p_viewport,false); } else if (true /*|| !p_viewport->canvas_list.empty()*/){ //clear the viewport black because of no camera? i seriously should.. - rasterizer->clear_viewport(clear_color); + if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) { + if (p_viewport->transparent_bg) { + rasterizer->clear_viewport(Color(0,0,0,0)); + } + else { + Color cc=clear_color; + if (scenario_draw_canvas_bg) + cc.a=0; + rasterizer->clear_viewport(cc); + } + p_viewport->render_target_clear=false; + } } if (!p_viewport->hide_canvas) { @@ -5873,21 +7030,141 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ Map<Viewport::CanvasKey,Viewport::CanvasData*> canvas_map; + Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height); + Rasterizer::CanvasLight *lights=NULL; + Rasterizer::CanvasLight *lights_with_shadow=NULL; + Rect2 shadow_rect; + + int light_count=0; + for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) { + + Matrix32 xf = p_viewport->global_transform * E->get().transform; + + //find lights in canvas + + + for(Set<Rasterizer::CanvasLight*>::Element *F=E->get().canvas->lights.front();F;F=F->next()) { + + Rasterizer::CanvasLight* cl=F->get(); + if (cl->enabled && cl->texture.is_valid()) { + //not super efficient.. + Size2 tsize(rasterizer->texture_get_width(cl->texture),rasterizer->texture_get_height(cl->texture)); + tsize*=cl->scale; + Vector2 offset=tsize/2.0; + cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize); + cl->xform_cache=xf * cl->xform; + + + if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) { + cl->filter_next_ptr=lights; + lights=cl; + cl->texture_cache=NULL; + Matrix32 scale; + scale.scale(cl->rect_cache.size); + scale.elements[2]=cl->rect_cache.pos; + cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse(); + cl->light_shader_pos=cl->xform_cache[2]; + if (cl->shadow_buffer.is_valid()) { + cl->shadows_next_ptr=lights_with_shadow; + if (lights_with_shadow==NULL) { + shadow_rect = cl->xform_cache.xform(cl->rect_cache); + } else { + shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) ); + } + lights_with_shadow=cl; + cl->radius_cache=cl->rect_cache.size.length(); + + } + + light_count++; + } + } + } + + //print_line("lights: "+itos(light_count)); canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get(); } + if (lights_with_shadow) { + //update shadows if any + + Rasterizer::CanvasLightOccluderInstance * occluders=NULL; + + //make list of occluders + for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) { + + Matrix32 xf = p_viewport->global_transform * E->get().transform; + + for(Set<Rasterizer::CanvasLightOccluderInstance*>::Element *F=E->get().canvas->occluders.front();F;F=F->next()) { + + F->get()->xform_cache = xf * F->get()->xform; + if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) { + + F->get()->next=occluders; + occluders=F->get(); + + } + } + } + //update the light shadowmaps with them + Rasterizer::CanvasLight *light=lights_with_shadow; + while(light) { + + rasterizer->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache); + light=light->shadows_next_ptr; + } + + rasterizer->set_viewport(viewport_rect); //must reset viewport afterwards + } + + + + + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) { + + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + + } + for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) { // print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform); Matrix32 xform = p_viewport->global_transform * E->get()->transform; - _render_canvas( E->get()->canvas,xform ); + + Rasterizer::CanvasLight *canvas_lights=NULL; + + Rasterizer::CanvasLight *ptr=lights; + while(ptr) { + if (E->get()->layer>=ptr->layer_min && E->get()->layer<=ptr->layer_max) { + ptr->next_ptr=canvas_lights; + canvas_lights=ptr; + } + ptr=ptr->filter_next_ptr; + } + + _render_canvas( E->get()->canvas,xform,canvas_lights ); i++; + if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } + + } + + if (scenario_draw_canvas_bg) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } + + +// rasterizer->canvas_debug_viewport_shadows(lights_with_shadow); } //capture @@ -5976,7 +7253,7 @@ void VisualServerRaster::_draw_viewports() { rasterizer->set_viewport(viewport_rect); } - rasterizer->canvas_begin(); + rasterizer->canvas_begin(); rasterizer->canvas_disable_blending(); rasterizer->canvas_begin_rect(Matrix32()); rasterizer->canvas_draw_rect(E->get()->rt_to_screen_rect,0,Rect2(Point2(),E->get()->rt_to_screen_rect.size),E->get()->render_target_texture,Color(1,1,1)); @@ -5995,7 +7272,14 @@ void VisualServerRaster::_draw_viewports() { int window_w = OS::get_singleton()->get_video_mode(E->get()).width; int window_h = OS::get_singleton()->get_video_mode(E->get()).height; - _draw_viewport(vp,0,0,window_w,window_h); + Rect2 r(0,0,vp->rect.width,vp->rect.height); + if (r.size.width==0) + r.size.width=window_w; + if (r.size.height==0) + r.size.height=window_w; + + + _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height); } @@ -6224,6 +7508,7 @@ RID VisualServerRaster::get_test_cube() { VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) { rasterizer=p_rasterizer; + rasterizer->draw_viewport_func=_render_canvas_item_viewport; instance_update_list=NULL; render_pass=0; clear_color=Color(0.3,0.3,0.3,1.0); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 8ed348affa..a89a685e30 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer { MAX_LIGHTS_CULLED=256, MAX_ROOM_CULL=32, MAX_EXTERIOR_PORTALS=128, + MAX_LIGHT_SAMPLERS=256, INSTANCE_ROOMLESS_MASK=(1<<20) @@ -84,18 +85,36 @@ class VisualServerRaster : public VisualServer { Vector<Point2> shape; Rect2 bounds; + Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; } }; struct BakedLight { Rasterizer::BakedLightData data; + DVector<int> sampler; AABB octree_aabb; Size2i octree_tex_size; + Size2i light_tex_size; }; + struct BakedLightSampler { + + float params[BAKED_LIGHT_SAMPLER_MAX]; + int resolution; + Vector<Vector3> dp_cache; + + BakedLightSampler() { + params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0; + params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0; + params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0; + params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1; + resolution=16; + } + }; + void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp); struct Camera { enum Type { @@ -169,6 +188,7 @@ class VisualServerRaster : public VisualServer { List<Instance*>::Element *RE; Instance *baked_light; List<Instance*>::Element *BLE; + Instance *sampled_light; bool exterior; uint64_t last_render_pass; @@ -179,6 +199,8 @@ class VisualServerRaster : public VisualServer { InstanceSet lights; bool light_cache_dirty; + + struct RoomInfo { Transform affine_inverse; @@ -235,6 +257,23 @@ class VisualServerRaster : public VisualServer { Transform affine_inverse; List<Instance*> owned_instances; }; + + struct BakedLightSamplerInfo { + + Set<Instance*> baked_lights; + Set<Instance*> owned_instances; + BakedLightSampler *sampler; + int resolution; + Vector<Color> light_bufer; + RID sampled_light; + uint64_t last_pass; + Transform xform; // viewspace normal to lightspace, might not use one. + BakedLightSamplerInfo() { + sampler=NULL; + last_pass=0; + resolution=0; + } + }; struct ParticlesInfo { @@ -247,6 +286,7 @@ class VisualServerRaster : public VisualServer { ParticlesInfo *particles_info; PortalInfo * portal_info; BakedLightInfo * baked_light_info; + BakedLightSamplerInfo * baked_light_sampler_info; Instance() { @@ -282,6 +322,8 @@ class VisualServerRaster : public VisualServer { baked_light=NULL; baked_light_info=NULL; + baked_light_sampler_info=NULL; + sampled_light=NULL; BLE=NULL; light_cache_dirty=true; @@ -329,141 +371,34 @@ class VisualServerRaster : public VisualServer { + mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner; + struct CanvasItem : public Rasterizer::CanvasItem { - struct CanvasItem { - - struct Command { - - enum Type { - - TYPE_LINE, - TYPE_RECT, - TYPE_STYLE, - TYPE_PRIMITIVE, - TYPE_POLYGON, - TYPE_POLYGON_PTR, - TYPE_CIRCLE, - TYPE_TRANSFORM, - TYPE_BLEND_MODE, - TYPE_CLIP_IGNORE, - }; - - Type type; - }; - - struct CommandLine : public Command { - - Point2 from,to; - Color color; - float width; - CommandLine() { type = TYPE_LINE; } - }; - - struct CommandRect : public Command { - - Rect2 rect; - RID texture; - Color modulate; - Rect2 source; - uint8_t flags; - - CommandRect() { flags=0; type = TYPE_RECT; } - }; - - struct CommandStyle : public Command { - - Rect2 rect; - RID texture; - float margin[4]; - float draw_center; - Color color; - CommandStyle() { draw_center=true; type = TYPE_STYLE; } - }; - - struct CommandPrimitive : public Command { - - Vector<Point2> points; - Vector<Point2> uvs; - Vector<Color> colors; - RID texture; - float width; - - CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;} - }; - - struct CommandPolygon : public Command { - - Vector<int> indices; - Vector<Point2> points; - Vector<Point2> uvs; - Vector<Color> colors; - RID texture; - int count; - - CommandPolygon() { type = TYPE_POLYGON; count = 0; } - }; - - struct CommandPolygonPtr : public Command { - - const int* indices; - const Point2* points; - const Point2* uvs; - const Color* colors; - RID texture; - int count; - - CommandPolygonPtr() { type = TYPE_POLYGON_PTR; count = 0; } - }; - - struct CommandCircle : public Command { - - Point2 pos; - float radius; - Color color; - CommandCircle() { type = TYPE_CIRCLE; } - }; - - struct CommandTransform : public Command { - - Matrix32 xform; - CommandTransform() { type = TYPE_TRANSFORM; } - }; - - struct CommandBlendMode : public Command { - - MaterialBlendMode blend_mode; - CommandBlendMode() { type = TYPE_BLEND_MODE; blend_mode = MATERIAL_BLEND_MODE_MIX; }; - }; - struct CommandClipIgnore : public Command { - - bool ignore; - CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; }; - }; RID parent; // canvas it belongs to List<CanvasItem*>::Element *E; - Matrix32 xform; - bool clip; - bool visible; - bool ontop; + RID viewport; + int z; + bool z_relative; bool sort_y; float opacity; float self_opacity; - MaterialBlendMode blend_mode; - RID viewport; + bool use_parent_material; + - mutable bool custom_rect; - mutable bool rect_dirty; - mutable Rect2 rect; - - Vector<Command*> commands; Vector<CanvasItem*> child_items; - const Rect2& get_rect() const; - void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true;}; - CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; sort_y=false;} - ~CanvasItem() { clear(); } + + CanvasItem() { + E=NULL; + z=0; + opacity=1; + self_opacity=1; + sort_y=false; + use_parent_material=false; + z_relative=true; + } }; @@ -475,6 +410,26 @@ class VisualServerRaster : public VisualServer { } }; + struct CanvasLightOccluder; + + struct CanvasLightOccluderPolygon { + + bool active; + Rect2 aabb; + CanvasOccluderPolygonCullMode cull_mode; + RID occluder; + Set<Rasterizer::CanvasLightOccluderInstance*> owners; + + CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + }; + + + RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner; + + RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner; + + struct CanvasLight; + struct Canvas { Set<RID> viewports; @@ -484,8 +439,11 @@ class VisualServerRaster : public VisualServer { CanvasItem *item; }; + Set<Rasterizer::CanvasLight*> lights; + Set<Rasterizer::CanvasLightOccluderInstance*> occluders; Vector<ChildItem> child_items; + Color modulate; int find_item(CanvasItem *p_item) { for(int i=0;i<child_items.size();i++) { @@ -500,11 +458,13 @@ class VisualServerRaster : public VisualServer { child_items.remove(idx); } - Canvas() { } + Canvas() { modulate=Color(1,1,1,1); } }; + RID_Owner<Rasterizer::CanvasLight> canvas_light_owner; + struct Viewport { @@ -527,6 +487,10 @@ class VisualServerRaster : public VisualServer { bool transparent_bg; bool queue_capture; bool render_target_vflip; + bool render_target_clear_on_new_frame; + bool render_target_clear; + bool disable_environment; + Image capture; bool rendered_in_prev_frame; @@ -553,7 +517,7 @@ class VisualServerRaster : public VisualServer { SelfList<Viewport> update_list; - Viewport() : update_list(this) { transparent_bg=false; render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; queue_capture=false; rendered_in_prev_frame=false; render_target_vflip=false;} + Viewport() : update_list(this) { transparent_bg=false; render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE; queue_capture=false; rendered_in_prev_frame=false; render_target_vflip=false; render_target_clear_on_new_frame=true; render_target_clear=true; disable_environment=false; } }; SelfList<Viewport>::List viewport_update_list; @@ -603,6 +567,9 @@ class VisualServerRaster : public VisualServer { int exterior_portal_cull_count; bool exterior_visited; + Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS]; + int light_samplers_culled; + Instance *room_cull_result[MAX_ROOM_CULL]; int room_cull_count; bool room_cull_enabled; @@ -638,6 +605,7 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Portal> portal_owner; mutable RID_Owner<BakedLight> baked_light_owner; + mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner; mutable RID_Owner<Camera> camera_owner; mutable RID_Owner<Viewport> viewport_owner; @@ -658,9 +626,14 @@ class VisualServerRaster : public VisualServer { bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to); void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal); void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL); + void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace); + + void _render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); - void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity); - void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); + static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect); + void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights); + void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner); + void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights); Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); @@ -673,6 +646,7 @@ class VisualServerRaster : public VisualServer { int changes; bool draw_extra_frame; + void _draw_viewport_camera(Viewport *p_viewport, bool p_ignore_camera); void _draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ofs_y,int p_parent_w,int p_parent_h); void _draw_viewports(); void _draw_cursors_and_margins(); @@ -709,6 +683,10 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + + /* COMMON MATERIAL API */ virtual RID material_create(); @@ -953,12 +931,28 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree); virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const; + virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light); + virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler); + virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier); virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id); virtual void baked_light_clear_lightmaps(RID p_baked_light); + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create(); + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value); + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution); + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const; + /* CAMERA API */ virtual RID camera_create(); @@ -988,8 +982,12 @@ public: virtual RID viewport_get_render_target_texture(RID p_viewport) const; virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable); virtual bool viewport_get_render_target_vflip(RID p_viewport) const; + virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable); + virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const; + virtual void viewport_render_target_clear(RID p_viewport); virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect); + virtual void viewport_queue_screen_capture(RID p_viewport); virtual Image viewport_get_screen_capture(RID p_viewport) const; @@ -998,6 +996,7 @@ public: virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide); virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide); + virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable); virtual void viewport_attach_camera(RID p_viewport,RID p_camera); virtual void viewport_set_scenario(RID p_viewport,RID p_scenario); @@ -1096,6 +1095,9 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light); virtual RID instance_geometry_get_baked_light(RID p_instance) const; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler); + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id); virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const; @@ -1107,6 +1109,8 @@ public: virtual RID canvas_create(); virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring); virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const; + virtual void canvas_set_modulate(RID p_canvas,const Color& p_color); + virtual RID canvas_item_create(); @@ -1117,11 +1121,14 @@ public: virtual bool canvas_item_is_visible(RID p_item) const; virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend); + virtual void canvas_item_set_light_mask(RID p_canvas_item,int p_mask); + //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect); virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform); virtual void canvas_item_set_clip(RID p_item, bool p_clip); + virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2()); virtual void canvas_item_set_opacity(RID p_item, float p_opacity); virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const; @@ -1136,8 +1143,8 @@ public: virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0); virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color); virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color); - virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1)); - virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)); + virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); + virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0); virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID()); @@ -1147,10 +1154,62 @@ public: virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend); virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); + virtual void canvas_item_set_z(RID p_item, int p_z); + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); + virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect); + + virtual void canvas_item_set_material(RID p_item, RID p_material); + virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + + virtual RID canvas_light_create(); + virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas); + virtual void canvas_light_set_enabled(RID p_light, bool p_enabled); + virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform); + virtual void canvas_light_set_scale(RID p_light, float p_scale); + virtual void canvas_light_set_texture(RID p_light, RID p_texture); + virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset); + virtual void canvas_light_set_color(RID p_light, const Color& p_color); + virtual void canvas_light_set_height(RID p_light, float p_height); + virtual void canvas_light_set_energy(RID p_light, float p_energy); + virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); + virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); + virtual void canvas_light_set_item_mask(RID p_light, int p_mask); + virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask); + + virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode); + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); + virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); + virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier); + + + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas); + virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled); + virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon); + virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform); + virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask); + + + virtual RID canvas_occluder_polygon_create(); + virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close); + virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape); + virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode); + + virtual void canvas_item_clear(RID p_item); virtual void canvas_item_raise(RID p_item); + /* CANVAS ITEM MATERIAL */ + + virtual RID canvas_item_material_create(); + virtual void canvas_item_material_set_shader(RID p_material, RID p_shader); + virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value); + virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const; + virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode); + + + /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 1ad8c85986..6cd374aa08 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -653,6 +653,10 @@ public: FUNC1RC(String,shader_get_light_code,RID); FUNC2SC(shader_get_param_list,RID,List<PropertyInfo>*); + FUNC3(shader_set_default_texture_param,RID,const StringName&,RID); + FUNC2RC(RID,shader_get_default_texture_param,RID,const StringName&); + + /*virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) { if (Thread::get_caller_ID()!=server_thread) { command_queue.push_and_sync( visual_server, &VisualServer::shader_get_param_list,p_shader,p_param_list); @@ -909,6 +913,12 @@ public: FUNC2(baked_light_set_octree,RID,DVector<uint8_t>); FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID); + FUNC2(baked_light_set_light,RID,DVector<uint8_t>); + FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID); + + FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&); + FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID); + FUNC2(baked_light_set_lightmap_multiplier,RID,float); FUNC1RC(float,baked_light_get_lightmap_multiplier,RID); @@ -916,6 +926,14 @@ public: FUNC1(baked_light_clear_lightmaps,RID); + FUNC0R(RID,baked_light_sampler_create); + + FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float ); + FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam ); + + FUNC2(baked_light_sampler_set_resolution,RID,int); + FUNC1RC(int,baked_light_sampler_get_resolution,RID); + /* CAMERA API */ FUNC0R(RID,camera_create); @@ -949,6 +967,10 @@ public: FUNC2(viewport_set_render_target_vflip,RID,bool); FUNC1RC(bool,viewport_get_render_target_vflip,RID); FUNC2(viewport_set_render_target_to_screen_rect,RID,const Rect2&); + + FUNC2(viewport_set_render_target_clear_on_new_frame,RID,bool); + FUNC1RC(bool,viewport_get_render_target_clear_on_new_frame,RID); + FUNC1(viewport_render_target_clear,RID); FUNC1(viewport_queue_screen_capture,RID); FUNC1RC(Image,viewport_get_screen_capture,RID); @@ -960,6 +982,7 @@ public: FUNC2(viewport_set_hide_canvas,RID,bool ); FUNC2(viewport_attach_camera,RID,RID ); FUNC2(viewport_set_scenario,RID,RID ); + FUNC2(viewport_set_disable_environment,RID,bool ); FUNC1RC(RID,viewport_get_attached_camera,RID); FUNC1RC(RID,viewport_get_scenario,RID ); @@ -1055,6 +1078,9 @@ public: FUNC2(instance_geometry_set_baked_light,RID, RID ); FUNC1RC(RID,instance_geometry_get_baked_light,RID); + FUNC2(instance_geometry_set_baked_light_sampler,RID, RID ); + FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID); + FUNC2(instance_geometry_set_baked_light_texture_index,RID, int); FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID); @@ -1066,6 +1092,8 @@ public: FUNC0R(RID,canvas_create); FUNC3(canvas_set_item_mirroring,RID,RID,const Point2&); FUNC2RC(Point2,canvas_get_item_mirroring,RID,RID); + FUNC2(canvas_set_modulate,RID,const Color&); + FUNC0R(RID,canvas_item_create); @@ -1076,11 +1104,12 @@ public: FUNC1RC(bool,canvas_item_is_visible,RID); FUNC2(canvas_item_set_blend_mode,RID,MaterialBlendMode ); - + FUNC2(canvas_item_set_light_mask,RID,int ); //FUNC(canvas_item_set_rect,RID, const Rect2& p_rect); FUNC2(canvas_item_set_transform,RID, const Matrix32& ); FUNC2(canvas_item_set_clip,RID, bool ); + FUNC2(canvas_item_set_distance_field_mode,RID, bool ); FUNC3(canvas_item_set_custom_rect,RID, bool ,const Rect2&); FUNC2(canvas_item_set_opacity,RID, float ); FUNC2RC(float,canvas_item_get_opacity,RID, float ); @@ -1095,9 +1124,8 @@ public: FUNC5(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float ); FUNC3(canvas_item_add_rect,RID, const Rect2& , const Color& ); FUNC4(canvas_item_add_circle,RID, const Point2& , float ,const Color& ); - FUNC5(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color& ); - FUNC5(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color& ); - + FUNC6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color&,bool ); + FUNC6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color&,bool ); FUNC7(canvas_item_add_style_box,RID, const Rect2& , RID ,const Vector2& ,const Vector2&, bool ,const Color& ); FUNC6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float ); FUNC5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ); @@ -1110,10 +1138,62 @@ public: FUNC2(canvas_item_add_clip_ignore,RID, bool ); FUNC2(canvas_item_set_sort_children_by_y,RID,bool); + FUNC2(canvas_item_set_z,RID,int); + FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool); + FUNC3(canvas_item_set_copy_to_backbuffer,RID,bool,const Rect2&); + + + FUNC2(canvas_item_set_material,RID, RID ); + + FUNC2(canvas_item_set_use_parent_material,RID, bool ); FUNC1(canvas_item_clear,RID); FUNC1(canvas_item_raise,RID); + /* CANVAS LIGHT */ + FUNC0R(RID,canvas_light_create); + FUNC2(canvas_light_attach_to_canvas,RID,RID); + FUNC2(canvas_light_set_enabled,RID,bool); + FUNC2(canvas_light_set_transform,RID,const Matrix32&); + FUNC2(canvas_light_set_scale,RID,float); + FUNC2(canvas_light_set_texture,RID,RID); + FUNC2(canvas_light_set_texture_offset,RID,const Vector2&); + FUNC2(canvas_light_set_color,RID,const Color&); + FUNC2(canvas_light_set_height,RID,float); + FUNC2(canvas_light_set_energy,RID,float); + FUNC3(canvas_light_set_layer_range,RID,int,int); + FUNC3(canvas_light_set_z_range,RID,int,int); + FUNC2(canvas_light_set_item_mask,RID,int); + FUNC2(canvas_light_set_item_shadow_mask,RID,int); + + FUNC2(canvas_light_set_mode,RID,CanvasLightMode); + FUNC2(canvas_light_set_shadow_enabled,RID,bool); + FUNC2(canvas_light_set_shadow_buffer_size,RID,int); + FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float); + + + /* CANVAS OCCLUDER */ + + FUNC0R(RID,canvas_light_occluder_create); + FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID); + FUNC2(canvas_light_occluder_set_enabled,RID,bool); + FUNC2(canvas_light_occluder_set_polygon,RID,RID); + FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&); + FUNC2(canvas_light_occluder_set_light_mask,RID,int); + + + FUNC0R(RID,canvas_occluder_polygon_create); + FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool); + FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&); + FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode); + + /* CANVAS MATERIAL */ + + FUNC0R(RID,canvas_item_material_create); + FUNC2(canvas_item_material_set_shader,RID,RID); + FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&); + FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&); + FUNC2(canvas_item_material_set_shading_mode,RID,CanvasItemShadingMode); /* CURSOR */ FUNC2(cursor_set_rotation,float , int ); // radians diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 9abfecaac6..5ddfaf7967 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -28,6 +28,7 @@ /*************************************************************************/ #include "visual_server.h" #include "globals.h" +#include "method_bind_ext.inc" VisualServer *VisualServer::singleton=NULL; VisualServer* (*VisualServer::create_func)()=NULL; @@ -486,7 +487,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("instances_cull_aabb"),&VisualServer::instances_cull_aabb); ObjectTypeDB::bind_method(_MD("instances_cull_ray"),&VisualServer::instances_cull_ray); - ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_ray); + ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_convex); @@ -510,8 +511,9 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("canvas_item_add_line"),&VisualServer::canvas_item_add_line, DEFVAL(1.0)); ObjectTypeDB::bind_method(_MD("canvas_item_add_rect"),&VisualServer::canvas_item_add_rect); - ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect"),&VisualServer::canvas_item_add_texture_rect, DEFVAL(Color(1,1,1))); - ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect_region"),&VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1,1,1))); + ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect"),&VisualServer::canvas_item_add_texture_rect, DEFVAL(Color(1,1,1)), DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect_region"),&VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1,1,1)), DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("canvas_item_add_style_box"),&VisualServer::_canvas_item_add_style_box, DEFVAL(Color(1,1,1))); // ObjectTypeDB::bind_method(_MD("canvas_item_add_primitive"),&VisualServer::canvas_item_add_primitive,DEFVAL(Vector<Vector2>()),DEFVAL(RID())); ObjectTypeDB::bind_method(_MD("canvas_item_add_circle"),&VisualServer::canvas_item_add_circle); diff --git a/servers/visual_server.h b/servers/visual_server.h index 366758f1d8..e9425afbab 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -86,6 +86,9 @@ public: ARRAY_WEIGHTS_SIZE=4, MAX_PARTICLE_COLOR_PHASES=4, MAX_PARTICLE_ATTRACTORS=4, + CANVAS_ITEM_Z_MIN=-4096, + CANVAS_ITEM_Z_MAX=4096, + MAX_CURSORS = 8, @@ -140,6 +143,7 @@ public: SHADER_POST_PROCESS, }; + virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL)=0; virtual void shader_set_mode(RID p_shader,ShaderMode p_mode)=0; @@ -151,6 +155,9 @@ public: virtual String shader_get_light_code(RID p_shader) const=0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0; + /* COMMON MATERIAL API */ @@ -590,12 +597,35 @@ public: virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0; virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0; + virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0; + virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0; + + virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0; + virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0; + virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0; virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0; virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0; virtual void baked_light_clear_lightmaps(RID p_baked_light)=0; + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create()=0; + + enum BakedLightSamplerParam { + BAKED_LIGHT_SAMPLER_RADIUS, + BAKED_LIGHT_SAMPLER_STRENGTH, + BAKED_LIGHT_SAMPLER_ATTENUATION, + BAKED_LIGHT_SAMPLER_DETAIL_RATIO, + BAKED_LIGHT_SAMPLER_MAX + }; + + virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0; + virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0; + + virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0; + virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0; /* CAMERA API */ @@ -654,6 +684,9 @@ public: virtual RID viewport_get_render_target_texture(RID p_viewport) const=0; virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable)=0; virtual bool viewport_get_render_target_vflip(RID p_viewport) const=0; + virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable)=0; + virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const=0; + virtual void viewport_render_target_clear(RID p_viewport)=0; virtual void viewport_queue_screen_capture(RID p_viewport)=0; virtual Image viewport_get_screen_capture(RID p_viewport) const=0; @@ -671,6 +704,7 @@ public: virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide)=0; virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide)=0; + virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable)=0; virtual void viewport_attach_camera(RID p_viewport,RID p_camera)=0; virtual void viewport_set_scenario(RID p_viewport,RID p_scenario)=0; @@ -701,8 +735,7 @@ public: ENV_BG_COLOR, ENV_BG_TEXTURE, ENV_BG_CUBEMAP, - ENV_BG_TEXTURE_RGBE, - ENV_BG_CUBEMAP_RGBE, + ENV_BG_CANVAS, ENV_BG_MAX }; @@ -711,6 +744,7 @@ public: enum EnvironmentBGParam { + ENV_BG_PARAM_CANVAS_MAX_LAYER, ENV_BG_PARAM_COLOR, ENV_BG_PARAM_TEXTURE, ENV_BG_PARAM_CUBEMAP, @@ -824,7 +858,8 @@ public: INSTANCE_ROOM, INSTANCE_PORTAL, INSTANCE_BAKED_LIGHT, - + INSTANCE_BAKED_LIGHT_SAMPLER, + INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES) }; @@ -898,9 +933,13 @@ public: virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0; virtual RID instance_geometry_get_baked_light(RID p_instance) const=0; + virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0; + virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0; + virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0; virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0; + virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0; virtual bool instance_light_is_enabled(RID p_instance) const=0; @@ -909,6 +948,8 @@ public: virtual RID canvas_create()=0; virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring)=0; virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const=0; + virtual void canvas_set_modulate(RID p_canvas,const Color& p_color)=0; + virtual RID canvas_item_create()=0; @@ -918,6 +959,8 @@ public: virtual void canvas_item_set_visible(RID p_item,bool p_visible)=0; virtual bool canvas_item_is_visible(RID p_item) const=0; + virtual void canvas_item_set_light_mask(RID p_item,int p_mask)=0; + virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend)=0; virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport)=0; @@ -926,6 +969,7 @@ public: virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform)=0; virtual void canvas_item_set_clip(RID p_item, bool p_clip)=0; + virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable)=0; virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2())=0; virtual void canvas_item_set_opacity(RID p_item, float p_opacity)=0; virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const=0; @@ -939,8 +983,8 @@ public: virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0)=0; virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color)=0; virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color)=0; - virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1))=0; - virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1))=0; + virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0; + virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0; virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0)=0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID())=0; @@ -950,10 +994,78 @@ public: virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0; + virtual void canvas_item_set_z(RID p_item, int p_z)=0; + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable)=0; + virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect)=0; virtual void canvas_item_clear(RID p_item)=0; virtual void canvas_item_raise(RID p_item)=0; + virtual void canvas_item_set_material(RID p_item, RID p_material)=0; + + virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable)=0; + + virtual RID canvas_light_create()=0; + virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0; + virtual void canvas_light_set_enabled(RID p_light, bool p_enabled)=0; + virtual void canvas_light_set_scale(RID p_light, float p_scale)=0; + virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform)=0; + virtual void canvas_light_set_texture(RID p_light, RID p_texture)=0; + virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0; + virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0; + virtual void canvas_light_set_height(RID p_light, float p_height)=0; + virtual void canvas_light_set_energy(RID p_light, float p_energy)=0; + virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0; + virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0; + virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0; + virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0; + + enum CanvasLightMode { + CANVAS_LIGHT_MODE_ADD, + CANVAS_LIGHT_MODE_SUB, + CANVAS_LIGHT_MODE_MIX, + }; + + virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0; + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; + virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0; + virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0; + + + + virtual RID canvas_light_occluder_create()=0; + virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0; + virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0; + virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0; + virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0; + virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0; + + virtual RID canvas_occluder_polygon_create()=0; + virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0; + virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0; + enum CanvasOccluderPolygonCullMode { + CANVAS_OCCLUDER_POLYGON_CULL_DISABLED, + CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE, + CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE, + }; + virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0; + + /* CANVAS ITEM MATERIAL */ + + virtual RID canvas_item_material_create()=0; + virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0; + virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; + virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0; + + + enum CanvasItemShadingMode { + CANVAS_ITEM_SHADING_NORMAL, + CANVAS_ITEM_SHADING_UNSHADED, + CANVAS_ITEM_SHADING_ONLY_LIGHT, + }; + + virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode)=0; + /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0)=0; diff --git a/tools/SCsub b/tools/SCsub index 875663b849..ce7df2c35b 100644 --- a/tools/SCsub +++ b/tools/SCsub @@ -5,16 +5,17 @@ env.add_source_files(env.tool_sources,"*.cpp") Export('env') -SConscript('editor/SCsub'); -#SConscript('scintilla/SCsub'); -SConscript('collada/SCsub'); -SConscript('docdump/SCsub'); -SConscript('freetype/SCsub'); -SConscript('doc/SCsub'); -SConscript('pck/SCsub'); +if (env["tools"]!="no"): + SConscript('editor/SCsub'); + #SConscript('scintilla/SCsub'); + SConscript('collada/SCsub'); + SConscript('docdump/SCsub'); + SConscript('freetype/SCsub'); + SConscript('doc/SCsub') + SConscript('pck/SCsub') -lib = env.Library("tool",env.tool_sources) + lib = env.Library("tool",env.tool_sources) -env.Prepend(LIBS=[lib]) + env.Prepend(LIBS=[lib]) diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp index 7f4f92e82d..b55edde801 100644 --- a/tools/collada/collada.cpp +++ b/tools/collada/collada.cpp @@ -817,7 +817,7 @@ void Collada::_parse_camera(XMLParser& parser) { if (name=="perspective") { camera.mode=CameraData::MODE_PERSPECTIVE; - } else if (name=="orthogonal") { + } else if (name=="orthographic") { camera.mode=CameraData::MODE_ORTHOGONAL; } else if (name=="xfov") { @@ -2106,6 +2106,8 @@ void Collada::_parse_animation_clip(XMLParser& parser) { if (parser.has_attribute("name")) clip.name=parser.get_attribute_value("name"); + else if (parser.has_attribute("id")) + clip.name=parser.get_attribute_value("id"); if (parser.has_attribute("start")) clip.begin=parser.get_attribute_value("start").to_double(); if (parser.has_attribute("end")) @@ -2248,29 +2250,35 @@ void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) { } } -void Collada::_create_skeletons(Collada::Node **p_node) { +void Collada::_create_skeletons(Collada::Node **p_node,NodeSkeleton *p_skeleton) { Node *node = *p_node; - - if (node->type==Node::TYPE_JOINT) { - // ohohohoohoo it's a joint node, time to work! + if (!p_skeleton) { + + // ohohohoohoo it's a joint node, time to work! + NodeSkeleton *sk = memnew( NodeSkeleton ); + *p_node=sk; + sk->children.push_back(node); + sk->parent=node->parent; + node->parent=sk; + p_skeleton=sk; + } - NodeSkeleton *sk = memnew( NodeSkeleton ); - *p_node=sk; - sk->children.push_back(node); - sk->parent=node->parent; - node->parent=sk; - _joint_set_owner(node,sk); + NodeJoint *nj = static_cast<NodeJoint*>(node); + nj->owner=p_skeleton; } else { + p_skeleton=NULL; + } - for(int i=0;i<node->children.size();i++) { - _create_skeletons(&node->children[i]); - } + + for(int i=0;i<node->children.size();i++) { + _create_skeletons(&node->children[i],p_skeleton); } + } bool Collada::_remove_node(Node *p_parent,Node *p_node) { @@ -2323,6 +2331,9 @@ void Collada::_merge_skeletons(VisualScene *p_vscene,Node *p_node) { NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]); + if (!nj->owner) { + print_line("no owner for: "+String(nodeid)); + } ERR_CONTINUE( !nj->owner ); //weird, node should have a skeleton owner skeletons.insert(nj->owner); @@ -2624,6 +2635,7 @@ void Collada::_optimize() { _create_skeletons(&vs.root_nodes[i]); } +#if 1 for(int i=0;i<vs.root_nodes.size();i++) { _merge_skeletons(&vs,vs.root_nodes[i]); } @@ -2651,6 +2663,7 @@ void Collada::_optimize() { } } +#endif for(int i=0;i<vs.root_nodes.size();i++) { _find_morph_nodes(&vs,vs.root_nodes[i]); } diff --git a/tools/collada/collada.h b/tools/collada/collada.h index c5e5705105..7691d90c0a 100644 --- a/tools/collada/collada.h +++ b/tools/collada/collada.h @@ -337,6 +337,24 @@ public: if(normal==p_vert.normal) { if(uv==p_vert.uv) { if(uv2==p_vert.uv2) { + + if (!weights.empty() || !p_vert.weights.empty()) { + + if (weights.size()==p_vert.weights.size()) { + + for(int i=0;i<weights.size();i++) { + if (weights[i].bone_idx!=p_vert.weights[i].bone_idx) + return weights[i].bone_idx<p_vert.weights[i].bone_idx; + + if (weights[i].weight!=p_vert.weights[i].weight) + return weights[i].weight<p_vert.weights[i].weight; + } + } else { + return weights.size() < p_vert.weights.size(); + } + + } + return (color<p_vert.color); } else return (uv2<p_vert.uv2); @@ -619,7 +637,7 @@ private: // private stuff Transform _read_transform(XMLParser& parser); void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner); - void _create_skeletons(Collada::Node **p_node); + void _create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton=NULL); void _find_morph_nodes(VisualScene *p_vscene,Node *p_node); bool _remove_node(Node *p_parent,Node *p_node); void _remove_node(VisualScene *p_vscene,Node *p_node); diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index 0bd21219bf..75759e7d30 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -186,8 +186,10 @@ void DocData::generate(bool p_basic_types) { arginfo=E->get().return_val; if (arginfo.type==Variant::NIL) continue; - - method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); + if (m && m->get_return_type()!=StringName()) + method.return_type=m->get_return_type(); + else + method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); } else { @@ -724,6 +726,7 @@ Error DocData::_load(Ref<XMLParser> parser) { class_list[name]=ClassDoc(); ClassDoc& c = class_list[name]; +// print_line("class: "+name); c.name=name; if (parser->has_attribute("inherits")) c.inherits = parser->get_attribute_value("inherits"); @@ -809,7 +812,7 @@ Error DocData::_load(Ref<XMLParser> parser) { ERR_FAIL_V(ERR_FILE_CORRUPT); } - } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="members") + } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="theme_items") break; //end of <constants> } diff --git a/tools/docdump/class_list.xml b/tools/docdump/class_list.xml index 897477ff48..ab33cef7d7 100644 --- a/tools/docdump/class_list.xml +++ b/tools/docdump/class_list.xml @@ -319,7 +319,7 @@ <argument index="1" name="animation" type="Object"> </argument> <description> - Add an animation resource to the player, which will be later referenced by the "name" arguemnt. + Add an animation resource to the player, which will be later referenced by the "name" argument. </description> </method> <method name="remove_animation" > diff --git a/tools/docdump/makemd.py b/tools/docdump/makemd.py index 7cc2e9dc4b..f85d145d5e 100644 --- a/tools/docdump/makemd.py +++ b/tools/docdump/makemd.py @@ -337,7 +337,7 @@ for file in input_list: class_names.sort() -make_class_list(class_names, 3) +make_class_list(class_names, 2) for cn in class_names: c = classes[cn] diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index e693753c33..db70a2675a 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -687,9 +687,7 @@ void AnimationKeyEditor::_menu_track(int p_type) { case TRACK_MENU_OPTIMIZE: { - animation->optimize(); - - track_editor->update(); + optimize_dialog->popup_centered(Size2(250,180)); } break; @@ -698,6 +696,18 @@ void AnimationKeyEditor::_menu_track(int p_type) { } + +void AnimationKeyEditor::_animation_optimize() { + + + print_line("OPTIMIZE!"); + animation->optimize(optimize_linear_error->get_val(),optimize_angular_error->get_val(),optimize_max_angle->get_val()); + track_editor->update(); + undo_redo->clear_history(); + +} + + float AnimationKeyEditor::_get_zoom_scale() const { float zv = zoom->get_val(); @@ -2309,7 +2319,7 @@ void AnimationKeyEditor::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { zoomicon->set_texture( get_icon("Zoom","EditorIcons") ); //menu_track->set_icon(get_icon("AddTrack","EditorIcons")); @@ -2335,11 +2345,12 @@ void AnimationKeyEditor::_notification(int p_what) { tpp->add_item("Out-In",TRACK_MENU_SET_ALL_TRANS_OUTIN); tpp->set_name("Transitions"); tpp->connect("item_pressed",this,"_menu_track"); + optimize_dialog->connect("confirmed",this,"_animation_optimize"); menu_track->get_popup()->add_child(tpp); menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions"); - //menu_track->get_popup()->add_separator(); - //menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE); + menu_track->get_popup()->add_separator(); + menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE); @@ -2465,12 +2476,12 @@ void AnimationKeyEditor::set_animation(const Ref<Animation>& p_anim) { void AnimationKeyEditor::set_root(Node *p_root) { if (root) - root->disconnect("exit_scene",this,"_root_removed"); + root->disconnect("exit_tree",this,"_root_removed"); root=p_root; if (root) - root->connect("exit_scene",this,"_root_removed",make_binds(),CONNECT_ONESHOT); + root->connect("exit_tree",this,"_root_removed",make_binds(),CONNECT_ONESHOT); } @@ -2502,6 +2513,7 @@ void AnimationKeyEditor::_query_insert(const InsertData& p_id) { if (insert_frame!=OS::get_singleton()->get_frames_drawn()) { + //clear insert list for the frame if frame changed if (insert_confirm->is_visible()) return; //do nothing insert_data.clear(); @@ -2509,19 +2521,29 @@ void AnimationKeyEditor::_query_insert(const InsertData& p_id) { } insert_frame=OS::get_singleton()->get_frames_drawn(); + for (List<InsertData>::Element *E=insert_data.front();E;E=E->next()) { + //prevent insertion of multiple tracks + if (E->get().path==p_id.path) + return; //already inserted a track for this on this frame + } + insert_data.push_back(p_id); if (p_id.track_idx==-1) { - //potential new key, does not exist - if (insert_data.size()==1) - insert_confirm->set_text("Create NEW track for "+p_id.query+" and insert key?"); - else - insert_confirm->set_text("Create "+itos(insert_data.size())+" NEW tracks and insert keys?"); - - insert_confirm->get_ok()->set_text("Create"); - insert_confirm->popup_centered(Size2(300,100)); - insert_query=true; - + if (bool(EDITOR_DEF("animation/confirm_insert_track",true))) { + //potential new key, does not exist + if (insert_data.size()==1) + insert_confirm->set_text("Create NEW track for "+p_id.query+" and insert key?"); + else + insert_confirm->set_text("Create "+itos(insert_data.size())+" NEW tracks and insert keys?"); + + insert_confirm->get_ok()->set_text("Create"); + insert_confirm->popup_centered(Size2(300,100)); + insert_query=true; + } else { + call_deferred("_insert_delay"); + insert_queue=true; + } } else { if (!insert_query && !insert_queue) { @@ -2887,11 +2909,11 @@ void AnimationKeyEditor::set_anim_pos(float p_pos) { void AnimationKeyEditor::_pane_drag(const Point2& p_delta) { - Size2 ecs = ec->get_minsize(); + Size2 ecs = ec->get_custom_minimum_size(); ecs.y-=p_delta.y; if (ecs.y<100) ecs.y=100; - ec->set_minsize(ecs);; + ec->set_custom_minimum_size(ecs);; } @@ -3099,6 +3121,7 @@ void AnimationKeyEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_animation_len_update"),&AnimationKeyEditor::_animation_len_update); ObjectTypeDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation); + ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize); ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); @@ -3131,7 +3154,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h //add_child(menu); menu_track = memnew( MenuButton ); - menu_track->set_text("Tracks.."); + menu_track->set_text("Tracks"); hb->add_child(menu_track); menu_track->get_popup()->connect("item_pressed",this,"_menu_track"); @@ -3215,7 +3238,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h move_down_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_DOWN)); move_down_button->set_focus_mode(FOCUS_NONE); move_down_button->set_disabled(true); - move_down_button->set_tooltip("Move current track dosn."); + move_down_button->set_tooltip("Move current track down."); remove_button = memnew( ToolButton ); hb->add_child(remove_button); @@ -3224,6 +3247,37 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h remove_button->set_disabled(true); remove_button->set_tooltip("Remove selected track."); + + optimize_dialog = memnew( ConfirmationDialog ); + add_child(optimize_dialog); + optimize_dialog->set_title("Anim. Optimizer"); + VBoxContainer *optimize_vb = memnew( VBoxContainer ); + optimize_dialog->add_child(optimize_vb); + optimize_dialog->set_child_rect(optimize_vb); + optimize_linear_error = memnew( SpinBox ); + optimize_linear_error->set_max(1.0); + optimize_linear_error->set_min(0.001); + optimize_linear_error->set_step(0.001); + optimize_linear_error->set_val(0.05); + optimize_vb->add_margin_child("Max. Linear Error:",optimize_linear_error); + optimize_angular_error = memnew( SpinBox ); + optimize_angular_error->set_max(1.0); + optimize_angular_error->set_min(0.001); + optimize_angular_error->set_step(0.001); + optimize_angular_error->set_val(0.01); + + optimize_vb->add_margin_child("Max. Angular Error:",optimize_angular_error); + optimize_max_angle = memnew( SpinBox ); + optimize_vb->add_margin_child("Max Optimizable Angle:",optimize_max_angle); + optimize_max_angle->set_max(360.0); + optimize_max_angle->set_min(0.0); + optimize_max_angle->set_step(0.1); + optimize_max_angle->set_val(22); + + optimize_dialog->get_ok()->set_text("Optimize"); + + + /*keying = memnew( Button ); keying->set_toggle_mode(true); //keying->set_text("Keys"); @@ -3242,8 +3296,8 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h // menu->get_popup()->connect("item_pressed",this,"_menu_callback"); - ec = memnew (EmptyControl); - ec->set_minsize(Size2(0,50)); + ec = memnew (Control); + ec->set_custom_minimum_size(Size2(0,50)); add_child(ec); ec->set_v_size_flags(SIZE_EXPAND_FILL); @@ -3298,8 +3352,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h add_child(insert_confirm); insert_confirm->connect("confirmed",this,"_confirm_insert_list"); - EDITOR_DEF("animation_editor/confirm_insert_key",true); - click.click=ClickOver::CLICK_NONE; diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index 01f6e294cc..1f17922552 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -37,7 +37,7 @@ #include "scene/gui/scroll_bar.h" #include "scene/gui/tool_button.h" #include "scene/gui/file_dialog.h" -#include "scene/gui/empty_control.h" + #include "scene/resources/animation.h" #include "scene/animation/animation_cache.h" #include "scene_tree_editor.h" @@ -157,7 +157,7 @@ class AnimationKeyEditor : public VBoxContainer { PopupMenu *track_menu; PopupMenu *type_menu; - EmptyControl *ec; + Control *ec; TextureFrame *zoomicon; HSlider *zoom; //MenuButton *menu; @@ -169,6 +169,11 @@ class AnimationKeyEditor : public VBoxContainer { ToolButton *move_down_button; ToolButton *remove_button; + ConfirmationDialog *optimize_dialog; + SpinBox *optimize_linear_error; + SpinBox *optimize_angular_error; + SpinBox *optimize_max_angle; + SpinBox *step; MenuButton *menu_track; @@ -257,6 +262,7 @@ class AnimationKeyEditor : public VBoxContainer { StringName alc; void _animation_changed(); + void _animation_optimize(); void _scroll_changed(double); diff --git a/tools/editor/call_dialog.cpp b/tools/editor/call_dialog.cpp index 4548d7291c..2e4fb96a58 100644 --- a/tools/editor/call_dialog.cpp +++ b/tools/editor/call_dialog.cpp @@ -76,7 +76,7 @@ void CallDialog::_notification(int p_what) { _update_method_list(); } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { call->disconnect("pressed", this,"_call"); cancel->disconnect("pressed", this,"_cancel"); @@ -285,7 +285,7 @@ CallDialog::CallDialog() { property_editor->set_anchor_and_margin( MARGIN_TOP, ANCHOR_BEGIN, 50 ); property_editor->set_anchor_and_margin( MARGIN_LEFT, ANCHOR_RATIO, 0.55 ); property_editor->set_anchor_and_margin( MARGIN_BOTTOM, ANCHOR_END, 90 ); - property_editor->get_tree()->set_hide_root( true ); + property_editor->get_scene_tree()->set_hide_root( true ); property_editor->hide_top_label(); add_child(property_editor); diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 6de59f184a..2209b24245 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -487,6 +487,7 @@ FindReplaceDialog::FindReplaceDialog() { vb->add_child(error_label); + set_hide_on_ok(false); } @@ -507,15 +508,19 @@ void CodeTextEditor::_text_changed() { } void CodeTextEditor::_code_complete_timer_timeout() { + if (!is_visible()) + return; if (enable_complete_timer) text_editor->query_code_comple(); } -void CodeTextEditor::_complete_request(const String& p_request, int p_line) { +void CodeTextEditor::_complete_request() { List<String> entries; - _code_complete_script(text_editor->get_text(),p_request,p_line,&entries); + _code_complete_script(text_editor->get_text_for_completion(),&entries); // print_line("COMPLETE: "+p_request); + if (entries.size()==0) + return; Vector<String> strs; strs.resize(entries.size()); int i=0; @@ -555,7 +560,7 @@ void CodeTextEditor::_on_settings_change() { // AUTO BRACE COMPLETION text_editor->set_auto_brace_completion( - EDITOR_DEF("text_editor/auto_brace_complete", false) + EDITOR_DEF("text_editor/auto_brace_complete", true) ); code_complete_timer->set_wait_time( @@ -594,8 +599,21 @@ CodeTextEditor::CodeTextEditor() { add_child(text_editor); text_editor->set_area_as_parent_rect(); text_editor->set_margin(MARGIN_BOTTOM,20); - text_editor->add_font_override("font",get_font("source","Fonts")); + + String editor_font = EDITOR_DEF("text_editor/font", ""); + bool font_overrode = false; + if (editor_font!="") { + Ref<Font> fnt = ResourceLoader::load(editor_font); + if (fnt.is_valid()) { + text_editor->add_font_override("font",fnt); + font_overrode = true; + } + } + + if (!font_overrode) + text_editor->add_font_override("font",get_font("source","Fonts")); text_editor->set_show_line_numbers(true); + text_editor->set_brace_matching(true); line_col = memnew( Label ); add_child(line_col); @@ -632,6 +650,8 @@ CodeTextEditor::CodeTextEditor() { text_editor->connect("request_completion", this,"_complete_request"); Vector<String> cs; cs.push_back("."); + cs.push_back(","); + cs.push_back("("); text_editor->set_completion(true,cs); idle->connect("timeout", this,"_text_changed_idle_timeout"); diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h index 1804237f18..f82eaf5ec5 100644 --- a/tools/editor/code_editor.h +++ b/tools/editor/code_editor.h @@ -135,7 +135,7 @@ class CodeTextEditor : public Control { void _on_settings_change(); - void _complete_request(const String& p_request,int p_line); + void _complete_request(); protected: void set_error(const String& p_error); @@ -143,7 +143,7 @@ protected: virtual void _load_theme_settings() {} virtual void _validate_script()=0; - virtual void _code_complete_script(const String& p_code, const String& p_keyword,int p_line, List<String>* r_options) {}; + virtual void _code_complete_script(const String& p_code, List<String>* r_options) {}; void _text_changed_idle_timeout(); diff --git a/tools/editor/connections_dialog.cpp b/tools/editor/connections_dialog.cpp index d7158eb7e9..cf4b21510a 100644 --- a/tools/editor/connections_dialog.cpp +++ b/tools/editor/connections_dialog.cpp @@ -607,6 +607,14 @@ void ConnectionsDialog::_remove_confirm() { } */ + +struct _ConnectionsDialogMethodInfoSort { + + _FORCE_INLINE_ bool operator()(const MethodInfo& a, const MethodInfo& b) const { + return a.name < b.name; + } +}; + void ConnectionsDialog::update_tree() { if (!is_visible()) @@ -623,7 +631,8 @@ void ConnectionsDialog::update_tree() { node->get_signal_list(&node_signals); - + //node_signals.sort_custom<_ConnectionsDialogMethodInfoSort>(); + for(List<MethodInfo>::Element *E=node_signals.front();E;E=E->next()) { diff --git a/tools/editor/console.cpp b/tools/editor/console.cpp index 746f61ad67..6b37895bc4 100644 --- a/tools/editor/console.cpp +++ b/tools/editor/console.cpp @@ -129,7 +129,7 @@ void Console::_window_input_event(InputEvent p_event) { if (p_event.key.scancode==KEY_ESCAPE && !window_has_modal_stack() && is_visible()) { hide(); - get_scene()->call_group(0,"windows","_cancel_input_ID",p_event.ID); + get_tree()->call_group(0,"windows","_cancel_input_ID",p_event.ID); } @@ -153,7 +153,7 @@ void Console::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { _resized(); show(); diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp index 3a6b856247..f816e46bcf 100644 --- a/tools/editor/create_dialog.cpp +++ b/tools/editor/create_dialog.cpp @@ -225,7 +225,7 @@ void CreateDialog::_confirmed() { void CreateDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); _update_search(); @@ -289,7 +289,7 @@ CreateDialog::CreateDialog() { search_box->connect("input_event",this,"_sbox_input"); search_options = memnew( Tree ); vbc->add_margin_child("Matches:",search_options,true); - get_ok()->set_text("Open"); + get_ok()->set_text("Create"); get_ok()->set_disabled(true); register_text_enter(search_box); set_hide_on_ok(false); diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index bb4262e4b0..aeca76bb29 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -462,7 +462,7 @@ void EditorSelection::add_node(Node *p_node) { } selection[p_node]=meta; - p_node->connect("exit_scene",this,"_node_removed",varray(p_node),CONNECT_ONESHOT); + p_node->connect("exit_tree",this,"_node_removed",varray(p_node),CONNECT_ONESHOT); //emit_signal("selection_changed"); } @@ -478,7 +478,7 @@ void EditorSelection::remove_node(Node *p_node) { if (meta) memdelete(meta); selection.erase(p_node); - p_node->disconnect("exit_scene",this,"_node_removed"); + p_node->disconnect("exit_tree",this,"_node_removed"); //emit_signal("selection_changed"); } bool EditorSelection::is_selected(Node * p_node) const { diff --git a/tools/editor/editor_dir_dialog.cpp b/tools/editor/editor_dir_dialog.cpp index 790c3c8cd5..eec452ab7f 100644 --- a/tools/editor/editor_dir_dialog.cpp +++ b/tools/editor/editor_dir_dialog.cpp @@ -28,6 +28,9 @@ /*************************************************************************/ #include "editor_dir_dialog.h" #include "os/os.h" +#include "os/keyboard.h" +#include "tools/editor/editor_settings.h" + void EditorDirDialog::_update_dir(TreeItem* p_item) { @@ -39,12 +42,21 @@ void EditorDirDialog::_update_dir(TreeItem* p_item) { da->change_dir(cdir); da->list_dir_begin(); String p=da->get_next(); + + bool ishidden; + bool show_hidden = EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"); + while(p!="") { - if (da->current_is_dir() && !p.begins_with(".")) { - TreeItem *ti = tree->create_item(p_item); - ti->set_text(0,p); - ti->set_icon(0,get_icon("Folder","EditorIcons")); - ti->set_collapsed(true); + + ishidden = da->current_is_hidden(); + + if (show_hidden || !ishidden) { + if (da->current_is_dir() && !p.begins_with(".")) { + TreeItem *ti = tree->create_item(p_item); + ti->set_text(0,p); + ti->set_icon(0,get_icon("Folder","EditorIcons")); + ti->set_collapsed(true); + } } p=da->get_next(); @@ -69,7 +81,7 @@ void EditorDirDialog::reload() { void EditorDirDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { reload(); tree->connect("item_collapsed",this,"_item_collapsed",varray(),CONNECT_DEFERRED); } diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index daba52be03..5d72928e9c 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -142,7 +142,7 @@ void EditorFileSystemDirectory::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_file","idx"),&EditorFileSystemDirectory::get_file); ObjectTypeDB::bind_method(_MD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path); ObjectTypeDB::bind_method(_MD("get_file_types","idx"),&EditorFileSystemDirectory::get_file_type); - ObjectTypeDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::get_file_type); + ObjectTypeDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::is_missing_sources); ObjectTypeDB::bind_method(_MD("get_name"),&EditorFileSystemDirectory::get_name); ObjectTypeDB::bind_method(_MD("get_parent"),&EditorFileSystemDirectory::get_parent); @@ -681,12 +681,12 @@ void EditorFileSystem::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { _load_type_cache(); scan(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { if (use_threads && thread) { //abort thread if in progress abort_scan=true; @@ -992,6 +992,35 @@ void EditorFileSystem::_resource_saved(const String& p_path){ EditorFileSystem::get_singleton()->update_file(p_path); } +String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const { + + for(int i=0;i<p_dir->files.size();i++) { + for(int j=0;j<p_dir->files[i].meta.sources.size();j++) { + + if (p_dir->files[i].meta.sources[j].path==p_src) + return p_dir->get_file_path(i); + } + } + + for(int i=0;i<p_dir->subdirs.size();i++) { + + String ret = _find_first_from_source(p_dir->subdirs[i],p_src); + if (ret.length()>0) + return ret; + } + + return String(); +} + + +String EditorFileSystem::find_resource_from_source(const String& p_path) const { + + + if (filesystem) + return _find_first_from_source(filesystem,p_path); + return String(); +} + void EditorFileSystem::update_file(const String& p_file) { EditorFileSystemDirectory *fs=NULL; diff --git a/tools/editor/editor_file_system.h b/tools/editor/editor_file_system.h index c26fc02548..2d14f9012f 100644 --- a/tools/editor/editor_file_system.h +++ b/tools/editor/editor_file_system.h @@ -75,6 +75,7 @@ class EditorFileSystemDirectory : public Object { static void _bind_methods(); + friend class EditorFileSystem; public: @@ -180,6 +181,7 @@ class EditorFileSystem : public Node { List<String> sources_changed; static void _resource_saved(const String& p_path); + String _find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const; protected: @@ -197,6 +199,7 @@ public: void scan_sources(); void get_changed_sources(List<String> *r_changed); void update_file(const String& p_file); + String find_resource_from_source(const String& p_path) const; EditorFileSystemDirectory *get_path(const String& p_path); String get_file_type(const String& p_file) const; EditorFileSystem(); diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp index 819da4bb45..7deb136470 100644 --- a/tools/editor/editor_help.cpp +++ b/tools/editor/editor_help.cpp @@ -270,7 +270,7 @@ void EditorHelpSearch::_confirmed() { void EditorHelpSearch::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); _update_search(); @@ -293,7 +293,7 @@ void EditorHelpSearch::_bind_methods() { ObjectTypeDB::bind_method(_MD("_text_changed"),&EditorHelpSearch::_text_changed); ObjectTypeDB::bind_method(_MD("_confirmed"),&EditorHelpSearch::_confirmed); ObjectTypeDB::bind_method(_MD("_sbox_input"),&EditorHelpSearch::_sbox_input); - ObjectTypeDB::bind_method(_MD("_update_search"),&EditorHelpSearch::_sbox_input); + ObjectTypeDB::bind_method(_MD("_update_search"),&EditorHelpSearch::_update_search); ADD_SIGNAL(MethodInfo("go_to_help")); @@ -1361,8 +1361,8 @@ EditorHelp::EditorHelp(EditorNode *p_editor) { Separator *hs = memnew( VSeparator ); panel_hb->add_child(hs); - EmptyControl *ec = memnew( EmptyControl ); - ec->set_minsize(Size2(200,1)); + Control *ec = memnew( Control ); + ec->set_custom_minimum_size(Size2(200,1)); panel_hb->add_child(ec); search = memnew( LineEdit ); ec->add_child(search); @@ -1390,7 +1390,9 @@ EditorHelp::EditorHelp(EditorNode *p_editor) { { PanelContainer *pc = memnew( PanelContainer ); - pc->add_style_override("panel",get_stylebox("normal","TextEdit")); + Ref<StyleBoxFlat> style( memnew( StyleBoxFlat ) ); + style->set_bg_color( EditorSettings::get_singleton()->get("text_editor/background_color") ); + pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit")); h_split->add_child(pc); class_desc = memnew( RichTextLabel ); pc->add_child(class_desc); diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 6e8cb987e9..e6ec11e9d3 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -292,7 +292,11 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const _add_filter_to_list(exported,"*"); } else { _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported); - _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); + String cf = EditorImportExport::get_singleton()->get_export_custom_filter(); + if (cf!="") + cf+=","; + cf+="*.flags"; + _add_filter_to_list(exported,cf); } @@ -361,8 +365,12 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const } } } + String cf = EditorImportExport::get_singleton()->get_export_custom_filter(); + if (cf!="") + cf+=","; + cf+="*.flags"; + _add_filter_to_list(exported,cf); - _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } @@ -896,6 +904,16 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func return OK; } +static int _get_pad(int p_alignment, int p_n) { + + int rest = p_n % p_alignment; + int pad = 0; + if (rest > 0) { + pad = p_alignment - rest; + }; + + return pad; +}; Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) { @@ -922,11 +940,19 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total); pd->count++; pd->ftmp->store_buffer(p_data.ptr(),p_data.size()); + if (pd->alignment > 1) { + + int pad = _get_pad(pd->alignment, pd->ftmp->get_pos()); + for (int i=0; i<pad; i++) { + + pd->ftmp->store_8(0); + }; + }; return OK; } -Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) { +Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p_alignment) { EditorProgress ep("savepack","Packing",102); @@ -938,13 +964,12 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) { dst->store_32(0); //pack version dst->store_32(VERSION_MAJOR); dst->store_32(VERSION_MINOR); - dst->store_32(VERSION_REVISION); + dst->store_32(0); //hmph for(int i=0;i<16;i++) { //reserved dst->store_32(0); } - size_t fcountpos = dst->get_pos(); dst->store_32(0); @@ -953,11 +978,20 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) { pd.f=dst; pd.ftmp=tmp; pd.count=0; + pd.alignment = p_alignment; Error err = export_project_files(save_pack_file,&pd,p_make_bundles); memdelete(tmp); if (err) return err; + if (p_alignment > 1) { + int pad = _get_pad(p_alignment, dst->get_pos()); + for (int i=0; i<pad; i++) { + + dst->store_8(0); + }; + }; + size_t ofsplus = dst->get_pos(); //append file @@ -1133,10 +1167,36 @@ EditorImportExport* EditorImportExport::singleton=NULL; void EditorImportExport::add_import_plugin(const Ref<EditorImportPlugin>& p_plugin) { + // Need to make sure the name is unique if we are going to lookup by it + ERR_FAIL_COND(by_idx.has(p_plugin->get_name())); + by_idx[ p_plugin->get_name() ]=plugins.size(); plugins.push_back(p_plugin); } +void EditorImportExport::remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin) { + + String plugin_name = p_plugin->get_name(); + + // Keep the indices the same + // Find the index of the target plugin + ERR_FAIL_COND(!by_idx.has(plugin_name)); + int idx = by_idx[plugin_name]; + int last_idx = plugins.size() - 1; + + // Swap the last plugin and the target one + SWAP(plugins[idx], plugins[last_idx]); + + // Update the index of the old last one + by_idx[plugins[idx]->get_name()] = idx; + + // Remove the target plugin's by_idx entry + by_idx.erase(plugin_name); + + // Erase the plugin + plugins.remove(last_idx); +} + int EditorImportExport::get_import_plugin_count() const{ return plugins.size(); diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h index 8305e3c88c..a4723f41d0 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -100,6 +100,7 @@ protected: Vector<TempData> file_ofs; EditorProgress *ep; int count; + int alignment; }; @@ -121,7 +122,7 @@ public: Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles); - Error save_pack(FileAccess *p_where, bool p_make_bundles=false); + Error save_pack(FileAccess *p_where, bool p_make_bundles=false, int p_alignment = 1); virtual String get_name() const =0; virtual ImageCompression get_image_compression() const=0; virtual Ref<Texture> get_logo() const =0; @@ -270,6 +271,7 @@ public: static EditorImportExport* get_singleton() { return singleton; } void add_import_plugin(const Ref<EditorImportPlugin>& p_plugin); + void remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin); int get_import_plugin_count() const; Ref<EditorImportPlugin> get_import_plugin(int p_idx) const; Ref<EditorImportPlugin> get_import_plugin_by_name(const String& p_string) const; diff --git a/tools/editor/editor_log.cpp b/tools/editor/editor_log.cpp index 23ba88ef81..7c3fa6c1bd 100644 --- a/tools/editor/editor_log.cpp +++ b/tools/editor/editor_log.cpp @@ -76,7 +76,7 @@ void EditorLog::_error_handler(void *p_self, const char*p_func, const char*p_fil void EditorLog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { log->add_color_override("default_color",get_color("font_color","Tree")); tb->set_normal_texture( get_icon("Collapse","EditorIcons")); @@ -203,9 +203,9 @@ EditorLog::EditorLog() { tb->connect("pressed",this,"_close_request"); - ec = memnew( EmptyControl); + ec = memnew( Control); vb->add_child(ec); - ec->set_minsize(Size2(0,100)); + ec->set_custom_minimum_size(Size2(0,100)); ec->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/tools/editor/editor_log.h b/tools/editor/editor_log.h index b6cd951287..27cce4a584 100644 --- a/tools/editor/editor_log.h +++ b/tools/editor/editor_log.h @@ -33,7 +33,7 @@ #include "scene/gui/label.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/texture_button.h" -#include "scene/gui/empty_control.h" +//#include "scene/gui/empty_control.h" #include "scene/gui/box_container.h" #include "scene/gui/panel_container.h" #include "scene/gui/texture_frame.h" @@ -50,7 +50,7 @@ class EditorLog : public PanelContainer { TextureButton *tb; HBoxContainer *title_hb; // PaneDrag *pd; - EmptyControl *ec; + Control *ec; static void _error_handler(void *p_self, const char*p_func, const char*p_file,int p_line, const char*p_error,const char*p_errorexp,ErrorHandlerType p_type); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 701704fbfa..41545b887a 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -75,6 +75,7 @@ #include "plugins/tile_map_editor_plugin.h" #include "plugins/cube_grid_theme_editor_plugin.h" #include "plugins/shader_editor_plugin.h" +#include "plugins/shader_graph_editor_plugin.h" #include "plugins/path_editor_plugin.h" #include "plugins/rich_text_editor_plugin.h" #include "plugins/collision_polygon_editor_plugin.h" @@ -88,6 +89,8 @@ #include "plugins/animation_player_editor_plugin.h" #include "plugins/baked_light_editor_plugin.h" #include "plugins/polygon_2d_editor_plugin.h" +#include "plugins/navigation_polygon_editor_plugin.h" +#include "plugins/light_occluder_2d_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -140,7 +143,7 @@ void EditorNode::_unhandled_input(const InputEvent& p_event) { void EditorNode::_notification(int p_what) { - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { editor_data.save_editor_external_data(); log->deinit(); // do not get messages anymore @@ -213,13 +216,14 @@ void EditorNode::_notification(int p_what) { } } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { + //MessageQueue::get_singleton()->push_call(this,"_get_scene_metadata"); - get_scene()->set_editor_hint(true); - get_scene()->get_root()->set_as_audio_listener(false); - get_scene()->get_root()->set_as_audio_listener_2d(false); - get_scene()->set_auto_accept_quit(false); + get_tree()->set_editor_hint(true); + get_tree()->get_root()->set_as_audio_listener(false); + get_tree()->get_root()->set_as_audio_listener_2d(false); + get_tree()->set_auto_accept_quit(false); //VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport(),false); //import_monitor->scan_changes(); @@ -228,6 +232,8 @@ void EditorNode::_notification(int p_what) { VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport(),true); VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport(),true); + VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(),true); + _editor_select(1); if (defer_load_scene!="") { @@ -242,7 +248,7 @@ void EditorNode::_notification(int p_what) { if (ok!=OK) OS::get_singleton()->set_exit_code(255); defer_translatable=""; - get_scene()->quit(); + get_tree()->quit(); } /* @@ -335,6 +341,19 @@ void EditorNode::_vp_resized() { } +void EditorNode::_rebuild_import_menu() +{ + PopupMenu* p = import_menu->get_popup(); + p->clear(); + p->add_item("Sub-Scene", FILE_IMPORT_SUBSCENE); + p->add_separator(); + for (int i = 0; i < editor_import_export->get_import_plugin_count(); i++) { + p->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(), IMPORT_PLUGIN_BASE + i); + } + p->add_separator(); + p->add_item("Re-Import..", SETTINGS_IMPORT); +} + void EditorNode::_node_renamed() { if (property_editor) @@ -977,6 +996,15 @@ void EditorNode::_dialog_action(String p_file) { } } break; + + case FILE_SAVE_AND_RUN: { + if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { + + _save_scene(p_file); + _run(false); + } + } break; + case FILE_EXPORT_MESH_LIBRARY: { Ref<MeshLibrary> ml; @@ -1232,7 +1260,7 @@ void EditorNode::_edit_current() { Node * current_node = current_obj->cast_to<Node>(); ERR_FAIL_COND(!current_node); - ERR_FAIL_COND(!current_node->is_inside_scene()); + ERR_FAIL_COND(!current_node->is_inside_tree()); @@ -1310,6 +1338,8 @@ void EditorNode::_edit_current() { p->add_item("Copy Params",OBJECT_COPY_PARAMS); p->add_item("Set Params",OBJECT_PASTE_PARAMS); p->add_separator(); + p->add_item("Make Resources Unique",OBJECT_UNIQUE_RESOURCES); + p->add_separator(); p->add_icon_item(gui_base->get_icon("Help","EditorIcons"),"Class Reference",OBJECT_REQUEST_HELP); List<MethodInfo> methods; current_obj->get_method_list(&methods); @@ -1388,13 +1418,10 @@ void EditorNode::_run(bool p_current,const String& p_custom) { } if (scene->get_filename()=="") { - - current_option=-1; //accept->get_cancel()->hide(); - accept->get_ok()->set_text("I see.."); - accept->set_text("Scene has never been saved. Save before running!"); - accept->popup_centered(Size2(300,70));; + /**/ + _menu_option_confirm(FILE_SAVE_BEFORE_RUN, false); return; } @@ -1661,6 +1688,18 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } break; + case FILE_SAVE_BEFORE_RUN: { + if (!p_confirmed) { + accept->get_ok()->set_text("Yes"); + accept->set_text("This scene has never been saved. Save before running?"); + accept->popup_centered(Size2(300, 70)); + break; + } + + _menu_option(FILE_SAVE_AS_SCENE); + _menu_option_confirm(FILE_SAVE_AND_RUN, true); + } break; + case FILE_DUMP_STRINGS: { Node *scene = edited_scene; @@ -1900,7 +1939,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } _menu_option_confirm(RUN_STOP,true); - get_scene()->quit(); + get_tree()->quit(); } break; case FILE_EXTERNAL_OPEN_SCENE: { @@ -1946,6 +1985,25 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { log->add_message("REDO: "+action); } break; + + case EDIT_REVERT: { + + Node *scene = get_edited_scene(); + + if (!scene) + break; + + if (unsaved_cache && !p_confirmed) { + confirmation->get_ok()->set_text("Revert"); + confirmation->set_text("This action cannot be undone. Revert anyway?"); + confirmation->popup_centered(Size2(300,70)); + break; + } + + Error err = load_scene(scene->get_filename()); + + } break; + #if 0 case NODE_EXTERNAL_INSTANCE: { @@ -2023,6 +2081,47 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { editor_data.paste_object_params(current); editor_data.get_undo_redo().clear_history(); } break; + case OBJECT_UNIQUE_RESOURCES: { + + editor_data.apply_changes_in_editors();; + if (current) { + List<PropertyInfo> props; + current->get_property_list(&props); + Map<RES,RES> duplicates; + for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { + + if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) + continue; + + Variant v = current->get(E->get().name); + if (v.is_ref()) { + REF ref = v; + if (ref.is_valid()) { + + RES res = ref; + if (res.is_valid()) { + + if (!duplicates.has(res)) { + duplicates[res]=res->duplicate(); + } + res=duplicates[res]; + + current->set(E->get().name,res); + } + + } + } + + } + } + + editor_data.get_undo_redo().clear_history(); + if (editor_plugin_screen) { //reload editor plugin + editor_plugin_over->edit(NULL); + editor_plugin_over->edit(current); + } + + } break; case OBJECT_CALL_METHOD: { editor_data.apply_changes_in_editors();; @@ -2079,7 +2178,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { break; } - get_scene()->quit(); + get_tree()->quit(); String exec = OS::get_singleton()->get_executable_path(); List<String> args; @@ -2326,6 +2425,19 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) { } +void EditorNode::add_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import) { + + editor_import_export->add_import_plugin(p_editor_import); + _rebuild_import_menu(); +} + +void EditorNode::remove_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import) { + + editor_import_export->remove_import_plugin(p_editor_import); + _rebuild_import_menu(); +} + + void EditorNode::set_edited_scene(Node *p_scene) { if (edited_scene) { @@ -2337,8 +2449,8 @@ void EditorNode::set_edited_scene(Node *p_scene) { if (edited_scene && edited_scene->cast_to<Popup>()) edited_scene->cast_to<Popup>()->show(); //show popups scene_tree_dock->set_edited_scene(edited_scene); - if (get_scene()) - get_scene()->set_edited_scene_root(edited_scene); + if (get_tree()) + get_tree()->set_edited_scene_root(edited_scene); if (edited_scene) { if (p_scene->get_parent()!=scene_root) @@ -2382,7 +2494,7 @@ void EditorNode::_fetch_translatable_strings(const Object *p_object,Set<StringNa Error EditorNode::save_translatable_strings(const String& p_to_file) { - if (!is_inside_scene()) { + if (!is_inside_tree()) { defer_translatable=p_to_file; return OK; } @@ -2576,7 +2688,7 @@ Error EditorNode::save_optimized_copy(const String& p_scene,const String& p_pres Error EditorNode::load_scene(const String& p_scene) { - if (!is_inside_scene()) { + if (!is_inside_tree()) { defer_load_scene = p_scene; return OK; } @@ -2776,6 +2888,8 @@ void EditorNode::animation_editor_make_visible(bool p_visible) { //pd_anim->hide(); animation_editor->hide(); // scene_root_parent->set_margin(MARGIN_TOP,0); + if (!animation_vb->get_parent_control()) + return; animation_vb->get_parent_control()->minimum_size_changed(); top_split->set_collapsed(true); } @@ -3088,6 +3202,9 @@ void EditorNode::_bind_methods() { ObjectTypeDB::bind_method("_sources_changed",&EditorNode::_sources_changed); ObjectTypeDB::bind_method("_fs_changed",&EditorNode::_fs_changed); + ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin); + ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin); + ObjectTypeDB::bind_method(_MD("get_gui_base"), &EditorNode::get_gui_base); ADD_SIGNAL( MethodInfo("play_pressed") ); ADD_SIGNAL( MethodInfo("pause_pressed") ); @@ -3148,6 +3265,11 @@ Error EditorNode::export_platform(const String& p_platform, const String& p_path return OK; } +void EditorNode::show_warning(const String& p_text) { + + warning->set_text(p_text); + warning->popup_centered_minsize(); +} EditorNode::EditorNode() { @@ -3165,6 +3287,7 @@ EditorNode::EditorNode() { EditorSettings::create(); ResourceLoader::set_abort_on_missing_resources(false); + FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files")); ResourceLoader::set_error_notify_func(this,_load_error_notify); ResourceLoader::set_timestamp_on_load(true); @@ -3200,7 +3323,7 @@ EditorNode::EditorNode() { gui_base->set_area_as_parent_rect(); - Ref<Theme> theme( memnew( Theme ) ); + theme = Ref<Theme>( memnew( Theme ) ); gui_base->set_theme( theme ); editor_register_icons(theme); editor_register_fonts(theme); @@ -3263,13 +3386,13 @@ EditorNode::EditorNode() { main_editor_tabs->connect("tab_changed",this,"_editor_select"); HBoxContainer *srth = memnew( HBoxContainer ); srt->add_child( srth ); - EmptyControl *tec = memnew( EmptyControl ); - tec->set_minsize(Size2(100,0)); + Control *tec = memnew( Control ); + tec->set_custom_minimum_size(Size2(100,0)); tec->set_h_size_flags(Control::SIZE_EXPAND_FILL); srth->add_child(tec); srth->add_child(main_editor_tabs); - tec = memnew( EmptyControl ); - tec->set_minsize(Size2(100,0)); + tec = memnew( Control ); + tec->set_custom_minimum_size(Size2(100,0)); srth->add_child(tec); tec->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -3293,6 +3416,8 @@ EditorNode::EditorNode() { scene_root = memnew( Viewport ); + + //scene_root_base->add_child(scene_root); scene_root->set_meta("_editor_disable_input",true); VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport(),true); @@ -3377,7 +3502,7 @@ EditorNode::EditorNode() { p->add_item("New Scene",FILE_NEW_SCENE); p->add_item("Open Scene..",FILE_OPEN_SCENE,KEY_MASK_CMD+KEY_O); p->add_item("Save Scene",FILE_SAVE_SCENE,KEY_MASK_CMD+KEY_S); - p->add_item("Save Scene As..",FILE_SAVE_AS_SCENE); + p->add_item("Save Scene As..",FILE_SAVE_AS_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S); p->add_separator(); p->add_item("Goto Prev. Scene",FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P); p->add_submenu_item("Open Recent","RecentScenes",FILE_OPEN_RECENT); @@ -3405,6 +3530,8 @@ EditorNode::EditorNode() { p->add_separator(); p->add_item("Project Settings",RUN_SETTINGS); p->add_separator(); + p->add_item("Revert Scene",EDIT_REVERT); + p->add_separator(); p->add_item("Quit to Project List",RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_Q); p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q); @@ -3449,8 +3576,6 @@ EditorNode::EditorNode() { left_menu_hb->add_child( import_menu ); p=import_menu->get_popup(); - p->add_item("Sub-Scene",FILE_IMPORT_SUBSCENE); - p->add_separator(); p->connect("item_pressed",this,"_menu_option"); export_button = memnew( ToolButton ); @@ -3488,7 +3613,7 @@ EditorNode::EditorNode() { play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons")); play_button->set_focus_mode(Control::FOCUS_NONE); play_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY)); - play_button->set_tooltip("Start the scene (F5)."); + play_button->set_tooltip("Play the project (F5)."); @@ -3629,8 +3754,8 @@ EditorNode::EditorNode() { top_pallete->add_child(resources_dock); top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); - EmptyControl *editor_spacer = memnew( EmptyControl ); - editor_spacer->set_minsize(Size2(260,200)); + Control *editor_spacer = memnew( Control ); + editor_spacer->set_custom_minimum_size(Size2(260,200)); editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor_vsplit->add_child( editor_spacer ); editor_spacer->add_child( top_pallete ); @@ -3641,8 +3766,8 @@ EditorNode::EditorNode() { prop_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); - editor_spacer = memnew( EmptyControl ); - editor_spacer->set_minsize(Size2(260,200)); + editor_spacer = memnew( Control ); + editor_spacer->set_custom_minimum_size(Size2(260,200)); editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor_vsplit->add_child( editor_spacer ); editor_spacer->add_child( prop_pallete ); @@ -3858,6 +3983,8 @@ EditorNode::EditorNode() { logo->set_pos(Point2(20,20)); logo->set_texture(gui_base->get_icon("Logo","EditorIcons") ); + warning = memnew( AcceptDialog ); + add_child(warning); @@ -3950,8 +4077,8 @@ EditorNode::EditorNode() { Ref<EditorSceneImportPlugin> _scene_import = memnew(EditorSceneImportPlugin(this) ); Ref<EditorSceneImporterCollada> _collada_import = memnew( EditorSceneImporterCollada); _scene_import->add_importer(_collada_import); - Ref<EditorSceneImporterFBXConv> _fbxconv_import = memnew( EditorSceneImporterFBXConv); - _scene_import->add_importer(_fbxconv_import); +// Ref<EditorSceneImporterFBXConv> _fbxconv_import = memnew( EditorSceneImporterFBXConv); +// _scene_import->add_importer(_fbxconv_import); editor_import_export->add_import_plugin( _scene_import); editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this)))); @@ -3959,11 +4086,6 @@ EditorNode::EditorNode() { editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this)))); - - for(int i=0;i<editor_import_export->get_import_plugin_count();i++) { - import_menu->get_popup()->add_item(editor_import_export->get_import_plugin(i)->get_visible_name(),IMPORT_PLUGIN_BASE+i); - } - editor_import_export->add_export_plugin( Ref<EditorTextureExportPlugin>( memnew(EditorTextureExportPlugin))); add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) ); @@ -3971,7 +4093,10 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( ScriptEditorPlugin(this) ) ); add_editor_plugin( memnew( EditorHelpPlugin(this) ) ); add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) ); - add_editor_plugin( memnew( ShaderEditorPlugin(this) ) ); + add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,true) ) ); + add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,false) ) ); + add_editor_plugin( memnew( ShaderEditorPlugin(this,true) ) ); + add_editor_plugin( memnew( ShaderEditorPlugin(this,false) ) ); add_editor_plugin( memnew( CameraEditorPlugin(this) ) ); add_editor_plugin( memnew( SampleEditorPlugin(this) ) ); add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) ); @@ -3997,6 +4122,8 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( PathEditorPlugin(this) ) ); add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) ); add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) ); + add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) ); + add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) ); for(int i=0;i<EditorPlugins::get_plugin_count();i++) add_editor_plugin( EditorPlugins::create(i,this) ); @@ -4005,9 +4132,7 @@ EditorNode::EditorNode() { circle_step_frame=OS::get_singleton()->get_frames_drawn();; circle_step=0; - - import_menu->get_popup()->add_separator(); - import_menu->get_popup()->add_item("Re-Import..",SETTINGS_IMPORT); + _rebuild_import_menu(); editor_plugin_screen=NULL; editor_plugin_over=NULL; @@ -4022,9 +4147,9 @@ EditorNode::EditorNode() { Globals::get_singleton()->set("debug/indicators_enabled",true); Globals::get_singleton()->set("render/room_cull_enabled",false); - theme->set_color("prop_category","Editor",Color::hex(0x3f3945ff)); - theme->set_color("prop_section","Editor",Color::hex(0x38323dff)); - theme->set_color("prop_subsection","Editor",Color::hex(0x342e39ff)); + theme->set_color("prop_category","Editor",Color::hex(0x403d41ff)); + theme->set_color("prop_section","Editor",Color::hex(0x383539ff)); + theme->set_color("prop_subsection","Editor",Color::hex(0x343135ff)); theme->set_color("fg_selected","Editor",Color::html("ffbd8e8e")); theme->set_color("fg_error","Editor",Color::html("ffbd8e8e")); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 2cec301cf6..531eccb546 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -108,6 +108,8 @@ class EditorNode : public Node { FILE_OPEN_SCENE, FILE_SAVE_SCENE, FILE_SAVE_AS_SCENE, + FILE_SAVE_BEFORE_RUN, + FILE_SAVE_AND_RUN, FILE_IMPORT_SUBSCENE, FILE_EXPORT_PROJECT, FILE_EXPORT_MESH_LIBRARY, @@ -125,6 +127,7 @@ class EditorNode : public Node { FILE_EXTERNAL_OPEN_SCENE, EDIT_UNDO, EDIT_REDO, + EDIT_REVERT, RESOURCE_NEW, RESOURCE_LOAD, RESOURCE_SAVE, @@ -133,6 +136,7 @@ class EditorNode : public Node { RESOURCE_COPY, OBJECT_COPY_PARAMS, OBJECT_PASTE_PARAMS, + OBJECT_UNIQUE_RESOURCES, OBJECT_CALL_METHOD, OBJECT_REQUEST_HELP, RUN_PLAY, @@ -211,6 +215,7 @@ class EditorNode : public Node { AcceptDialog *load_error_dialog; Control *scene_root_base; + Ref<Theme> theme; PopupMenu *recent_scenes; Button *property_back; @@ -227,6 +232,7 @@ class EditorNode : public Node { ConfirmationDialog *open_recent_confirmation; AcceptDialog *accept; AcceptDialog *about; + AcceptDialog *warning; //OptimizedPresetsDialog *optimized_presets; EditorSettingsDialog *settings_config_dialog; @@ -335,6 +341,8 @@ class EditorNode : public Node { void _show_messages(); void _vp_resized(); + void _rebuild_import_menu(); + void _save_scene(String p_file); @@ -416,6 +424,9 @@ public: static void add_editor_plugin(EditorPlugin *p_editor); static void remove_editor_plugin(EditorPlugin *p_editor); + void add_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import); + void remove_editor_import_plugin(const Ref<EditorImportPlugin>& p_editor_import); + void edit_node(Node *p_node); void edit_resource(const Ref<Resource>& p_resource); @@ -471,6 +482,12 @@ public: void stop_child_process(); + Ref<Theme> get_editor_theme() const { return theme; } + + + void show_warning(const String& p_text); + + Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false); static void register_editor_types(); diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp index 2a2ad63d32..1bad1dc6ac 100644 --- a/tools/editor/editor_plugin.cpp +++ b/tools/editor/editor_plugin.cpp @@ -73,6 +73,12 @@ void EditorPlugin::add_custom_control(CustomControlContainer p_location,Control } break; case CONTAINER_CANVAS_EDITOR_SIDE: { + CanvasItemEditor::get_singleton()->get_palette_split()->add_child(p_control); + + } break; + case CONTAINER_CANVAS_EDITOR_BOTTOM: { + + CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(p_control); } break; diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h index bcde0f73fb..4f2341d3b1 100644 --- a/tools/editor/editor_plugin.h +++ b/tools/editor/editor_plugin.h @@ -66,7 +66,8 @@ public: CONTAINER_SPATIAL_EDITOR_SIDE, CONTAINER_SPATIAL_EDITOR_BOTTOM, CONTAINER_CANVAS_EDITOR_MENU, - CONTAINER_CANVAS_EDITOR_SIDE + CONTAINER_CANVAS_EDITOR_SIDE, + CONTAINER_CANVAS_EDITOR_BOTTOM }; //TODO: send a resoucre for editing to the editor node? diff --git a/tools/editor/editor_run_native.cpp b/tools/editor/editor_run_native.cpp index be1a124fc2..17117be188 100644 --- a/tools/editor/editor_run_native.cpp +++ b/tools/editor/editor_run_native.cpp @@ -33,7 +33,7 @@ void EditorRunNative::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { List<StringName> ep; EditorImportExport::get_singleton()->get_export_platforms(&ep); diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 2b54a334bf..deb5d86a2e 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -386,6 +386,8 @@ void EditorSettings::_load_defaults() { set("global/font",""); hints["global/font"]=PropertyInfo(Variant::STRING,"global/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt"); + set("global/autoscan_project_path",""); + hints["global/autoscan_project_path"]=PropertyInfo(Variant::STRING,"global/autoscan_project_path",PROPERTY_HINT_GLOBAL_DIR); set("global/default_project_path",""); hints["global/default_project_path"]=PropertyInfo(Variant::STRING,"global/default_project_path",PROPERTY_HINT_GLOBAL_DIR); set("global/default_project_export_path",""); @@ -401,6 +403,8 @@ void EditorSettings::_load_defaults() { set("text_editor/string_color",Color::html("ef6ebe")); set("text_editor/symbol_color",Color::html("badfff")); set("text_editor/selection_color",Color::html("7b5dbe")); + set("text_editor/brace_mismatch_color",Color(1,0.2,0.2)); + set("text_editor/current_line_color",Color(0.3,0.5,0.8,0.15)); set("text_editor/idle_parse_delay",2); set("text_editor/create_signal_callbacks",true); @@ -410,12 +414,18 @@ void EditorSettings::_load_defaults() { set("text_editor/auto_brace_complete", false); + set("scenetree_editor/duplicate_node_name_num_separator",0); + hints["scenetree_editor/duplicate_node_name_num_separator"]=PropertyInfo(Variant::INT,"scenetree_editor/duplicate_node_name_num_separator",PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"); + + set("3d_editor/default_fov",45.0); set("3d_editor/default_z_near",0.1); set("3d_editor/default_z_far",500.0); set("3d_editor/navigation_scheme",0); hints["3d_editor/navigation_scheme"]=PropertyInfo(Variant::INT,"3d_editor/navigation_scheme",PROPERTY_HINT_ENUM,"Godot,Maya,Modo"); + set("3d_editor/zoom_style",0); + hints["3d_editor/zoom_style"]=PropertyInfo(Variant::INT,"3d_editor/zoom_style",PROPERTY_HINT_ENUM,"Vertical, Horizontal"); set("3d_editor/orbit_modifier",0); hints["3d_editor/orbit_modifier"]=PropertyInfo(Variant::INT,"3d_editor/orbit_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl"); set("3d_editor/pan_modifier",1); @@ -436,10 +446,13 @@ void EditorSettings::_load_defaults() { set("text_editor/create_signal_callbacks",true); + set("file_dialog/show_hidden_files", false); set("animation/autorename_animation_tracks",true); + set("animation/confirm_insert_track",true); set("property_editor/texture_preview_width",48); + set("property_editor/auto_refresh_interval",0.3); set("help/doc_path",""); set("import/ask_save_before_reimport",false); @@ -462,10 +475,10 @@ void EditorSettings::notify_changes() { _THREAD_SAFE_METHOD_ - SceneMainLoop *sml=NULL; + SceneTree *sml=NULL; if (OS::get_singleton()->get_main_loop()) - sml = OS::get_singleton()->get_main_loop()->cast_to<SceneMainLoop>(); + sml = OS::get_singleton()->get_main_loop()->cast_to<SceneTree>(); if (!sml) { print_line("not SML"); diff --git a/tools/editor/groups_editor.cpp b/tools/editor/groups_editor.cpp index f0a2a6a758..52db562d8a 100644 --- a/tools/editor/groups_editor.cpp +++ b/tools/editor/groups_editor.cpp @@ -36,7 +36,7 @@ void GroupsEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed", this,"_close"); } } diff --git a/tools/editor/icons/icon_add.png b/tools/editor/icons/icon_add.png Binary files differindex 1a97f356d6..26283ca67c 100644 --- a/tools/editor/icons/icon_add.png +++ b/tools/editor/icons/icon_add.png diff --git a/tools/editor/icons/icon_animation.png b/tools/editor/icons/icon_animation.png Binary files differindex 6af126bf37..ac663c0554 100644 --- a/tools/editor/icons/icon_animation.png +++ b/tools/editor/icons/icon_animation.png diff --git a/tools/editor/icons/icon_atlas_texture.png b/tools/editor/icons/icon_atlas_texture.png Binary files differindex 3da9f0bee4..0051b0cda4 100644 --- a/tools/editor/icons/icon_atlas_texture.png +++ b/tools/editor/icons/icon_atlas_texture.png diff --git a/tools/editor/icons/icon_audio_stream_gibberish.png b/tools/editor/icons/icon_audio_stream_gibberish.png Binary files differindex f10671e8a2..95470c298e 100644 --- a/tools/editor/icons/icon_audio_stream_gibberish.png +++ b/tools/editor/icons/icon_audio_stream_gibberish.png diff --git a/tools/editor/icons/icon_auto_play.png b/tools/editor/icons/icon_auto_play.png Binary files differindex e454ca8c7b..1d5c957cc7 100644 --- a/tools/editor/icons/icon_auto_play.png +++ b/tools/editor/icons/icon_auto_play.png diff --git a/tools/editor/icons/icon_back_buffer_copy.png b/tools/editor/icons/icon_back_buffer_copy.png Binary files differnew file mode 100644 index 0000000000..b27eb39108 --- /dev/null +++ b/tools/editor/icons/icon_back_buffer_copy.png diff --git a/tools/editor/icons/icon_bake.png b/tools/editor/icons/icon_bake.png Binary files differindex b1b0f941da..ae06ce48e6 100644 --- a/tools/editor/icons/icon_bake.png +++ b/tools/editor/icons/icon_bake.png diff --git a/tools/editor/icons/icon_blend.png b/tools/editor/icons/icon_blend.png Binary files differindex 985b63d5d1..2a75f0b2f4 100644 --- a/tools/editor/icons/icon_blend.png +++ b/tools/editor/icons/icon_blend.png diff --git a/tools/editor/icons/icon_bone.png b/tools/editor/icons/icon_bone.png Binary files differindex 174b0bc167..81b6d8856e 100644 --- a/tools/editor/icons/icon_bone.png +++ b/tools/editor/icons/icon_bone.png diff --git a/tools/editor/icons/icon_bool.png b/tools/editor/icons/icon_bool.png Binary files differindex d465b7da07..3381033b00 100644 --- a/tools/editor/icons/icon_bool.png +++ b/tools/editor/icons/icon_bool.png diff --git a/tools/editor/icons/icon_canvas_item.png b/tools/editor/icons/icon_canvas_item.png Binary files differindex 99403bed21..add54ba1af 100644 --- a/tools/editor/icons/icon_canvas_item.png +++ b/tools/editor/icons/icon_canvas_item.png diff --git a/tools/editor/icons/icon_canvas_item_material.png b/tools/editor/icons/icon_canvas_item_material.png Binary files differnew file mode 100644 index 0000000000..2fe8921653 --- /dev/null +++ b/tools/editor/icons/icon_canvas_item_material.png diff --git a/tools/editor/icons/icon_canvas_item_shader.png b/tools/editor/icons/icon_canvas_item_shader.png Binary files differnew file mode 100644 index 0000000000..a5f4e7bf85 --- /dev/null +++ b/tools/editor/icons/icon_canvas_item_shader.png diff --git a/tools/editor/icons/icon_canvas_item_shader_graph.png b/tools/editor/icons/icon_canvas_item_shader_graph.png Binary files differnew file mode 100644 index 0000000000..bba966b43e --- /dev/null +++ b/tools/editor/icons/icon_canvas_item_shader_graph.png diff --git a/tools/editor/icons/icon_canvas_modulate.png b/tools/editor/icons/icon_canvas_modulate.png Binary files differnew file mode 100644 index 0000000000..2a34df7793 --- /dev/null +++ b/tools/editor/icons/icon_canvas_modulate.png diff --git a/tools/editor/icons/icon_check_box.png b/tools/editor/icons/icon_check_box.png Binary files differnew file mode 100644 index 0000000000..8a2b56cc3e --- /dev/null +++ b/tools/editor/icons/icon_check_box.png diff --git a/tools/editor/icons/icon_close.png b/tools/editor/icons/icon_close.png Binary files differindex 11fa746271..10e56d5bb8 100644 --- a/tools/editor/icons/icon_close.png +++ b/tools/editor/icons/icon_close.png diff --git a/tools/editor/icons/icon_close_hover.png b/tools/editor/icons/icon_close_hover.png Binary files differindex efcc9e7471..cb519691e5 100644 --- a/tools/editor/icons/icon_close_hover.png +++ b/tools/editor/icons/icon_close_hover.png diff --git a/tools/editor/icons/icon_collapse.png b/tools/editor/icons/icon_collapse.png Binary files differindex bd5c9765a5..23db9e42a7 100644 --- a/tools/editor/icons/icon_collapse.png +++ b/tools/editor/icons/icon_collapse.png diff --git a/tools/editor/icons/icon_collapse_hl.png b/tools/editor/icons/icon_collapse_hl.png Binary files differindex 7ed9a5c125..0dfbc8b175 100644 --- a/tools/editor/icons/icon_collapse_hl.png +++ b/tools/editor/icons/icon_collapse_hl.png diff --git a/tools/editor/icons/icon_connect.png b/tools/editor/icons/icon_connect.png Binary files differindex 24258414c4..745e445a61 100644 --- a/tools/editor/icons/icon_connect.png +++ b/tools/editor/icons/icon_connect.png diff --git a/tools/editor/icons/icon_del.png b/tools/editor/icons/icon_del.png Binary files differindex 5349af466e..10e56d5bb8 100644 --- a/tools/editor/icons/icon_del.png +++ b/tools/editor/icons/icon_del.png diff --git a/tools/editor/icons/icon_duplicate.png b/tools/editor/icons/icon_duplicate.png Binary files differindex bae4aa2c30..f854a14fd3 100644 --- a/tools/editor/icons/icon_duplicate.png +++ b/tools/editor/icons/icon_duplicate.png diff --git a/tools/editor/icons/icon_edit.png b/tools/editor/icons/icon_edit.png Binary files differindex 012a7f5f1d..157f785b83 100644 --- a/tools/editor/icons/icon_edit.png +++ b/tools/editor/icons/icon_edit.png diff --git a/tools/editor/icons/icon_edit_key.png b/tools/editor/icons/icon_edit_key.png Binary files differindex 43a7056f38..9ab1287fc6 100644 --- a/tools/editor/icons/icon_edit_key.png +++ b/tools/editor/icons/icon_edit_key.png diff --git a/tools/editor/icons/icon_edit_resource.png b/tools/editor/icons/icon_edit_resource.png Binary files differindex de538dfe95..31d0c68fc6 100644 --- a/tools/editor/icons/icon_edit_resource.png +++ b/tools/editor/icons/icon_edit_resource.png diff --git a/tools/editor/icons/icon_editor_focus.png b/tools/editor/icons/icon_editor_focus.png Binary files differindex f21d22ebd8..40ce11f381 100644 --- a/tools/editor/icons/icon_editor_focus.png +++ b/tools/editor/icons/icon_editor_focus.png diff --git a/tools/editor/icons/icon_enum.png b/tools/editor/icons/icon_enum.png Binary files differindex 2496e1d0db..ac36c96e28 100644 --- a/tools/editor/icons/icon_enum.png +++ b/tools/editor/icons/icon_enum.png diff --git a/tools/editor/icons/icon_event_player.png b/tools/editor/icons/icon_event_player.png Binary files differindex b67f91b1b3..68646b3dfe 100644 --- a/tools/editor/icons/icon_event_player.png +++ b/tools/editor/icons/icon_event_player.png diff --git a/tools/editor/icons/icon_file_server.png b/tools/editor/icons/icon_file_server.png Binary files differindex 27c99127c3..4bd94fa8c8 100644 --- a/tools/editor/icons/icon_file_server.png +++ b/tools/editor/icons/icon_file_server.png diff --git a/tools/editor/icons/icon_folder.png b/tools/editor/icons/icon_folder.png Binary files differindex 814f217edf..a450a7b297 100644 --- a/tools/editor/icons/icon_folder.png +++ b/tools/editor/icons/icon_folder.png diff --git a/tools/editor/icons/icon_font.png b/tools/editor/icons/icon_font.png Binary files differindex d9554183c2..3ffe4f1b17 100644 --- a/tools/editor/icons/icon_font.png +++ b/tools/editor/icons/icon_font.png diff --git a/tools/editor/icons/icon_g_d_script.png b/tools/editor/icons/icon_g_d_script.png Binary files differindex 3b1cc98c4d..88d865356c 100644 --- a/tools/editor/icons/icon_g_d_script.png +++ b/tools/editor/icons/icon_g_d_script.png diff --git a/tools/editor/icons/icon_graph_color_ramp.png b/tools/editor/icons/icon_graph_color_ramp.png Binary files differnew file mode 100644 index 0000000000..9031b5ec53 --- /dev/null +++ b/tools/editor/icons/icon_graph_color_ramp.png diff --git a/tools/editor/icons/icon_graph_comment.png b/tools/editor/icons/icon_graph_comment.png Binary files differnew file mode 100644 index 0000000000..bf7889c510 --- /dev/null +++ b/tools/editor/icons/icon_graph_comment.png diff --git a/tools/editor/icons/icon_graph_cube_uniform.png b/tools/editor/icons/icon_graph_cube_uniform.png Binary files differnew file mode 100644 index 0000000000..d1b92b4943 --- /dev/null +++ b/tools/editor/icons/icon_graph_cube_uniform.png diff --git a/tools/editor/icons/icon_graph_curve_map.png b/tools/editor/icons/icon_graph_curve_map.png Binary files differnew file mode 100644 index 0000000000..de5c32f09e --- /dev/null +++ b/tools/editor/icons/icon_graph_curve_map.png diff --git a/tools/editor/icons/icon_graph_default_texture.png b/tools/editor/icons/icon_graph_default_texture.png Binary files differnew file mode 100644 index 0000000000..da77ec9364 --- /dev/null +++ b/tools/editor/icons/icon_graph_default_texture.png diff --git a/tools/editor/icons/icon_graph_input.png b/tools/editor/icons/icon_graph_input.png Binary files differnew file mode 100644 index 0000000000..a396bc2350 --- /dev/null +++ b/tools/editor/icons/icon_graph_input.png diff --git a/tools/editor/icons/icon_graph_rgb.png b/tools/editor/icons/icon_graph_rgb.png Binary files differnew file mode 100644 index 0000000000..abffaedd34 --- /dev/null +++ b/tools/editor/icons/icon_graph_rgb.png diff --git a/tools/editor/icons/icon_graph_rgb_op.png b/tools/editor/icons/icon_graph_rgb_op.png Binary files differnew file mode 100644 index 0000000000..642fc838c2 --- /dev/null +++ b/tools/editor/icons/icon_graph_rgb_op.png diff --git a/tools/editor/icons/icon_graph_rgb_uniform.png b/tools/editor/icons/icon_graph_rgb_uniform.png Binary files differnew file mode 100644 index 0000000000..92c79997ef --- /dev/null +++ b/tools/editor/icons/icon_graph_rgb_uniform.png diff --git a/tools/editor/icons/icon_graph_scalar.png b/tools/editor/icons/icon_graph_scalar.png Binary files differnew file mode 100644 index 0000000000..028d0e9ea4 --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar.png diff --git a/tools/editor/icons/icon_graph_scalar_interp.png b/tools/editor/icons/icon_graph_scalar_interp.png Binary files differnew file mode 100644 index 0000000000..4f178a27c4 --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar_interp.png diff --git a/tools/editor/icons/icon_graph_scalar_op.png b/tools/editor/icons/icon_graph_scalar_op.png Binary files differnew file mode 100644 index 0000000000..0fc4cae94c --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar_op.png diff --git a/tools/editor/icons/icon_graph_scalar_uniform.png b/tools/editor/icons/icon_graph_scalar_uniform.png Binary files differnew file mode 100644 index 0000000000..fc6590a8cf --- /dev/null +++ b/tools/editor/icons/icon_graph_scalar_uniform.png diff --git a/tools/editor/icons/icon_graph_scalars_to_vec.png b/tools/editor/icons/icon_graph_scalars_to_vec.png Binary files differnew file mode 100644 index 0000000000..7ca39a2f56 --- /dev/null +++ b/tools/editor/icons/icon_graph_scalars_to_vec.png diff --git a/tools/editor/icons/icon_graph_texscreen.png b/tools/editor/icons/icon_graph_texscreen.png Binary files differnew file mode 100644 index 0000000000..e183a8fa56 --- /dev/null +++ b/tools/editor/icons/icon_graph_texscreen.png diff --git a/tools/editor/icons/icon_graph_texture_uniform.png b/tools/editor/icons/icon_graph_texture_uniform.png Binary files differnew file mode 100644 index 0000000000..7517ac1d92 --- /dev/null +++ b/tools/editor/icons/icon_graph_texture_uniform.png diff --git a/tools/editor/icons/icon_graph_time.png b/tools/editor/icons/icon_graph_time.png Binary files differnew file mode 100644 index 0000000000..b61e45589f --- /dev/null +++ b/tools/editor/icons/icon_graph_time.png diff --git a/tools/editor/icons/icon_graph_vec_dp.png b/tools/editor/icons/icon_graph_vec_dp.png Binary files differnew file mode 100644 index 0000000000..059c3025e7 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_dp.png diff --git a/tools/editor/icons/icon_graph_vec_interp.png b/tools/editor/icons/icon_graph_vec_interp.png Binary files differnew file mode 100644 index 0000000000..daf7a00203 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_interp.png diff --git a/tools/editor/icons/icon_graph_vec_length.png b/tools/editor/icons/icon_graph_vec_length.png Binary files differnew file mode 100644 index 0000000000..60ade8c90a --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_length.png diff --git a/tools/editor/icons/icon_graph_vec_op.png b/tools/editor/icons/icon_graph_vec_op.png Binary files differnew file mode 100644 index 0000000000..f2a7a51123 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_op.png diff --git a/tools/editor/icons/icon_graph_vec_scalar_op.png b/tools/editor/icons/icon_graph_vec_scalar_op.png Binary files differnew file mode 100644 index 0000000000..f0f4e7a196 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_scalar_op.png diff --git a/tools/editor/icons/icon_graph_vec_to_scalars.png b/tools/editor/icons/icon_graph_vec_to_scalars.png Binary files differnew file mode 100644 index 0000000000..a677a7cc53 --- /dev/null +++ b/tools/editor/icons/icon_graph_vec_to_scalars.png diff --git a/tools/editor/icons/icon_graph_vecs_to_xform.png b/tools/editor/icons/icon_graph_vecs_to_xform.png Binary files differnew file mode 100644 index 0000000000..51216c93eb --- /dev/null +++ b/tools/editor/icons/icon_graph_vecs_to_xform.png diff --git a/tools/editor/icons/icon_graph_vector.png b/tools/editor/icons/icon_graph_vector.png Binary files differnew file mode 100644 index 0000000000..9dfe47d757 --- /dev/null +++ b/tools/editor/icons/icon_graph_vector.png diff --git a/tools/editor/icons/icon_graph_vector_uniform.png b/tools/editor/icons/icon_graph_vector_uniform.png Binary files differnew file mode 100644 index 0000000000..611539fca7 --- /dev/null +++ b/tools/editor/icons/icon_graph_vector_uniform.png diff --git a/tools/editor/icons/icon_graph_xform.png b/tools/editor/icons/icon_graph_xform.png Binary files differnew file mode 100644 index 0000000000..22df472be4 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform.png diff --git a/tools/editor/icons/icon_graph_xform_mult.png b/tools/editor/icons/icon_graph_xform_mult.png Binary files differnew file mode 100644 index 0000000000..5d0ce7982d --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_mult.png diff --git a/tools/editor/icons/icon_graph_xform_scalar_func.png b/tools/editor/icons/icon_graph_xform_scalar_func.png Binary files differnew file mode 100644 index 0000000000..e53f08a564 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_scalar_func.png diff --git a/tools/editor/icons/icon_graph_xform_to_vecs.png b/tools/editor/icons/icon_graph_xform_to_vecs.png Binary files differnew file mode 100644 index 0000000000..847261f726 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_to_vecs.png diff --git a/tools/editor/icons/icon_graph_xform_uniform.png b/tools/editor/icons/icon_graph_xform_uniform.png Binary files differnew file mode 100644 index 0000000000..94c9759b25 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_uniform.png diff --git a/tools/editor/icons/icon_graph_xform_vec_func.png b/tools/editor/icons/icon_graph_xform_vec_func.png Binary files differnew file mode 100644 index 0000000000..f3ba528896 --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_vec_func.png diff --git a/tools/editor/icons/icon_graph_xform_vec_imult.png b/tools/editor/icons/icon_graph_xform_vec_imult.png Binary files differnew file mode 100644 index 0000000000..7e7330cb8c --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_vec_imult.png diff --git a/tools/editor/icons/icon_graph_xform_vec_mult.png b/tools/editor/icons/icon_graph_xform_vec_mult.png Binary files differnew file mode 100644 index 0000000000..f80a28c80d --- /dev/null +++ b/tools/editor/icons/icon_graph_xform_vec_mult.png diff --git a/tools/editor/icons/icon_group.png b/tools/editor/icons/icon_group.png Binary files differindex 577c84777e..d43b4958c9 100644 --- a/tools/editor/icons/icon_group.png +++ b/tools/editor/icons/icon_group.png diff --git a/tools/editor/icons/icon_groups.png b/tools/editor/icons/icon_groups.png Binary files differindex da4fd0d985..f4386821ed 100644 --- a/tools/editor/icons/icon_groups.png +++ b/tools/editor/icons/icon_groups.png diff --git a/tools/editor/icons/icon_hidden.png b/tools/editor/icons/icon_hidden.png Binary files differindex 45fcfc2f47..e51b9ad03a 100644 --- a/tools/editor/icons/icon_hidden.png +++ b/tools/editor/icons/icon_hidden.png diff --git a/tools/editor/icons/icon_image.png b/tools/editor/icons/icon_image.png Binary files differindex a6b1fbf6c1..5919ca8c6d 100644 --- a/tools/editor/icons/icon_image.png +++ b/tools/editor/icons/icon_image.png diff --git a/tools/editor/icons/icon_image_texture.png b/tools/editor/icons/icon_image_texture.png Binary files differindex 4618d984b8..b87e284a52 100644 --- a/tools/editor/icons/icon_image_texture.png +++ b/tools/editor/icons/icon_image_texture.png diff --git a/tools/editor/icons/icon_instance_options.png b/tools/editor/icons/icon_instance_options.png Binary files differindex 2d3e98b2ea..9108448095 100644 --- a/tools/editor/icons/icon_instance_options.png +++ b/tools/editor/icons/icon_instance_options.png diff --git a/tools/editor/icons/icon_integer.png b/tools/editor/icons/icon_integer.png Binary files differindex 0e5b5abd62..32c8d9885b 100644 --- a/tools/editor/icons/icon_integer.png +++ b/tools/editor/icons/icon_integer.png diff --git a/tools/editor/icons/icon_interp_cubic.png b/tools/editor/icons/icon_interp_cubic.png Binary files differindex ab33aa7e6a..a946d70947 100644 --- a/tools/editor/icons/icon_interp_cubic.png +++ b/tools/editor/icons/icon_interp_cubic.png diff --git a/tools/editor/icons/icon_interp_linear.png b/tools/editor/icons/icon_interp_linear.png Binary files differindex bf3849ecaf..9174af39e7 100644 --- a/tools/editor/icons/icon_interp_linear.png +++ b/tools/editor/icons/icon_interp_linear.png diff --git a/tools/editor/icons/icon_interp_raw.png b/tools/editor/icons/icon_interp_raw.png Binary files differindex 48650d6e66..f12936493b 100644 --- a/tools/editor/icons/icon_interp_raw.png +++ b/tools/editor/icons/icon_interp_raw.png diff --git a/tools/editor/icons/icon_key.png b/tools/editor/icons/icon_key.png Binary files differindex d647876866..d6096ef41f 100644 --- a/tools/editor/icons/icon_key.png +++ b/tools/editor/icons/icon_key.png diff --git a/tools/editor/icons/icon_key_selected.png b/tools/editor/icons/icon_key_selected.png Binary files differindex d916c55286..562beef98a 100644 --- a/tools/editor/icons/icon_key_selected.png +++ b/tools/editor/icons/icon_key_selected.png diff --git a/tools/editor/icons/icon_light_2d.png b/tools/editor/icons/icon_light_2d.png Binary files differnew file mode 100644 index 0000000000..9162b33090 --- /dev/null +++ b/tools/editor/icons/icon_light_2d.png diff --git a/tools/editor/icons/icon_light_map.png b/tools/editor/icons/icon_light_map.png Binary files differindex 96d3f6e11c..e0333f06ea 100644 --- a/tools/editor/icons/icon_light_map.png +++ b/tools/editor/icons/icon_light_map.png diff --git a/tools/editor/icons/icon_light_occluder_2d.png b/tools/editor/icons/icon_light_occluder_2d.png Binary files differnew file mode 100644 index 0000000000..c66dd536d3 --- /dev/null +++ b/tools/editor/icons/icon_light_occluder_2d.png diff --git a/tools/editor/icons/icon_load.png b/tools/editor/icons/icon_load.png Binary files differindex fdc06d38a3..a450a7b297 100644 --- a/tools/editor/icons/icon_load.png +++ b/tools/editor/icons/icon_load.png diff --git a/tools/editor/icons/icon_lock.png b/tools/editor/icons/icon_lock.png Binary files differindex 0cfd1d4ab1..995d87b6fb 100644 --- a/tools/editor/icons/icon_lock.png +++ b/tools/editor/icons/icon_lock.png diff --git a/tools/editor/icons/icon_loop.png b/tools/editor/icons/icon_loop.png Binary files differindex d75642359d..7bde451ca0 100644 --- a/tools/editor/icons/icon_loop.png +++ b/tools/editor/icons/icon_loop.png diff --git a/tools/editor/icons/icon_main_play.png b/tools/editor/icons/icon_main_play.png Binary files differindex 401708c49e..9e8cc6c4a9 100644 --- a/tools/editor/icons/icon_main_play.png +++ b/tools/editor/icons/icon_main_play.png diff --git a/tools/editor/icons/icon_main_stop.png b/tools/editor/icons/icon_main_stop.png Binary files differindex 3f54ba69c9..31a6cd601e 100644 --- a/tools/editor/icons/icon_main_stop.png +++ b/tools/editor/icons/icon_main_stop.png diff --git a/tools/editor/icons/icon_material_shader.png b/tools/editor/icons/icon_material_shader.png Binary files differnew file mode 100644 index 0000000000..0e476b2540 --- /dev/null +++ b/tools/editor/icons/icon_material_shader.png diff --git a/tools/editor/icons/icon_material_shader_graph.png b/tools/editor/icons/icon_material_shader_graph.png Binary files differnew file mode 100644 index 0000000000..68d8b4cb49 --- /dev/null +++ b/tools/editor/icons/icon_material_shader_graph.png diff --git a/tools/editor/icons/icon_mirror_x.png b/tools/editor/icons/icon_mirror_x.png Binary files differindex d20f90c1da..657e7f5458 100644 --- a/tools/editor/icons/icon_mirror_x.png +++ b/tools/editor/icons/icon_mirror_x.png diff --git a/tools/editor/icons/icon_mirror_y.png b/tools/editor/icons/icon_mirror_y.png Binary files differindex 5e2f710425..111aa5e4ae 100644 --- a/tools/editor/icons/icon_mirror_y.png +++ b/tools/editor/icons/icon_mirror_y.png diff --git a/tools/editor/icons/icon_move_down.png b/tools/editor/icons/icon_move_down.png Binary files differindex ef310e80e1..06c7246084 100644 --- a/tools/editor/icons/icon_move_down.png +++ b/tools/editor/icons/icon_move_down.png diff --git a/tools/editor/icons/icon_move_down_hl.png b/tools/editor/icons/icon_move_down_hl.png Binary files differindex dec56e8da8..f9de58a940 100644 --- a/tools/editor/icons/icon_move_down_hl.png +++ b/tools/editor/icons/icon_move_down_hl.png diff --git a/tools/editor/icons/icon_move_up.png b/tools/editor/icons/icon_move_up.png Binary files differindex d67b1aff0b..ca6c64f7a1 100644 --- a/tools/editor/icons/icon_move_up.png +++ b/tools/editor/icons/icon_move_up.png diff --git a/tools/editor/icons/icon_move_up_hl.png b/tools/editor/icons/icon_move_up_hl.png Binary files differindex 19ce8bbe27..e076c9a265 100644 --- a/tools/editor/icons/icon_move_up_hl.png +++ b/tools/editor/icons/icon_move_up_hl.png diff --git a/tools/editor/icons/icon_navigation_2d.png b/tools/editor/icons/icon_navigation_2d.png Binary files differnew file mode 100644 index 0000000000..8170ecf68c --- /dev/null +++ b/tools/editor/icons/icon_navigation_2d.png diff --git a/tools/editor/icons/icon_navigation_polygon_instance.png b/tools/editor/icons/icon_navigation_polygon_instance.png Binary files differnew file mode 100644 index 0000000000..9f9c318906 --- /dev/null +++ b/tools/editor/icons/icon_navigation_polygon_instance.png diff --git a/tools/editor/icons/icon_new.png b/tools/editor/icons/icon_new.png Binary files differindex 3596d2e8ea..c04785fc3f 100644 --- a/tools/editor/icons/icon_new.png +++ b/tools/editor/icons/icon_new.png diff --git a/tools/editor/icons/icon_node.png b/tools/editor/icons/icon_node.png Binary files differindex b0f7fb01dc..d8ce1b7538 100644 --- a/tools/editor/icons/icon_node.png +++ b/tools/editor/icons/icon_node.png diff --git a/tools/editor/icons/icon_occluder_polygon_2d.png b/tools/editor/icons/icon_occluder_polygon_2d.png Binary files differnew file mode 100644 index 0000000000..705794b729 --- /dev/null +++ b/tools/editor/icons/icon_occluder_polygon_2d.png diff --git a/tools/editor/icons/icon_open.png b/tools/editor/icons/icon_open.png Binary files differindex 4fad5677ca..a450a7b297 100644 --- a/tools/editor/icons/icon_open.png +++ b/tools/editor/icons/icon_open.png diff --git a/tools/editor/icons/icon_p_hash_translation.png b/tools/editor/icons/icon_p_hash_translation.png Binary files differindex c0eadc3c55..e18ef6a76f 100644 --- a/tools/editor/icons/icon_p_hash_translation.png +++ b/tools/editor/icons/icon_p_hash_translation.png diff --git a/tools/editor/icons/icon_packed_scene.png b/tools/editor/icons/icon_packed_scene.png Binary files differindex 9c1e1c4fbf..c9802f2b66 100644 --- a/tools/editor/icons/icon_packed_scene.png +++ b/tools/editor/icons/icon_packed_scene.png diff --git a/tools/editor/icons/icon_panels_1.png b/tools/editor/icons/icon_panels_1.png Binary files differindex 501c8c9acc..546ca61c89 100644 --- a/tools/editor/icons/icon_panels_1.png +++ b/tools/editor/icons/icon_panels_1.png diff --git a/tools/editor/icons/icon_panels_2.png b/tools/editor/icons/icon_panels_2.png Binary files differindex 08f104e2b1..5a4750bda2 100644 --- a/tools/editor/icons/icon_panels_2.png +++ b/tools/editor/icons/icon_panels_2.png diff --git a/tools/editor/icons/icon_panels_3.png b/tools/editor/icons/icon_panels_3.png Binary files differindex 1d1902d8dd..13988de93a 100644 --- a/tools/editor/icons/icon_panels_3.png +++ b/tools/editor/icons/icon_panels_3.png diff --git a/tools/editor/icons/icon_panels_4.png b/tools/editor/icons/icon_panels_4.png Binary files differindex 83cc133d21..c217330d43 100644 --- a/tools/editor/icons/icon_panels_4.png +++ b/tools/editor/icons/icon_panels_4.png diff --git a/tools/editor/icons/icon_pin.png b/tools/editor/icons/icon_pin.png Binary files differindex f34c8585f7..037352137d 100644 --- a/tools/editor/icons/icon_pin.png +++ b/tools/editor/icons/icon_pin.png diff --git a/tools/editor/icons/icon_pin_pressed.png b/tools/editor/icons/icon_pin_pressed.png Binary files differindex f151b5a590..5738e6856f 100644 --- a/tools/editor/icons/icon_pin_pressed.png +++ b/tools/editor/icons/icon_pin_pressed.png diff --git a/tools/editor/icons/icon_play.png b/tools/editor/icons/icon_play.png Binary files differindex 544b3bc5f4..08cce495a9 100644 --- a/tools/editor/icons/icon_play.png +++ b/tools/editor/icons/icon_play.png diff --git a/tools/editor/icons/icon_play_custom.png b/tools/editor/icons/icon_play_custom.png Binary files differindex 5c98c7100b..8e8ab8c62a 100644 --- a/tools/editor/icons/icon_play_custom.png +++ b/tools/editor/icons/icon_play_custom.png diff --git a/tools/editor/icons/icon_play_scene.png b/tools/editor/icons/icon_play_scene.png Binary files differindex 7ca59fe900..7079cc9677 100644 --- a/tools/editor/icons/icon_play_scene.png +++ b/tools/editor/icons/icon_play_scene.png diff --git a/tools/editor/icons/icon_prev_scene.png b/tools/editor/icons/icon_prev_scene.png Binary files differindex c7c180e1c4..9d8dda5180 100644 --- a/tools/editor/icons/icon_prev_scene.png +++ b/tools/editor/icons/icon_prev_scene.png diff --git a/tools/editor/icons/icon_real.png b/tools/editor/icons/icon_real.png Binary files differindex bfe5038319..80fbf7017c 100644 --- a/tools/editor/icons/icon_real.png +++ b/tools/editor/icons/icon_real.png diff --git a/tools/editor/icons/icon_reload.png b/tools/editor/icons/icon_reload.png Binary files differindex 07f53efb56..f7c6530d77 100644 --- a/tools/editor/icons/icon_reload.png +++ b/tools/editor/icons/icon_reload.png diff --git a/tools/editor/icons/icon_remove.png b/tools/editor/icons/icon_remove.png Binary files differindex 5349af466e..10e56d5bb8 100644 --- a/tools/editor/icons/icon_remove.png +++ b/tools/editor/icons/icon_remove.png diff --git a/tools/editor/icons/icon_rename.png b/tools/editor/icons/icon_rename.png Binary files differindex f88da39915..7b6a10df93 100644 --- a/tools/editor/icons/icon_rename.png +++ b/tools/editor/icons/icon_rename.png diff --git a/tools/editor/icons/icon_reparent.png b/tools/editor/icons/icon_reparent.png Binary files differindex af85b17ecc..59aee5e42d 100644 --- a/tools/editor/icons/icon_reparent.png +++ b/tools/editor/icons/icon_reparent.png diff --git a/tools/editor/icons/icon_replace.png b/tools/editor/icons/icon_replace.png Binary files differindex 2ae843ae10..662a58dc93 100644 --- a/tools/editor/icons/icon_replace.png +++ b/tools/editor/icons/icon_replace.png diff --git a/tools/editor/icons/icon_resource_preloader.png b/tools/editor/icons/icon_resource_preloader.png Binary files differindex e31e5a0d59..14b8c4de3c 100644 --- a/tools/editor/icons/icon_resource_preloader.png +++ b/tools/editor/icons/icon_resource_preloader.png diff --git a/tools/editor/icons/icon_rotate_0.png b/tools/editor/icons/icon_rotate_0.png Binary files differnew file mode 100644 index 0000000000..85a4b4c420 --- /dev/null +++ b/tools/editor/icons/icon_rotate_0.png diff --git a/tools/editor/icons/icon_rotate_180.png b/tools/editor/icons/icon_rotate_180.png Binary files differnew file mode 100644 index 0000000000..c4c516cff5 --- /dev/null +++ b/tools/editor/icons/icon_rotate_180.png diff --git a/tools/editor/icons/icon_rotate_270.png b/tools/editor/icons/icon_rotate_270.png Binary files differnew file mode 100644 index 0000000000..6e0f2e62b8 --- /dev/null +++ b/tools/editor/icons/icon_rotate_270.png diff --git a/tools/editor/icons/icon_rotate_90.png b/tools/editor/icons/icon_rotate_90.png Binary files differnew file mode 100644 index 0000000000..f25b0e99a3 --- /dev/null +++ b/tools/editor/icons/icon_rotate_90.png diff --git a/tools/editor/icons/icon_sample_player.png b/tools/editor/icons/icon_sample_player.png Binary files differindex 5561769b05..92d9cc77bf 100644 --- a/tools/editor/icons/icon_sample_player.png +++ b/tools/editor/icons/icon_sample_player.png diff --git a/tools/editor/icons/icon_save.png b/tools/editor/icons/icon_save.png Binary files differindex dce274ffb1..ddef66688d 100644 --- a/tools/editor/icons/icon_save.png +++ b/tools/editor/icons/icon_save.png diff --git a/tools/editor/icons/icon_script.png b/tools/editor/icons/icon_script.png Binary files differindex 65fb3c4934..baf5927c18 100644 --- a/tools/editor/icons/icon_script.png +++ b/tools/editor/icons/icon_script.png diff --git a/tools/editor/icons/icon_sound_room_params.png b/tools/editor/icons/icon_sound_room_params.png Binary files differindex 8e381d7978..2d37a4b49f 100644 --- a/tools/editor/icons/icon_sound_room_params.png +++ b/tools/editor/icons/icon_sound_room_params.png diff --git a/tools/editor/icons/icon_stop.png b/tools/editor/icons/icon_stop.png Binary files differindex 3b7562fa4a..fd568b61a8 100644 --- a/tools/editor/icons/icon_stop.png +++ b/tools/editor/icons/icon_stop.png diff --git a/tools/editor/icons/icon_stream_player.png b/tools/editor/icons/icon_stream_player.png Binary files differindex 2670a567e8..cf8fdcbaea 100644 --- a/tools/editor/icons/icon_stream_player.png +++ b/tools/editor/icons/icon_stream_player.png diff --git a/tools/editor/icons/icon_string.png b/tools/editor/icons/icon_string.png Binary files differindex 86cc8e633f..48bf753c40 100644 --- a/tools/editor/icons/icon_string.png +++ b/tools/editor/icons/icon_string.png diff --git a/tools/editor/icons/icon_texture.png b/tools/editor/icons/icon_texture.png Binary files differindex 03d6ac7db2..bbcc54bd6e 100644 --- a/tools/editor/icons/icon_texture.png +++ b/tools/editor/icons/icon_texture.png diff --git a/tools/editor/icons/icon_timer.png b/tools/editor/icons/icon_timer.png Binary files differindex 3855683033..e8c36ae893 100644 --- a/tools/editor/icons/icon_timer.png +++ b/tools/editor/icons/icon_timer.png diff --git a/tools/editor/icons/icon_tool_move.png b/tools/editor/icons/icon_tool_move.png Binary files differindex fc611cdbb1..7257d3897b 100644 --- a/tools/editor/icons/icon_tool_move.png +++ b/tools/editor/icons/icon_tool_move.png diff --git a/tools/editor/icons/icon_tool_pan.png b/tools/editor/icons/icon_tool_pan.png Binary files differindex 5c078a7b1c..bfe6fddf45 100644 --- a/tools/editor/icons/icon_tool_pan.png +++ b/tools/editor/icons/icon_tool_pan.png diff --git a/tools/editor/icons/icon_tool_rotate.png b/tools/editor/icons/icon_tool_rotate.png Binary files differindex c833b93d6e..9575ceb54e 100644 --- a/tools/editor/icons/icon_tool_rotate.png +++ b/tools/editor/icons/icon_tool_rotate.png diff --git a/tools/editor/icons/icon_tool_scale.png b/tools/editor/icons/icon_tool_scale.png Binary files differindex 3eaeae1e99..a94a6e7c98 100644 --- a/tools/editor/icons/icon_tool_scale.png +++ b/tools/editor/icons/icon_tool_scale.png diff --git a/tools/editor/icons/icon_tool_select.png b/tools/editor/icons/icon_tool_select.png Binary files differindex eb5ff6e1da..47683228e9 100644 --- a/tools/editor/icons/icon_tool_select.png +++ b/tools/editor/icons/icon_tool_select.png diff --git a/tools/editor/icons/icon_tools.png b/tools/editor/icons/icon_tools.png Binary files differindex 927173ea0f..f02d924203 100644 --- a/tools/editor/icons/icon_tools.png +++ b/tools/editor/icons/icon_tools.png diff --git a/tools/editor/icons/icon_track_continuous.png b/tools/editor/icons/icon_track_continuous.png Binary files differindex 97e8762299..9f99891c21 100644 --- a/tools/editor/icons/icon_track_continuous.png +++ b/tools/editor/icons/icon_track_continuous.png diff --git a/tools/editor/icons/icon_track_discrete.png b/tools/editor/icons/icon_track_discrete.png Binary files differindex 57a4cd5579..4e65e49afb 100644 --- a/tools/editor/icons/icon_track_discrete.png +++ b/tools/editor/icons/icon_track_discrete.png diff --git a/tools/editor/icons/icon_translation.png b/tools/editor/icons/icon_translation.png Binary files differindex 6211ab9a1b..917c6f548a 100644 --- a/tools/editor/icons/icon_translation.png +++ b/tools/editor/icons/icon_translation.png diff --git a/tools/editor/icons/icon_transpose.png b/tools/editor/icons/icon_transpose.png Binary files differnew file mode 100644 index 0000000000..f9b78bc0fd --- /dev/null +++ b/tools/editor/icons/icon_transpose.png diff --git a/tools/editor/icons/icon_unbone.png b/tools/editor/icons/icon_unbone.png Binary files differindex 819e8a8e5d..c8cd774460 100644 --- a/tools/editor/icons/icon_unbone.png +++ b/tools/editor/icons/icon_unbone.png diff --git a/tools/editor/icons/icon_ungroup.png b/tools/editor/icons/icon_ungroup.png Binary files differindex 16511e3f1c..4ea620bf96 100644 --- a/tools/editor/icons/icon_ungroup.png +++ b/tools/editor/icons/icon_ungroup.png diff --git a/tools/editor/icons/icon_unlock.png b/tools/editor/icons/icon_unlock.png Binary files differindex b86447bf7a..f9fa31c3e0 100644 --- a/tools/editor/icons/icon_unlock.png +++ b/tools/editor/icons/icon_unlock.png diff --git a/tools/editor/icons/icon_uv.png b/tools/editor/icons/icon_uv.png Binary files differindex 4d9d198d86..39bc737a37 100644 --- a/tools/editor/icons/icon_uv.png +++ b/tools/editor/icons/icon_uv.png diff --git a/tools/editor/icons/icon_vector.png b/tools/editor/icons/icon_vector.png Binary files differindex 7826d7f7a9..0ee33ba0b7 100644 --- a/tools/editor/icons/icon_vector.png +++ b/tools/editor/icons/icon_vector.png diff --git a/tools/editor/icons/icon_vector2.png b/tools/editor/icons/icon_vector2.png Binary files differindex 44e48c36c7..5920109a55 100644 --- a/tools/editor/icons/icon_vector2.png +++ b/tools/editor/icons/icon_vector2.png diff --git a/tools/editor/icons/icon_viewport.png b/tools/editor/icons/icon_viewport.png Binary files differindex 0a0d93cf4d..3859f6c7e9 100644 --- a/tools/editor/icons/icon_viewport.png +++ b/tools/editor/icons/icon_viewport.png diff --git a/tools/editor/icons/icon_visible.png b/tools/editor/icons/icon_visible.png Binary files differindex 519898bbef..cbc44c4e30 100644 --- a/tools/editor/icons/icon_visible.png +++ b/tools/editor/icons/icon_visible.png diff --git a/tools/editor/icons/icon_zoom.png b/tools/editor/icons/icon_zoom.png Binary files differindex cbacaaaeca..e4bbbfe7c3 100644 --- a/tools/editor/icons/icon_zoom.png +++ b/tools/editor/icons/icon_zoom.png diff --git a/tools/editor/import_settings.cpp b/tools/editor/import_settings.cpp index 74e4aa97d7..63b8d65b69 100644 --- a/tools/editor/import_settings.cpp +++ b/tools/editor/import_settings.cpp @@ -224,7 +224,7 @@ void ImportSettingsDialog::update_tree() { void ImportSettingsDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"update_tree"); } diff --git a/tools/editor/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp index 6a6ee8c614..0562153199 100644 --- a/tools/editor/io_plugins/editor_font_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -47,6 +47,12 @@ class _EditorFontImportOptions : public Object { OBJ_TYPE(_EditorFontImportOptions,Object); public: + enum FontMode { + + FONT_BITMAP, + FONT_DISTANCE_FIELD + }; + enum ColorType { COLOR_WHITE, COLOR_CUSTOM, @@ -69,6 +75,9 @@ public: CHARSET_CUSTOM_LATIN }; + + FontMode font_mode; + CharacterSet character_set; String custom_file; @@ -91,7 +100,6 @@ public: bool color_use_monochrome; String gradient_image; - bool disable_filter; bool round_advance; @@ -100,7 +108,10 @@ public: bool _set(const StringName& p_name, const Variant& p_value) { String n = p_name; - if (n=="extra_space/char") + if (n=="mode/mode") { + font_mode=FontMode(int(p_value)); + _change_notify(); + } else if (n=="extra_space/char") char_extra_spacing=p_value; else if (n=="extra_space/space") space_extra_spacing=p_value; @@ -169,7 +180,9 @@ public: bool _get(const StringName& p_name,Variant &r_ret) const{ String n = p_name; - if (n=="extra_space/char") + if (n=="mode/mode") + r_ret=font_mode; + else if (n=="extra_space/char") r_ret=char_extra_spacing; else if (n=="extra_space/space") r_ret=space_extra_spacing; @@ -231,6 +244,9 @@ public: void _get_property_list( List<PropertyInfo> *p_list) const{ + + p_list->push_back(PropertyInfo(Variant::INT,"mode/mode",PROPERTY_HINT_ENUM,"Bitmap,Distance Field")); + p_list->push_back(PropertyInfo(Variant::INT,"extra_space/char",PROPERTY_HINT_RANGE,"-64,64,1")); p_list->push_back(PropertyInfo(Variant::INT,"extra_space/space",PROPERTY_HINT_RANGE,"-64,64,1")); p_list->push_back(PropertyInfo(Variant::INT,"extra_space/top",PROPERTY_HINT_RANGE,"-64,64,1")); @@ -240,35 +256,45 @@ public: if (character_set>=CHARSET_CUSTOM) p_list->push_back(PropertyInfo(Variant::STRING,"character_set/custom",PROPERTY_HINT_FILE)); - p_list->push_back(PropertyInfo(Variant::BOOL,"shadow/enabled")); - if (shadow) { - p_list->push_back(PropertyInfo(Variant::INT,"shadow/radius",PROPERTY_HINT_RANGE,"-64,64,1")); - p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow/offset")); - p_list->push_back(PropertyInfo(Variant::COLOR,"shadow/color")); - p_list->push_back(PropertyInfo(Variant::REAL,"shadow/transition",PROPERTY_HINT_EXP_EASING)); - } + int usage = PROPERTY_USAGE_DEFAULT; - p_list->push_back(PropertyInfo(Variant::BOOL,"shadow2/enabled")); - if (shadow2) { - p_list->push_back(PropertyInfo(Variant::INT,"shadow2/radius",PROPERTY_HINT_RANGE,"-64,64,1")); - p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow2/offset")); - p_list->push_back(PropertyInfo(Variant::COLOR,"shadow2/color")); - p_list->push_back(PropertyInfo(Variant::REAL,"shadow2/transition",PROPERTY_HINT_EXP_EASING)); + if (font_mode==FONT_DISTANCE_FIELD) { + usage = PROPERTY_USAGE_NOEDITOR; } - p_list->push_back(PropertyInfo(Variant::INT,"color/mode",PROPERTY_HINT_ENUM,"White,Color,Gradient,Gradient Image")); - if (color_type==COLOR_CUSTOM) { - p_list->push_back(PropertyInfo(Variant::COLOR,"color/color")); + { + p_list->push_back(PropertyInfo(Variant::BOOL,"shadow/enabled",PROPERTY_HINT_NONE,"",usage)); + if (shadow) { + p_list->push_back(PropertyInfo(Variant::INT,"shadow/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage)); + p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow/offset",PROPERTY_HINT_NONE,"",usage)); + p_list->push_back(PropertyInfo(Variant::COLOR,"shadow/color",PROPERTY_HINT_NONE,"",usage)); + p_list->push_back(PropertyInfo(Variant::REAL,"shadow/transition",PROPERTY_HINT_EXP_EASING,"",usage)); + } + + p_list->push_back(PropertyInfo(Variant::BOOL,"shadow2/enabled",PROPERTY_HINT_NONE,"",usage)); + if (shadow2) { + p_list->push_back(PropertyInfo(Variant::INT,"shadow2/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage)); + p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow2/offset",PROPERTY_HINT_NONE,"",usage)); + p_list->push_back(PropertyInfo(Variant::COLOR,"shadow2/color",PROPERTY_HINT_NONE,"",usage)); + p_list->push_back(PropertyInfo(Variant::REAL,"shadow2/transition",PROPERTY_HINT_EXP_EASING,"",usage)); + } + + p_list->push_back(PropertyInfo(Variant::INT,"color/mode",PROPERTY_HINT_ENUM,"White,Color,Gradient,Gradient Image",usage)); + if (color_type==COLOR_CUSTOM) { + p_list->push_back(PropertyInfo(Variant::COLOR,"color/color",PROPERTY_HINT_NONE,"",usage)); + + } + if (color_type==COLOR_GRADIENT_RANGE) { + p_list->push_back(PropertyInfo(Variant::COLOR,"color/begin",PROPERTY_HINT_NONE,"",usage)); + p_list->push_back(PropertyInfo(Variant::COLOR,"color/end",PROPERTY_HINT_NONE,"",usage)); + } + if (color_type==COLOR_GRADIENT_IMAGE) { + p_list->push_back(PropertyInfo(Variant::STRING,"color/image",PROPERTY_HINT_FILE,"",usage)); + } + p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome",PROPERTY_HINT_NONE,"",usage)); } - if (color_type==COLOR_GRADIENT_RANGE) { - p_list->push_back(PropertyInfo(Variant::COLOR,"color/begin")); - p_list->push_back(PropertyInfo(Variant::COLOR,"color/end")); - } - if (color_type==COLOR_GRADIENT_IMAGE) { - p_list->push_back(PropertyInfo(Variant::STRING,"color/image",PROPERTY_HINT_FILE)); - } - p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome")); + p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/round_advance")); p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/disable_filter")); @@ -307,6 +333,7 @@ public: gradient_end=Color(0.5,0.5,0.5,1); color_use_monochrome=false; + font_mode=FONT_BITMAP; round_advance=true; disable_filter=false; @@ -314,6 +341,8 @@ public: _EditorFontImportOptions() { + font_mode=FONT_BITMAP; + char_extra_spacing=0; top_extra_spacing=0; bottom_extra_spacing=0; @@ -499,7 +528,7 @@ class EditorFontImportDialog : public ConfirmationDialog { Error err = plugin->import(dest->get_line_edit()->get_text(),rimd); if (err!=OK) { - error_dialog->set_text("Could't save font."); + error_dialog->set_text("Couldn't save font."); error_dialog->popup_centered(Size2(200,100)); return; } @@ -529,7 +558,7 @@ public: void _notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { prop_edit->edit(options); _update_text(); } @@ -706,6 +735,137 @@ struct _EditorKerningKey { }; + +static unsigned char get_SDF_radial( + unsigned char *fontmap, + int w, int h, + int x, int y, + int max_radius ) +{ + // hideous brute force method + float d2 = max_radius*max_radius+1.0; + unsigned char v = fontmap[x+y*w]; + for( int radius = 1; (radius <= max_radius) && (radius*radius < d2); ++radius ) + { + int line, lo, hi; + // north + line = y - radius; + if( (line >= 0) && (line < h) ) + { + lo = x - radius; + hi = x + radius; + if( lo < 0 ) { lo = 0; } + if( hi >= w ) { hi = w-1; } + int idx = line * w + lo; + for( int i = lo; i <= hi; ++i ) + { + // check this pixel + if( fontmap[idx] != v ) + { + float nx = i - x; + float ny = line - y; + float nd2 = nx*nx+ny*ny; + if( nd2 < d2 ) + { + d2 = nd2; + } + } + // move on + ++idx; + } + } + // south + line = y + radius; + if( (line >= 0) && (line < h) ) + { + lo = x - radius; + hi = x + radius; + if( lo < 0 ) { lo = 0; } + if( hi >= w ) { hi = w-1; } + int idx = line * w + lo; + for( int i = lo; i <= hi; ++i ) + { + // check this pixel + if( fontmap[idx] != v ) + { + float nx = i - x; + float ny = line - y; + float nd2 = nx*nx+ny*ny; + if( nd2 < d2 ) + { + d2 = nd2; + } + } + // move on + ++idx; + } + } + // west + line = x - radius; + if( (line >= 0) && (line < w) ) + { + lo = y - radius + 1; + hi = y + radius - 1; + if( lo < 0 ) { lo = 0; } + if( hi >= h ) { hi = h-1; } + int idx = lo * w + line; + for( int i = lo; i <= hi; ++i ) + { + // check this pixel + if( fontmap[idx] != v ) + { + float nx = line - x; + float ny = i - y; + float nd2 = nx*nx+ny*ny; + if( nd2 < d2 ) + { + d2 = nd2; + } + } + // move on + idx += w; + } + } + // east + line = x + radius; + if( (line >= 0) && (line < w) ) + { + lo = y - radius + 1; + hi = y + radius - 1; + if( lo < 0 ) { lo = 0; } + if( hi >= h ) { hi = h-1; } + int idx = lo * w + line; + for( int i = lo; i <= hi; ++i ) + { + // check this pixel + if( fontmap[idx] != v ) + { + float nx = line - x; + float ny = i - y; + float nd2 = nx*nx+ny*ny; + if( nd2 < d2 ) + { + d2 = nd2; + } + } + // move on + idx += w; + } + } + } + d2 = sqrtf( d2 ); + if( v==0 ) + { + d2 = -d2; + } + d2 *= 127.5 / max_radius; + d2 += 127.5; + if( d2 < 0.0 ) d2 = 0.0; + if( d2 > 255.0 ) d2 = 255.0; + return (unsigned char)(d2 + 0.5); +} + + Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata>& p_from, const String &p_existing) { Ref<ResourceImportMetadata> from = p_from; @@ -754,7 +914,11 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata } - error = FT_Set_Pixel_Sizes(face,0,size); + int font_mode = from->get_option("mode/mode"); + + int scaler=(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD)?16:1; + + error = FT_Set_Pixel_Sizes(face,0,size*scaler); FT_GlyphSlot slot = face->glyph; @@ -820,9 +984,9 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata { bool skip=false; - error = FT_Load_Char( face, charcode, FT_LOAD_RENDER ); + error = FT_Load_Char( face, charcode, font_mode==_EditorFontImportOptions::FONT_BITMAP?FT_LOAD_RENDER:FT_LOAD_MONOCHROME ); if (error) skip=true; - else error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); + else error = FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono ); if (error) { skip=true; } else if (!skip) { @@ -847,28 +1011,36 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata } _EditorFontData * fdata = memnew( _EditorFontData ); - fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows ); - fdata->width=slot->bitmap.width; - fdata->height=slot->bitmap.rows; - fdata->character=charcode; - fdata->glyph=FT_Get_Char_Index(face,charcode); - if (charcode=='x') - xsize=slot->bitmap.width; - if (charcode<127) { - if (slot->bitmap_top>max_up) { + int w = slot->bitmap.width; + int h = slot->bitmap.rows; + int p = slot->bitmap.pitch; - max_up=slot->bitmap_top; - } + print_line("W: "+itos(w)+" P: "+itos(slot->bitmap.pitch)); + if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) { - if ( (slot->bitmap_top - fdata->height)<max_down ) { + // oversize the holding buffer so I can smooth it! + int sw = w + scaler * 4; + int sh = h + scaler * 4; + // do the SDF + int sdfw = sw / scaler; + int sdfh = sh / scaler; - max_down=slot->bitmap_top - fdata->height; - } + fdata->width=sdfw; + fdata->height=sdfh; + } else { + fdata->width=w; + fdata->height=h; } + fdata->character=charcode; + fdata->glyph=FT_Get_Char_Index(face,charcode); + if (charcode=='x') + xsize=w/scaler; + + fdata->valign=slot->bitmap_top; fdata->halign=slot->bitmap_left; @@ -878,12 +1050,85 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata else fdata->advance=slot->advance.x/float(1<<6); + if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) { + + fdata->halign = fdata->halign / scaler - 1.5; + fdata->valign = fdata->valign / scaler + 1.5; + fdata->advance/=scaler; + + } + fdata->advance+=font_spacing; - for (int i=0;i<slot->bitmap.width;i++) { - for (int j=0;j<slot->bitmap.rows;j++) { - fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i]; + if (charcode<127) { + int top = fdata->valign; + int hmax = h/scaler; + + if (top>max_up) { + + max_up=top; + } + + + if ( (top - hmax)<max_down ) { + + max_down=top - hmax; + } + } + + if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) { + + + // oversize the holding buffer so I can smooth it! + int sw = w + scaler * 4; + int sh = h + scaler * 4; + + unsigned char *smooth_buf = new unsigned char[sw*sh]; + + for( int i = 0; i < sw*sh; ++i ) { + smooth_buf[i] = 0; + } + + // copy the glyph into the buffer to be smoothed + unsigned char *buf = slot->bitmap.buffer; + for( int j = 0; j < h; ++j ) { + for( int i = 0; i < w; ++i ) { + smooth_buf[scaler*2+i+(j+scaler*2)*sw] = 255 * ((buf[j*p+(i>>3)] >> (7 - (i & 7))) & 1); + } + } + + // do the SDF + int sdfw = fdata->width; + int sdfh = fdata->height; + + fdata->bitmap.resize( sdfw*sdfh ); + + for( int j = 0; j < sdfh; ++j ) { + for( int i = 0; i < sdfw; ++i ) { + int pd_idx = j*sdfw+i; + + //fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i]; + + fdata->bitmap[pd_idx] = + //get_SDF + get_SDF_radial + ( smooth_buf, sw, sh, + i*scaler + (scaler >>1), j*scaler + (scaler >>1), + 2*scaler ); + + } + } + + delete [] smooth_buf; + + } else { + fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows ); + for (int i=0;i<slot->bitmap.width;i++) { + for (int j=0;j<slot->bitmap.rows;j++) { + + fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i]; + } } } @@ -904,9 +1149,10 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata spd->ofs_x=0; spd->ofs_y=0; - if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, ft_render_mode_normal )) { + if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono )) { spd->advance = slot->advance.x>>6; //round to nearest or store as float + spd->advance/=scaler; spd->advance+=font_spacing; } else { @@ -955,7 +1201,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata if (kern==0) continue; - kerning_map[kpk]=kern; + kerning_map[kpk]=kern/scaler; } } } @@ -1079,7 +1325,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata pixels.resize(s.x*s.y*4); DVector<uint8_t>::Write w = pixels.write(); - print_line("val: "+itos(font_data_list[i]->valign)); + //print_line("val: "+itos(font_data_list[i]->valign)); for(int y=0;y<s.height;y++) { int yc=CLAMP(y-o.y+font_data_list[i]->valign,0,height-1); @@ -1284,6 +1530,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata font->clear(); font->set_height(height+bottom_space+top_space); font->set_ascent(ascent+top_space); + font->set_distance_field_hint(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD); //register texures { diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp index e86356ebe9..990e52be46 100644 --- a/tools/editor/io_plugins/editor_import_collada.cpp +++ b/tools/editor/io_plugins/editor_import_collada.cpp @@ -39,6 +39,7 @@ #include "scene/resources/packed_scene.h" #include "os/os.h" #include "tools/editor/editor_node.h" +#include <iostream> struct ColladaImport { @@ -61,6 +62,8 @@ struct ColladaImport { Color ambient; bool found_directional; bool force_make_tangents; + bool apply_mesh_xform_to_vertices; + float bake_fps; @@ -68,6 +71,7 @@ struct ColladaImport { Map<String, Ref<Mesh> > mesh_cache; Map<String, Ref<Curve3D> > curve_cache; Map<String, Ref<Material> > material_cache; + Map<Collada::Node*,Skeleton*> skeleton_map; Map< Skeleton*, Map< String, int> > skeleton_bone_map; @@ -76,6 +80,7 @@ struct ColladaImport { Map<String,bool> bones_with_animation; Error _populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_node, int &r_bone, int p_parent); + Error _create_scene_skeletons(Collada::Node *p_node); Error _create_scene(Collada::Node *p_node, Spatial *p_parent); Error _create_resources(Collada::Node *p_node); Error _create_material(const String& p_material); @@ -95,6 +100,8 @@ struct ColladaImport { found_ambient=false; found_directional=false; force_make_tangents=false; + apply_mesh_xform_to_vertices=true; + bake_fps=15; } }; @@ -108,7 +115,7 @@ Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_no Collada::NodeJoint *joint = static_cast<Collada::NodeJoint*>(p_node); - + print_line("populating joint "+joint->name); p_skeleton->add_bone(p_node->name); if (p_parent>=0) p_skeleton->set_bone_parent(r_bone,p_parent); @@ -168,6 +175,34 @@ void ColladaImport::_pre_process_lights(Collada::Node *p_node) { _pre_process_lights(p_node->children[i]); } +Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) { + + + if (p_node->type==Collada::Node::TYPE_SKELETON) { + + Skeleton *sk = memnew( Skeleton ); + int bone = 0; + + for(int i=0;i<p_node->children.size();i++) { + + _populate_skeleton(sk,p_node->children[i],bone,-1); + } + sk->localize_rests(); //after creating skeleton, rests must be localized...! + skeleton_map[p_node]=sk; + } + + + for(int i=0;i<p_node->children.size();i++) { + + Error err = _create_scene_skeletons(p_node->children[i]); + if (err) + return err; + } + return OK; + +} + + Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { Spatial * node=NULL; @@ -251,13 +286,16 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { case Collada::CameraData::MODE_ORTHOGONAL: { - if (cd.orthogonal.x_mag) { + if (cd.orthogonal.y_mag) { - camera->set_orthogonal(cd.orthogonal.x_mag,cd.z_near,cd.z_far); + camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT); + camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far); - } else if (!cd.orthogonal.x_mag && cd.orthogonal.y_mag) { + } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) { - camera->set_orthogonal(cd.orthogonal.y_mag * cd.aspect,cd.z_near,cd.z_far); + + camera->set_keep_aspect_mode(Camera::KEEP_WIDTH); + camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far); } } break; @@ -295,15 +333,8 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } break; case Collada::Node::TYPE_SKELETON: { - Skeleton *sk = memnew( Skeleton ); - int bone = 0; - - for(int i=0;i<p_node->children.size();i++) { - - _populate_skeleton(sk,p_node->children[i],bone,-1); - } - sk->localize_rests(); //after creating skeleton, rests must be localized...! - + ERR_FAIL_COND_V(!skeleton_map.has(p_node),ERR_CANT_CREATE); + Skeleton *sk = skeleton_map[p_node]; node=sk; } break; @@ -1327,8 +1358,60 @@ Error ColladaImport::_create_mesh_surfaces(Ref<Mesh>& p_mesh,const Map<String,Co vertw = DVector<Vector3>::Write(); DVector<Vector3> normals; DVector<float> tangents; + if(md.vertices[vertex_src_id].sources.has("NORMAL")){ + //has normals + normals.resize(vlen); + //std::cout << "has normals" << std::endl; + String normal_src_id = md.vertices[vertex_src_id].sources["NORMAL"]; + //std::cout << "normals source: "<< normal_src_id.utf8().get_data() <<std::endl; + ERR_FAIL_COND_V(!md.sources.has(normal_src_id),ERR_INVALID_DATA); + + const Collada::MeshData::Source *m=&md.sources[normal_src_id]; + + ERR_FAIL_COND_V( m->array.size() != vertex_src->array.size(), ERR_INVALID_DATA); + int stride=m->stride; + if (stride==0) + stride=3; + + + //read normals from morph target + DVector<Vector3>::Write vertw = normals.write(); + + for(int m_i=0;m_i<m->array.size()/stride;m_i++) { + + int pos = m_i*stride; + Vector3 vtx( m->array[pos+0], m->array[pos+1], m->array[pos+2] ); + + #ifndef NO_UP_AXIS_SWAP + if (collada.state.up_axis==Vector3::AXIS_Z) { - _generate_normals(index_array,vertices,normals); + SWAP( vtx.z, vtx.y ); + vtx.z = -vtx.z; + + } + #endif + + Collada::Vertex vertex; + vertex.vertex=vtx; + vertex.fix_unit_scale(collada); + vtx=vertex.vertex; + + vtx = p_local_xform.xform(vtx); + + + if (vertex_map.has(m_i)) { //vertex may no longer be here, don't bother converting + + + for (Set<int> ::Element *E=vertex_map[m_i].front() ; E; E=E->next() ) { + + vertw[E->get()]=vtx; + } + } + } + + }else{ + _generate_normals(index_array,vertices,normals);//no normals + } if (final_tangent_array.size() && final_uv_array.size()) { _generate_tangents_and_binormals(index_array,vertices,final_uv_array,normals,tangents); @@ -1500,6 +1583,9 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { ERR_FAIL_COND_V( skeletons.empty(), ERR_INVALID_DATA ); String skname = skeletons[0]; + if (!node_map.has(skname)) { + print_line("no node for skeleton "+skname); + } ERR_FAIL_COND_V( !node_map.has(skname), ERR_INVALID_DATA ); NodeMap nmsk = node_map[skname]; Skeleton *sk = nmsk.node->cast_to<Skeleton>(); @@ -1516,8 +1602,12 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { meshid=morph->mesh; } - apply_xform=collada.fix_transform(p_node->default_transform); - node->set_transform(Transform()); + if (apply_mesh_xform_to_vertices) { + apply_xform=collada.fix_transform(p_node->default_transform); + node->set_transform(Transform()); + } else { + apply_xform=Transform(); + } Collada::SkinControllerData::Source *joint_src=NULL; @@ -1613,6 +1703,16 @@ Error ColladaImport::load(const String& p_path,int p_flags,bool p_force_make_tan } //import scene + + for(int i=0;i<vs.root_nodes.size();i++) { + + Error err = _create_scene_skeletons(vs.root_nodes[i]); + if (err!=OK) { + memdelete(scene); + ERR_FAIL_COND_V(err,err); + } + } + for(int i=0;i<vs.root_nodes.size();i++) { Error err = _create_scene(vs.root_nodes[i],scene); @@ -1835,19 +1935,22 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones Vector<float> base_snapshots; float f=0; - float snapshot_interval = 1.0/20.0; //should be customizable somewhere... + float snapshot_interval = 1.0/bake_fps; //should be customizable somewhere... float anim_length=collada.state.animation_length; if (p_clip>=0 && collada.state.animation_clips[p_clip].end) anim_length=collada.state.animation_clips[p_clip].end; while(f<anim_length) { - if (f>=anim_length) - f=anim_length; base_snapshots.push_back(f); f+=snapshot_interval; + + if (f>=anim_length) { + base_snapshots.push_back(anim_length); + } } + //print_line("anim len: "+rtos(anim_length)); animation->set_length(anim_length); @@ -1892,6 +1995,8 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones for(int i=0;i<at.keys.size();i++) snapshots.push_back(at.keys[i].time); + print_line("using anim snapshots"); + } @@ -2142,14 +2247,14 @@ void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) cons r_extensions->push_back("dae"); } -Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_flags, List<String> *r_missing_deps, Error* r_err) { - +Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_flags,int p_bake_fps, List<String> *r_missing_deps, Error* r_err) { ColladaImport state; uint32_t flags=Collada::IMPORT_FLAG_SCENE; if (p_flags&IMPORT_ANIMATION) flags|=Collada::IMPORT_FLAG_ANIMATION; + state.bake_fps=p_bake_fps; Error err = state.load(p_path,flags,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS); @@ -2174,7 +2279,7 @@ Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_ if (p_flags&IMPORT_ANIMATION) { - state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES); + state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS); AnimationPlayer *ap = memnew( AnimationPlayer ); for(int i=0;i<state.animations.size();i++) { String name; @@ -2183,8 +2288,6 @@ Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_ else name=state.animations[i]->get_name(); - if (p_flags&IMPORT_ANIMATION_OPTIMIZE) - state.animations[i]->optimize(); if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) { if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { @@ -2213,7 +2316,7 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String& p_path ERR_FAIL_COND_V(err!=OK,RES()); - state.create_animations(p_flags&EditorSceneImporter::IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES); + state.create_animations(p_flags&EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS); if (state.scene) memdelete(state.scene); @@ -2230,8 +2333,6 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String& p_path } } - if (p_flags&IMPORT_ANIMATION_OPTIMIZE) - anim->optimize(); return anim; } diff --git a/tools/editor/io_plugins/editor_import_collada.h b/tools/editor/io_plugins/editor_import_collada.h index 9580f42ed0..ae4cedeff6 100644 --- a/tools/editor/io_plugins/editor_import_collada.h +++ b/tools/editor/io_plugins/editor_import_collada.h @@ -40,7 +40,7 @@ public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node* import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps=NULL,Error* r_err=NULL); + virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps=NULL,Error* r_err=NULL); virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags); EditorSceneImporterCollada(); diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp index d76a778433..7d6f400ccc 100644 --- a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -245,7 +245,7 @@ public: void _notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { option_editor->edit(options); } @@ -425,7 +425,7 @@ Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImp ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA); Vector2 uv; uv.x=v[1].to_float(); - uv.y=v[2].to_float(); + uv.y=1.0-v[2].to_float(); uvs.push_back(uv); } else if (l.begins_with("vn ")) { diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index cd02156eef..377af8f179 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -290,7 +290,7 @@ public: void _notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { option_editor->edit(options); } diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp index 27400344d3..06780e4d8a 100644 --- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp @@ -78,12 +78,31 @@ class EditorImportAnimationOptions : public VBoxContainer { OBJ_TYPE( EditorImportAnimationOptions, VBoxContainer ); + + TreeItem *fps; + TreeItem* optimize_linear_error; + TreeItem* optimize_angular_error; + TreeItem* optimize_max_angle; + + TreeItem *clips_base; + + TextEdit *filters; + Vector<TreeItem*> clips; + Tree *flags; + Tree *clips_tree; + Tree *optimization_tree; Vector<TreeItem*> items; bool updating; + bool validating; + + void _changed(); + void _item_edited(); + void _button_action(Object *p_obj,int p_col,int p_id); + protected: static void _bind_methods(); void _notification(int p_what); @@ -93,6 +112,23 @@ public: void set_flags(uint32_t p_flags); uint32_t get_flags() const; + void set_fps(int p_fps); + int get_fps() const; + + void set_optimize_linear_error(float p_error); + float get_optimize_linear_error() const; + + void set_optimize_angular_error(float p_error); + float get_optimize_angular_error() const; + + void set_optimize_max_angle(float p_error); + float get_optimize_max_angle() const; + + void setup_clips(const Array& p_clips); + Array get_clips() const; + + void set_filter(const String& p_filter); + String get_filter() const; EditorImportAnimationOptions(); @@ -141,6 +177,9 @@ class EditorSceneImportDialog : public ConfirmationDialog { Map<Ref<Mesh>,Ref<Shape> > collision_map; ConfirmationDialog *error_dialog; + OptionButton *this_import; + OptionButton *next_import; + void _choose_file(const String& p_path); void _choose_save_file(const String& p_path); void _choose_script(const String& p_path); @@ -178,7 +217,7 @@ static const char *anim_flag_names[]={ "Detect Loop (-loop,-cycle)", "Keep Value Tracks", "Optimize", - "Force Tracks in All Bones", + "Force All Tracks in All Clips", NULL }; @@ -223,9 +262,101 @@ void EditorImportAnimationOptions::_changed() { } +void EditorImportAnimationOptions::_button_action(Object *p_obj,int p_col,int p_id) { + + memdelete(p_obj); + +} + + +void EditorImportAnimationOptions::_item_edited() { + + if (validating) + return; + + if (clips.size()==0) + return; + validating=true; + print_line("edited"); + TreeItem *item = clips_tree->get_edited(); + if (item==clips[clips.size()-1]) { + //add new + print_line("islast"); + if (item->get_text(0).find("<")!=-1 || item->get_text(0).find(">")!=-1) { + validating=false; + return; //fuckit + } + + item->set_editable(1,true); + item->set_editable(2,true); + item->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons")); + item->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); + item->set_range_config(1,0,3600,0.01); + item->set_range(1,0); + item->set_editable(1,true); + item->set_cell_mode(2,TreeItem::CELL_MODE_RANGE); + item->set_range_config(2,0,3600,0.01); + item->set_range(2,0); + item->set_cell_mode(3,TreeItem::CELL_MODE_CHECK); + item->set_editable(3,true); + + TreeItem *newclip = clips_tree->create_item(clips_base); + newclip->set_text(0,"<new clip>"); + newclip->set_editable(0,true); + newclip->set_editable(1,false); + newclip->set_editable(2,false); + clips.push_back(newclip); + + + + } + + + //make name unique JUST IN CASE + String name = item->get_text(0); + name=name.replace("/","_").replace(":","_").strip_edges(); + if (name=="") + name="New Clip"; + + if (clips.size()>2) { + int index=1; + while(true) { + bool valid = true; + String try_name=name; + if (index>1) + try_name+=" "+itos(index); + + for(int i=0;i<clips.size()-1;i++) { + + if (clips[i]==item) + continue; + if (clips[i]->get_text(0)==try_name) { + index++; + valid=false; + break; + } + } + + if (valid) { + name=try_name; + break; + } + + } + } + + if (item->get_text(0)!=name) + item->set_text(0,name); + + validating=false; + +} + void EditorImportAnimationOptions::_bind_methods() { ObjectTypeDB::bind_method("_changed",&EditorImportAnimationOptions::_changed); + ObjectTypeDB::bind_method("_item_edited",&EditorImportAnimationOptions::_item_edited); + ObjectTypeDB::bind_method("_button_action",&EditorImportAnimationOptions::_button_action); // ObjectTypeDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp); ADD_SIGNAL(MethodInfo("changed")); @@ -234,20 +365,87 @@ void EditorImportAnimationOptions::_bind_methods() { void EditorImportAnimationOptions::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { flags->connect("item_edited",this,"_changed"); + clips_tree->connect("item_edited",this,"_item_edited"); + clips_tree->connect("button_pressed",this,"_button_action",varray(),CONNECT_DEFERRED); // format->connect("item_selected",this,"_changedp"); } } + +Array EditorImportAnimationOptions::get_clips() const { + + Array arr; + for(int i=0;i<clips.size()-1;i++) { + + arr.push_back(clips[i]->get_text(0)); + arr.push_back(clips[i]->get_range(1)); + arr.push_back(clips[i]->get_range(2)); + arr.push_back(clips[i]->is_checked(3)); + } + + return arr; +} + + +void EditorImportAnimationOptions::setup_clips(const Array& p_clips) { + + ERR_FAIL_COND(p_clips.size()%4!=0); + for(int i=0;i<clips.size();i++) { + + memdelete(clips[i]); + } + + + clips.clear(); + + for(int i=0;i<p_clips.size();i+=4) { + + TreeItem *clip = clips_tree->create_item(clips_base); + clip->set_text(0,p_clips[i]); + clip->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons")); + clip->set_editable(0,true); + clip->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); + clip->set_range_config(1,0,3600,0.01); + clip->set_range(1,p_clips[i+1]); + clip->set_editable(1,true); + clip->set_cell_mode(2,TreeItem::CELL_MODE_RANGE); + clip->set_range_config(2,0,3600,0.01); + clip->set_range(2,p_clips[i+2]); + clip->set_editable(2,true); + clip->set_cell_mode(3,TreeItem::CELL_MODE_CHECK); + clip->set_editable(3,true); + clip->set_checked(3,p_clips[i+3]); + clips.push_back(clip); + + } + + TreeItem *newclip = clips_tree->create_item(clips_base); + newclip->set_text(0,"<new clip>"); + newclip->set_editable(0,true); + newclip->set_editable(1,false); + newclip->set_editable(2,false); + newclip->set_editable(3,false); + clips.push_back(newclip); + +} + + EditorImportAnimationOptions::EditorImportAnimationOptions() { updating=false; + validating=false; + + TabContainer *tab= memnew(TabContainer); + add_margin_child("Animation Options",tab,true); flags = memnew( Tree ); flags->set_hide_root(true); + tab->add_child(flags); + flags->set_name("Flags"); TreeItem *root = flags->create_item(); const char ** fname=anim_flag_names; @@ -263,14 +461,133 @@ EditorImportAnimationOptions::EditorImportAnimationOptions() { items.push_back(ti); fname++; fdescr++; - } + } + + + TreeItem *fps_base = flags->create_item(root); + fps_base->set_text(0,"Bake FPS:"); + fps_base->set_editable(0,false); + fps = flags->create_item(fps_base); + fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE); + fps->set_editable(0,true); + fps->set_range_config(0,1,120,1); + fps->set_range(0,15); + + optimization_tree = memnew( Tree ); + optimization_tree->set_columns(2); + tab->add_child(optimization_tree); + optimization_tree->set_name("Optimizer"); + optimization_tree->set_column_expand(0,true); + optimization_tree->set_column_expand(1,false); + optimization_tree->set_column_min_width(1,80); + optimization_tree->set_hide_root(true); + + + TreeItem *optimize_root = optimization_tree->create_item(); + + optimize_linear_error = optimization_tree->create_item(optimize_root); + optimize_linear_error->set_text(0,"Max Linear Error"); + optimize_linear_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); + optimize_linear_error->set_editable(1,true); + optimize_linear_error->set_range_config(1,0,1,0.001); + optimize_linear_error->set_range(1,0.05); + + optimize_angular_error = optimization_tree->create_item(optimize_root); + optimize_angular_error->set_text(0,"Max Angular Error"); + optimize_angular_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); + optimize_angular_error->set_editable(1,true); + optimize_angular_error->set_range_config(1,0,1,0.001); + optimize_angular_error->set_range(1,0.01); + + optimize_max_angle = optimization_tree->create_item(optimize_root); + optimize_max_angle->set_text(0,"Max Angle"); + optimize_max_angle->set_cell_mode(1,TreeItem::CELL_MODE_RANGE); + optimize_max_angle->set_editable(1,true); + optimize_max_angle->set_range_config(1,0,360,0.001); + optimize_max_angle->set_range(1,int(180*0.125)); + + clips_tree = memnew( Tree ); + clips_tree->set_hide_root(true); + tab->add_child(clips_tree); + clips_tree->set_name("Clips"); + + clips_tree->set_columns(4); + clips_tree->set_column_expand(0,1); + clips_tree->set_column_expand(1,0); + clips_tree->set_column_expand(2,0); + clips_tree->set_column_expand(3,0); + clips_tree->set_column_min_width(1,60); + clips_tree->set_column_min_width(2,60); + clips_tree->set_column_min_width(3,40); + clips_tree->set_column_titles_visible(true); + clips_tree->set_column_title(0,"Name"); + clips_tree->set_column_title(1,"Start(s)"); + clips_tree->set_column_title(2,"End(s)"); + clips_tree->set_column_title(3,"Loop"); + clips_base =clips_tree->create_item(0); + + + setup_clips(Array()); + + + filters = memnew( TextEdit ); + tab->add_child(filters); + filters->set_name("Filters"); +} + + + +void EditorImportAnimationOptions::set_fps(int p_fps) { + + fps->set_range(0,p_fps); +} + +int EditorImportAnimationOptions::get_fps() const { + + return fps->get_range(0); +} + + +void EditorImportAnimationOptions::set_optimize_linear_error(float p_optimize_linear_error) { + + optimize_linear_error->set_range(1,p_optimize_linear_error); +} + +float EditorImportAnimationOptions::get_optimize_linear_error() const { + + return optimize_linear_error->get_range(1); +} + +void EditorImportAnimationOptions::set_optimize_angular_error(float p_optimize_angular_error) { + + optimize_angular_error->set_range(1,p_optimize_angular_error); +} + +float EditorImportAnimationOptions::get_optimize_angular_error() const { + + return optimize_angular_error->get_range(1); +} + +void EditorImportAnimationOptions::set_optimize_max_angle(float p_optimize_max_angle) { + + optimize_max_angle->set_range(1,p_optimize_max_angle); +} + +float EditorImportAnimationOptions::get_optimize_max_angle() const { + + return optimize_max_angle->get_range(1); +} - add_margin_child("Animation Options",flags,true); +void EditorImportAnimationOptions::set_filter(const String& p_filter) { + filters->set_text(p_filter); } +String EditorImportAnimationOptions::get_filter() const { + return filters->get_text(); +} @@ -308,6 +625,17 @@ void EditorSceneImportDialog::_choose_file(const String& p_path) { } #endif + if (p_path!=String()) { + + String from_path = EditorFileSystem::get_singleton()->find_resource_from_source(EditorImportPlugin::validate_source_path(p_path)); + print_line("from path.."+from_path); + if (from_path!=String()) { + popup_import(from_path); + + } + } + + import_path->set_text(p_path); } @@ -413,7 +741,15 @@ void EditorSceneImportDialog::_import(bool p_and_open) { rim->set_option("texture_format",texture_options->get_format()); rim->set_option("texture_quality",texture_options->get_quality()); rim->set_option("animation_flags",animation_options->get_flags()); + rim->set_option("animation_bake_fps",animation_options->get_fps()); + rim->set_option("animation_optimizer_linear_error",animation_options->get_optimize_linear_error()); + rim->set_option("animation_optimizer_angular_error",animation_options->get_optimize_angular_error()); + rim->set_option("animation_optimizer_max_angle",animation_options->get_optimize_max_angle()); + rim->set_option("animation_filters",animation_options->get_filter()); + rim->set_option("animation_clips",animation_options->get_clips()); rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String()); + rim->set_option("import_this_time",this_import->get_selected()); + rim->set_option("import_next_time",next_import->get_selected()); rim->set_option("reimport",true); List<String> missing; @@ -526,7 +862,7 @@ void EditorSceneImportDialog::_browse_script() { void EditorSceneImportDialog::popup_import(const String &p_from) { - popup_centered(Size2(700,500)); + popup_centered(Size2(750,550)); if (p_from!="") { Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from); if (rimd.is_null()) @@ -544,7 +880,24 @@ void EditorSceneImportDialog::popup_import(const String &p_from) { texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format")))); texture_options->set_quality(rimd->get_option("texture_quality")); animation_options->set_flags(rimd->get_option("animation_flags")); + if (rimd->has_option("animation_clips")) + animation_options->setup_clips(rimd->get_option("animation_clips")); + if (rimd->has_option("animation_filters")) + animation_options->set_filter(rimd->get_option("animation_filters")); + if (rimd->has_option("animation_bake_fps")) + animation_options->set_fps(rimd->get_option("animation_bake_fps")); + if (rimd->has_option("animation_optimizer_linear_error")) + animation_options->set_optimize_linear_error(rimd->get_option("animation_optimizer_linear_error")); + if (rimd->has_option("animation_optimizer_angular_error")) + animation_options->set_optimize_angular_error(rimd->get_option("animation_optimizer_angular_error")); + if (rimd->has_option("animation_optimizer_max_angle")) + animation_options->set_optimize_max_angle(rimd->get_option("animation_optimizer_max_angle")); + script_path->set_text(rimd->get_option("post_import_script")); + if (rimd->has_option("import_this_time")) + this_import->select(rimd->get_option("import_this_time")); + if (rimd->has_option("import_next_time")) + next_import->select(rimd->get_option("import_next_time")); save_path->set_text(p_from.get_base_dir()); import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0))); @@ -556,7 +909,7 @@ void EditorSceneImportDialog::popup_import(const String &p_from) { void EditorSceneImportDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { List<String> extensions; @@ -619,7 +972,7 @@ void EditorSceneImportDialog::_bind_methods() { ObjectTypeDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file); ObjectTypeDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file); ObjectTypeDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script); - ObjectTypeDB::bind_method("_import",&EditorSceneImportDialog::_import); + ObjectTypeDB::bind_method("_import",&EditorSceneImportDialog::_import,DEFVAL(false)); ObjectTypeDB::bind_method("_browse",&EditorSceneImportDialog::_browse); ObjectTypeDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target); ObjectTypeDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script); @@ -792,6 +1145,20 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce error_dialog->get_ok()->set_text("Accept"); // error_dialog->get_cancel()->hide(); + this_import = memnew( OptionButton ); + this_import->add_item("Overwrite Existing Scene"); + this_import->add_item("Owerwrite Existing, Keep Materials"); + this_import->add_item("Keep Existing, Merge with New"); + this_import->add_item("Keep Existing, Ignore New"); + vbc->add_margin_child("This Time:",this_import); + + next_import = memnew( OptionButton ); + next_import->add_item("Overwrite Existing Scene"); + next_import->add_item("Owerwrite Existing, Keep Materials"); + next_import->add_item("Keep Existing, Merge with New"); + next_import->add_item("Keep Existing, Ignore New"); + vbc->add_margin_child("Next Time:",next_import); + set_hide_on_ok(false); GLOBAL_DEF("import/shared_textures","res://"); @@ -814,7 +1181,7 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce animation_options = memnew( EditorImportAnimationOptions ); ovb->add_child(animation_options); animation_options->set_v_size_flags(SIZE_EXPAND_FILL); - animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_TRACKS_IN_ALL_BONES); + animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS); confirm_import = memnew( ConfirmationDialog ); @@ -1815,6 +2182,79 @@ void EditorSceneImportPlugin::_merge_scenes(Node *p_node,Node *p_imported) { } +void EditorSceneImportPlugin::_scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials) { + + if (!p_base && p_node->get_owner()!=p_base) + return; + MeshInstance *mi=p_node->cast_to<MeshInstance>(); + + if (mi) { + if (mi->get_material_override().is_valid()) { + String path = p_base->get_path_to(p_node); + override_materials[path]=mi->get_material_override(); + } + Ref<Mesh> mesh = mi->get_mesh(); + if (mesh.is_valid()) { + + for(int i=0;i<mesh->get_surface_count();i++) { + + String name = mesh->get_name()+":"+mesh->surface_get_name(i); + if (!mesh_materials.has(name)) { + mesh_materials[name]=mesh->surface_get_material(i); + } + } + } + } + + for(int i=0;i<p_node->get_child_count();i++) { + _scan_materials(p_base,p_node->get_child(i),mesh_materials,override_materials); + } +} + + +void EditorSceneImportPlugin::_apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed) { + + if (!p_base && p_node->get_owner()!=p_base) + return; + + MeshInstance *mi=p_node->cast_to<MeshInstance>(); + + if (mi) { + + String path = p_base->get_path_to(p_node); + if (override_materials.has(path)) + mi->set_material_override(override_materials[path]); + + Ref<Mesh> mesh = mi->get_mesh(); + if (mesh.is_valid() && !meshes_processed.has(mesh)) { + meshes_processed.insert(mesh); + for(int i=0;i<mesh->get_surface_count();i++) { + + String name = mesh->get_name()+":"+mesh->surface_get_name(i); + if (mesh_materials.has(name)) { + + Ref<Material> mat = mesh_materials[name]; + mesh->surface_set_material(i,mat); + } + } + } + } + + for(int i=0;i<p_node->get_child_count();i++) { + _apply_materials(p_base,p_node->get_child(i),mesh_materials,override_materials,meshes_processed); + } +} + +void EditorSceneImportPlugin::_merge_materials(Node *p_node,Node *p_imported) { + + Map<String,Ref<Material> > mesh_materials; + Map<String,Ref<Material> > override_materials; + + _scan_materials(p_node,p_node,mesh_materials,override_materials); + Set<Ref<Mesh> > mp; + _apply_materials(p_imported,p_imported,mesh_materials,override_materials,mp); + +} #if 0 @@ -1882,14 +2322,22 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from int animation_flags=p_from->get_option("animation_flags"); int scene_flags = from->get_option("flags"); + int fps = 24; + if (from->has_option("animation_bake_fps")) + fps=from->get_option("animation_bake_fps"); + + + Array clips; + if (from->has_option("animation_clips")) + clips=from->get_option("animation_clips"); uint32_t import_flags=0; if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP) import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP; if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE) import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE; - if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_TRACKS_IN_ALL_BONES) - import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES; + if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS) + import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS; if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS) import_flags|=EditorSceneImporter::IMPORT_ANIMATION; //if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES) @@ -1902,7 +2350,7 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from Error err=OK; - Node *scene = importer->import_scene(src_path,import_flags,r_missing,&err); + Node *scene = importer->import_scene(src_path,import_flags,fps,r_missing,&err); if (!scene || err!=OK) { return err; } @@ -1913,19 +2361,301 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from return OK; } + +void EditorSceneImportPlugin::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) { + + if (!scene->has_node(String("AnimationPlayer"))) + return; + + Node* n = scene->get_node(String("AnimationPlayer")); + ERR_FAIL_COND(!n); + AnimationPlayer *anim = n->cast_to<AnimationPlayer>(); + ERR_FAIL_COND(!anim); + + if (!anim->has_animation("default")) + return; + + + Ref<Animation> default_anim = anim->get_animation("default"); + + for(int i=0;i<p_clips.size();i+=4) { + + String name = p_clips[i]; + float from=p_clips[i+1]; + float to=p_clips[i+2]; + bool loop=p_clips[i+3]; + if (from>=to) + continue; + + Ref<Animation> new_anim = memnew( Animation ); + + for(int j=0;j<default_anim->get_track_count();j++) { + + + List<float> keys; + int kc = default_anim->track_get_key_count(j); + int dtrack=-1; + for(int k=0;k<kc;k++) { + + float kt = default_anim->track_get_key_time(j,k); + if (kt>=from && kt<to) { + + //found a key within range, so create track + if (dtrack==-1) { + new_anim->add_track(default_anim->track_get_type(j)); + dtrack = new_anim->get_track_count()-1; + new_anim->track_set_path(dtrack,default_anim->track_get_path(j)); + + if (kt>(from+0.01) && k>0) { + + if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) { + Quat q; + Vector3 p; + Vector3 s; + default_anim->transform_track_interpolate(j,from,&p,&q,&s); + new_anim->transform_track_insert_key(dtrack,0,p,q,s); + } + } + + } + + if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) { + Quat q; + Vector3 p; + Vector3 s; + default_anim->transform_track_get_key(j,k,&p,&q,&s); + new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s); + } + + } + + if (dtrack!=-1 && kt>=to) { + + if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) { + Quat q; + Vector3 p; + Vector3 s; + default_anim->transform_track_interpolate(j,to,&p,&q,&s); + new_anim->transform_track_insert_key(dtrack,to-from,p,q,s); + } + } + + } + + if (dtrack==-1 && p_bake_all) { + new_anim->add_track(default_anim->track_get_type(j)); + dtrack = new_anim->get_track_count()-1; + new_anim->track_set_path(dtrack,default_anim->track_get_path(j)); + if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) { + + + Quat q; + Vector3 p; + Vector3 s; + default_anim->transform_track_interpolate(j,from,&p,&q,&s); + new_anim->transform_track_insert_key(dtrack,0,p,q,s); + default_anim->transform_track_interpolate(j,to,&p,&q,&s); + new_anim->transform_track_insert_key(dtrack,to-from,p,q,s); + } + + } + } + + + new_anim->set_loop(loop); + new_anim->set_length(to-from); + anim->add_animation(name,new_anim); + } + + anim->remove_animation("default"); //remove default (no longer needed) +} + +void EditorSceneImportPlugin::_filter_anim_tracks(Ref<Animation> anim,Set<String> &keep) { + + Ref<Animation> a = anim; + ERR_FAIL_COND(!a.is_valid()); + + print_line("From Anim "+anim->get_name()+":"); + + for(int j=0;j<a->get_track_count();j++) { + + String path = a->track_get_path(j); + + if (!keep.has(path)) { + + print_line("Remove: "+path); + a->remove_track(j); + j--; + } + + } +} + + +void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text) { + + if (!scene->has_node(String("AnimationPlayer"))) + return; + Node* n = scene->get_node(String("AnimationPlayer")); + ERR_FAIL_COND(!n); + AnimationPlayer *anim = n->cast_to<AnimationPlayer>(); + ERR_FAIL_COND(!anim); + + Vector<String> strings = p_text.split("\n"); + for(int i=0;i<strings.size();i++) { + + strings[i]=strings[i].strip_edges(); + } + + List<StringName> anim_names; + anim->get_animation_list(&anim_names); + for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) { + + String name = E->get(); + bool valid_for_this=false; + bool valid=false; + + Set<String> keep; + Set<String> keep_local; + + + for(int i=0;i<strings.size();i++) { + + + if (strings[i].begins_with("@")) { + + valid_for_this=false; + for(Set<String>::Element *F=keep_local.front();F;F=F->next()) { + keep.insert(F->get()); + } + keep_local.clear(); + + Vector<String> filters=strings[i].substr(1,strings[i].length()).split(","); + for(int j=0;j<filters.size();j++) { + + String fname = filters[j].strip_edges(); + if (fname=="") + continue; + int fc = fname[0]; + bool plus; + if (fc=='+') + plus=true; + else if (fc=='-') + plus=false; + else + continue; + + String filter=fname.substr(1,fname.length()).strip_edges(); + + if (!name.matchn(filter)) + continue; + valid_for_this=plus; + } + + if (valid_for_this) + valid=true; + + } else if (valid_for_this) { + + Ref<Animation> a = anim->get_animation(name); + if (!a.is_valid()) + continue; + + for(int j=0;j<a->get_track_count();j++) { + + String path = a->track_get_path(j); + + String tname = strings[i]; + if (tname=="") + continue; + int fc = tname[0]; + bool plus; + if (fc=='+') + plus=true; + else if (fc=='-') + plus=false; + else + continue; + + String filter=tname.substr(1,tname.length()).strip_edges(); + + if (!path.matchn(filter)) + continue; + + if (plus) + keep_local.insert(path); + else if (!keep.has(path)) { + keep_local.erase(path); + } + } + + } + + } + + if (valid) { + for(Set<String>::Element *F=keep_local.front();F;F=F->next()) { + keep.insert(F->get()); + } + + _filter_anim_tracks(anim->get_animation(name),keep); + } + + } + + + +} + +void EditorSceneImportPlugin::_optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle) { + + if (!scene->has_node(String("AnimationPlayer"))) + return; + Node* n = scene->get_node(String("AnimationPlayer")); + ERR_FAIL_COND(!n); + AnimationPlayer *anim = n->cast_to<AnimationPlayer>(); + ERR_FAIL_COND(!anim); + + + List<StringName> anim_names; + anim->get_animation_list(&anim_names); + for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) { + + Ref<Animation> a = anim->get_animation(E->get()); + a->optimize(p_max_lin_error,p_max_ang_error,Math::deg2rad(p_max_angle)); + } +} + + Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) { Error err=OK; Ref<ResourceImportMetadata> from=p_from; String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0)); int animation_flags=p_from->get_option("animation_flags"); + Array animation_clips = p_from->get_option("animation_clips"); + String animation_filter = p_from->get_option("animation_filters"); int scene_flags = from->get_option("flags"); + float anim_optimizer_linerr=0.05; + float anim_optimizer_angerr=0.01; + float anim_optimizer_maxang=22; + + if (from->has_option("animation_optimizer_linear_error")) + anim_optimizer_linerr=from->get_option("animation_optimizer_linear_error"); + if (from->has_option("animation_optimizer_angular_error")) + anim_optimizer_angerr=from->get_option("animation_optimizer_angular_error"); + if (from->has_option("animation_optimizer_max_angle")) + anim_optimizer_maxang=from->get_option("animation_optimizer_max_angle"); EditorProgress progress("import","Import Scene",104); progress.step("Importing Scene..",2); - bool merge = !bool(from->get_option("reimport")); + bool reimport = bool(from->get_option("reimport")); + int this_time_action = from->get_option("import_this_time"); + int next_time_action = from->get_option("import_next_time"); + + int import_action = reimport?this_time_action:next_time_action; from->set_source_md5(0,FileAccess::get_md5(src_path)); from->set_editor(get_name()); @@ -1940,6 +2670,13 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c Map< Ref<ImageTexture>,TextureRole > imagemap; scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap); + if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE) + _optimize_animations(scene,anim_optimizer_linerr,anim_optimizer_angerr,anim_optimizer_maxang); + if (animation_clips.size()) + _create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS); + + _filter_tracks(scene,animation_filter); + /// BEFORE ANYTHING, RUN SCRIPT @@ -2063,7 +2800,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c /// BEFORE SAVING - MERGE - if (merge) { + if (import_action!=SCENE_UPDATE_REPLACE_WITH_NEW) { progress.step("Merging..",103); @@ -2082,10 +2819,30 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c if (existing) { - _merge_scenes(existing,scene); - memdelete(scene); - scene=existing; + switch(import_action) { + + case SCENE_UPDATE_REPLACE_WITH_NEW: break; + case SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS: { + + _merge_materials(existing,scene); + memdelete(existing); + + } break; + case SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES: { + + _merge_scenes(existing,scene); + memdelete(scene); + scene=existing; + + } break; + case SCENE_UPDATE_KEEP_OLD: { + + memdelete(scene); + scene=existing; + } break; + } + } } diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.h b/tools/editor/io_plugins/editor_scene_import_plugin.h index 72b4089d89..fa4730f7ee 100644 --- a/tools/editor/io_plugins/editor_scene_import_plugin.h +++ b/tools/editor/io_plugins/editor_scene_import_plugin.h @@ -58,7 +58,7 @@ public: IMPORT_ANIMATION=2, IMPORT_ANIMATION_DETECT_LOOP=4, IMPORT_ANIMATION_OPTIMIZE=8, - IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES=16, + IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16, IMPORT_GENERATE_TANGENT_ARRAYS=256, IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512 @@ -66,7 +66,7 @@ public: virtual uint32_t get_import_flags() const=0; virtual void get_extensions(List<String> *r_extensions) const=0; - virtual Node* import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps,Error* r_err=NULL)=0; + virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps,Error* r_err=NULL)=0; virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0; @@ -108,10 +108,18 @@ class EditorSceneImportPlugin : public EditorImportPlugin { void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,TextureRole >& image_map,int p_flags); Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map); + void _create_clips(Node *scene, const Array& p_clips, bool p_bake_all); + void _filter_anim_tracks(Ref<Animation> anim,Set<String> &keep); + void _filter_tracks(Node *scene, const String& p_text); void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes); + void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set<Node*> &checked_nodes); + void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle); void _merge_scenes(Node *p_node, Node *p_imported); + void _scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials); + void _apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed); + void _merge_materials(Node *p_node,Node *p_imported); void _tag_import_paths(Node *p_scene,Node *p_node); @@ -142,6 +150,13 @@ public: SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30, }; + enum SceneUpdate { + SCENE_UPDATE_REPLACE_WITH_NEW, + SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS, + SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES, + SCENE_UPDATE_KEEP_OLD, + }; + virtual String get_name() const; virtual String get_visible_name() const; @@ -171,7 +186,7 @@ public: ANIMATION_DETECT_LOOP=1, ANIMATION_KEEP_VALUE_TRACKS=2, ANIMATION_OPTIMIZE=4, - ANIMATION_FORCE_TRACKS_IN_ALL_BONES=8 + ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=8 }; virtual String get_name() const; @@ -185,5 +200,4 @@ public: }; - #endif // EDITOR_SCENE_IMPORT_PLUGIN_H diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 86f7787a9c..ce376f2e7b 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -151,7 +151,7 @@ void EditorImportTextureOptions::_bind_methods() { void EditorImportTextureOptions::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { flags->connect("item_edited",this,"_changed"); format->connect("item_selected",this,"_changedp"); @@ -411,7 +411,11 @@ void EditorTextureImportDialog::popup_import(const String& p_from) { Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from); ERR_FAIL_COND(!rimd.is_valid()); - save_path->set_text(p_from.get_base_dir()); + if (plugin->get_mode()==EditorTextureImportPlugin::MODE_ATLAS) + save_path->set_text(p_from); + else + save_path->set_text(p_from.get_base_dir()); + texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("format")))); texture_options->set_flags(rimd->get_option("flags")); texture_options->set_quality(rimd->get_option("quality")); @@ -429,7 +433,7 @@ void EditorTextureImportDialog::popup_import(const String& p_from) { void EditorTextureImportDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { List<String> extensions; diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h index d17b3c05c2..e733a3ddf9 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.h +++ b/tools/editor/io_plugins/editor_texture_import_plugin.h @@ -98,6 +98,7 @@ public: IMAGE_FLAG_USE_ANISOTROPY=1024, //convert image to linear }; + Mode get_mode() const { return mode; } virtual String get_name() const; virtual String get_visible_name() const; virtual void import_dialog(const String& p_from=""); diff --git a/tools/editor/io_plugins/editor_translation_import_plugin.cpp b/tools/editor/io_plugins/editor_translation_import_plugin.cpp index 89a7584f77..9540869789 100644 --- a/tools/editor/io_plugins/editor_translation_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_translation_import_plugin.cpp @@ -273,7 +273,7 @@ public: void _notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { } diff --git a/tools/editor/output_strings.cpp b/tools/editor/output_strings.cpp index 122db3adf9..ec85505484 100644 --- a/tools/editor/output_strings.cpp +++ b/tools/editor/output_strings.cpp @@ -129,7 +129,7 @@ void OutputStrings::_notification(int p_what) { } break; - case NOTIFICATION_ENTER_SCENE: + case NOTIFICATION_ENTER_TREE: case NOTIFICATION_RESIZED: { diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index 0d709b9a72..f706d67f6d 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -76,6 +76,8 @@ void AnimationPlayerEditor::_notification(int p_what) { seek->set_val(player->get_current_animation_pos()); if (edit_anim->is_pressed()) editor->get_animation_editor()->set_anim_pos(player->get_current_animation_pos()); + EditorNode::get_singleton()->get_property_editor()->refresh(); + } else if (last_active) { //need the last frame after it stopped @@ -87,7 +89,7 @@ void AnimationPlayerEditor::_notification(int p_what) { updating = false; } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { editor->connect("hide_animation_player_editors",this,"_hide_anim_editors"); add_anim->set_icon( get_icon("New","EditorIcons") ); @@ -119,7 +121,7 @@ void AnimationPlayerEditor::_notification(int p_what) { if (p_what==NOTIFICATION_READY) { - get_scene()->connect("node_removed",this,"_node_removed"); + get_tree()->connect("node_removed",this,"_node_removed"); } if (p_what==NOTIFICATION_DRAW) { @@ -854,6 +856,8 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos) { return; seek->set_val(p_pos); + EditorNode::get_singleton()->get_property_editor()->refresh(); + //seekit diff --git a/tools/editor/plugins/animation_tree_editor_plugin.cpp b/tools/editor/plugins/animation_tree_editor_plugin.cpp index aeef593093..af15e17f50 100644 --- a/tools/editor/plugins/animation_tree_editor_plugin.cpp +++ b/tools/editor/plugins/animation_tree_editor_plugin.cpp @@ -221,8 +221,8 @@ void AnimationTreeEditor::_edit_dialog_animation_changed() { void AnimationTreeEditor::_edit_dialog_edit_animation() { - if (get_scene()->is_editor_hint()) { - get_scene()->get_root()->get_child(0)->call("_resource_selected", property_editor->get_variant().operator RefPtr()); + if (get_tree()->is_editor_hint()) { + get_tree()->get_root()->get_child(0)->call("_resource_selected", property_editor->get_variant().operator RefPtr()); }; }; @@ -936,7 +936,7 @@ void AnimationTreeEditor::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { play_button->set_icon( get_icon("Play","EditorIcons") ); add_menu->set_icon( get_icon("Add","EditorIcons") ); diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp index 3774b7d25b..184f80a1b7 100644 --- a/tools/editor/plugins/baked_light_baker.cpp +++ b/tools/editor/plugins/baked_light_baker.cpp @@ -4,8 +4,17 @@ #include <cmath> #include "io/marshalls.h" #include "tools/editor/editor_node.h" +#include "tools/editor/editor_settings.h" +void baked_light_baker_add_64f(double *dst,double value); +void baked_light_baker_add_64i(int64_t *dst,int64_t value); + +//-separar en 2 testuras? +//*mejorar performance y threads +//*modos lineales +//*saturacion + _FORCE_INLINE_ static uint64_t get_uv_normal_bit(const Vector3& p_vector) { int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*6.0/Math_PI+0.5)); @@ -66,6 +75,12 @@ BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>& image.convert(Image::FORMAT_RGBA); } + if (imgtex->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR) { + Image copy = image; + copy.srgb_to_linear(); + image=copy; + } + DVector<uint8_t> dvt=image.get_data(); DVector<uint8_t>::Read r=dvt.read(); MeshTexture mt; @@ -105,8 +120,13 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m if (fm.is_valid()) { //fixed route mm.diffuse.color=fm->get_parameter(FixedMaterial::PARAM_DIFFUSE); + if (linear_color) + mm.diffuse.color=mm.diffuse.color.to_linear(); mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_DIFFUSE)); mm.specular.color=fm->get_parameter(FixedMaterial::PARAM_SPECULAR); + if (linear_color) + mm.specular.color=mm.specular.color.to_linear(); + mm.specular.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_SPECULAR)); } else { @@ -270,6 +290,11 @@ void BakedLightBaker::_parse_geometry(Node* p_node) { dirl.type=VS::LightType(dl->get_light_type()); dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + if (linear_color) + dirl.diffuse=dirl.diffuse.to_linear(); + if (linear_color) + dirl.specular=dirl.specular.to_linear(); + dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); dirl.pos=dl->get_global_transform().origin; dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); @@ -472,8 +497,11 @@ void BakedLightBaker::_make_bvh() { } bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); + ray_stack = memnew_arr(uint32_t,max_depth); bvh_stack = memnew_arr(BVH*,max_depth); + + bvh_depth = max_depth; } void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_depth) { @@ -563,6 +591,12 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de child->aabb.pos.z+=child->aabb.size.z; + child->full_accum[0]=0; + child->full_accum[1]=0; + child->full_accum[2]=0; + child->sampler_ofs=0; + + if (stack_pos==octree_depth-1) { child->leaf=true; @@ -585,14 +619,10 @@ void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_de cell_count++; int lz = lights.size(); - child->light = memnew_arr(OctantLight,lz); - - for(int li=0;li<lz;li++) { - for(int ci=0;ci<8;ci++) { - child->light[li].accum[ci][0]=0; - child->light[li].accum[ci][1]=0; - child->light[li].accum[ci][2]=0; - } + for(int ci=0;ci<8;ci++) { + child->light_accum[ci][0]=0; + child->light_accum[ci][1]=0; + child->light_accum[ci][2]=0; } child->parent=ptr_stack[stack_pos]; @@ -797,12 +827,12 @@ void BakedLightBaker::_make_octree() { -void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light, const Plane& p_plane) { +void BakedLightBaker::_plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light,const Color& p_tint_light,bool p_only_full, const Plane& p_plane) { //stackless version - uint32_t *stack=octant_stack; - uint32_t *ptr_stack=octantptr_stack; + uint32_t *stack=thread_stack.octant_stack; + uint32_t *ptr_stack=thread_stack.octantptr_stack; Octant *octants=octant_pool.ptr(); stack[0]=0; @@ -815,6 +845,29 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, Octant &octant=octants[ptr_stack[stack_pos]]; + if (stack[stack_pos]==0) { + + + Vector3 pos = octant.aabb.pos + octant.aabb.size*0.5; + float md = 1<<(octree_depth - stack_pos ); + float r=cell_size*plot_size*md; + float div = 1.0/(md*md*md); + //div=1.0; + + + float d = p_plot_pos.distance_to(pos); + + if ((p_plane.distance_to(pos)>-cell_size*1.75*md) && d<=r) { + + + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + + baked_light_baker_add_64f(&octant.full_accum[0],p_tint_light.r*intensity*div); + baked_light_baker_add_64f(&octant.full_accum[1],p_tint_light.g*intensity*div); + baked_light_baker_add_64f(&octant.full_accum[2],p_tint_light.b*intensity*div); + } + } + if (octant.leaf) { @@ -822,41 +875,44 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, //if (p_plane.normal.dot(octant.aabb.get_support(p_plane.normal)) < p_plane.d-CMP_EPSILON) { //octants behind are no go - - float r=cell_size*plot_size; - for(int i=0;i<8;i++) { - Vector3 pos=octant.aabb.pos; - if (i&1) - pos.x+=octant.aabb.size.x; - if (i&2) - pos.y+=octant.aabb.size.y; - if (i&4) - pos.z+=octant.aabb.size.z; + if (!p_only_full) { + float r=cell_size*plot_size; + for(int i=0;i<8;i++) { + Vector3 pos=octant.aabb.pos; + if (i&1) + pos.x+=octant.aabb.size.x; + if (i&2) + pos.y+=octant.aabb.size.y; + if (i&4) + pos.z+=octant.aabb.size.z; - float d = p_plot_pos.distance_to(pos); + float d = p_plot_pos.distance_to(pos); - if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) { + if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) { - float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. - if (edge_damp>0) { - Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]); - if (normal.x>0 || normal.y>0 || normal.z>0) { + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + if (edge_damp>0) { + Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]); + if (normal.x>0 || normal.y>0 || normal.z>0) { - float damp = Math::abs(p_plane.normal.dot(normal)); - intensity*=pow(damp,edge_damp); + float damp = Math::abs(p_plane.normal.dot(normal)); + intensity*=pow(damp,edge_damp); + } } - } - //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); - //intensity = Math::cos(d*Math_PI*0.5/r); + //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); + //intensity = Math::cos(d*Math_PI*0.5/r); + + baked_light_baker_add_64f(&octant.light_accum[i][0],p_light.r*intensity); + baked_light_baker_add_64f(&octant.light_accum[i][1],p_light.g*intensity); + baked_light_baker_add_64f(&octant.light_accum[i][2],p_light.b*intensity); + - octant.light[p_light_index].accum[i][0]+=p_light.r*intensity; - octant.light[p_light_index].accum[i][1]+=p_light.g*intensity; - octant.light[p_light_index].accum[i][2]+=p_light.b*intensity; + } } } @@ -893,11 +949,11 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, } -float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) { +float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) { - uint32_t* stack = ray_stack; - BVH **bstack = bvh_stack; + uint32_t* stack = thread_stack.ray_stack; + BVH **bstack = thread_stack.bvh_stack; enum { TEST_AABB_BIT=0, @@ -915,6 +971,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons n/=len; + real_t d=1e10; bool inters=false; Vector3 r_normal; @@ -1139,7 +1196,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons #endif - ret=_throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + ret=_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) { @@ -1150,7 +1207,7 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons Vector3 rn = n - r_normal *r_normal.dot(n) * 2.0; - _throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); } } @@ -1158,19 +1215,25 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons // _plot_light_point(r_point,octree,octree_aabb,p_light); - Color plot_light=diffuse_at_point; + Color plot_light=res_light.linear_interpolate(diffuse_at_point,tint); plot_light.r*=att; plot_light.g*=att; plot_light.b*=att; + Color tint_light=diffuse_at_point; + tint_light.r*=att; + tint_light.g*=att; + tint_light.b*=att; + + bool skip=false; - if (!p_first_bounce) { + if (!p_first_bounce || p_bake_direct) { float r = plot_size * cell_size*2; if (dist<r) { //avoid accumulaiton of light on corners //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size); - plot_light=Color(0,0,0,0); + skip=true; } else { @@ -1181,12 +1244,12 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons double r2 = double(rand())/RAND_MAX; double r3 = double(rand())/RAND_MAX; Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.25)).normalized(); - float d =_throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true); - r = plot_size*cell_size*0.7; + float d =_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true); + r = plot_size*cell_size*ao_radius; if (d>0 && d<r) { //avoid accumulaiton of light on corners //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size); - plot_light=Color(0,0,0,0); + skip=true; } else { //plot_light=Color(0,0,0,0); @@ -1195,11 +1258,9 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons } - if (!p_first_bounce || lights[p_light_index].bake_direct) { - Plane plane(r_point,r_normal); - //print_line(String(plot_light)+String(" ")+rtos(att)); - _plot_light(p_light_index,r_point,aabb,plot_light,plane); - } + Plane plane(r_point,r_normal); + if (!skip) + _plot_light(thread_stack,r_point,aabb,plot_light,tint_light,!(!p_first_bounce || p_bake_direct),plane); return dist; @@ -1305,79 +1366,100 @@ void BakedLightBaker::_make_octree_texture() { //ok let's try to just create a texture - { + int otex_w=256; - int otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally - Vector3 lattice_cell_size=octree_aabb.size; - for(int i=0;i<lattice_size;i++) { + while (true) { - lattice_cell_size*=0.5; - } + uint32_t oct_idx=leaf_list; - while(true) { + int row=0; - //let's plot the leafs first, given the octree is not so obvious which size it will have - int row=4+4*(1<<lattice_size); + print_line("begin at row "+itos(row)); + int longest_line_reused=0; + int col=0; + int processed=0; + + //reset + while(oct_idx) { - uint32_t oct_idx=leaf_list; + BakedLightBaker::Octant *oct = &octants[oct_idx]; + oct->texture_x=0; + oct->texture_y=0; + oct_idx=oct->next_leaf; - //untag - while(oct_idx) { + } - BakedLightBaker::Octant *oct = &octants[oct_idx]; - //0,0 also means unprocessed - oct->texture_x=0; - oct->texture_y=0; - oct_idx=oct->next_leaf; + oct_idx=leaf_list; + //assign + while(oct_idx) { + BakedLightBaker::Octant *oct = &octants[oct_idx]; + if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { + //was not processed + uint32_t current_idx=oct_idx; + int reused=0; + + while(current_idx) { + BakedLightBaker::Octant *o = &octants[current_idx]; + if (col+1 >= otex_w) { + col=0; + row+=4; + } + o->texture_x=col; + o->texture_y=row; + processed++; + + if (o->bake_neighbour) { + reused++; + } + col+=o->bake_neighbour ? 1 : 2; //reuse neighbour + current_idx=o->bake_neighbour; + } + + if (reused>longest_line_reused) { + longest_line_reused=reused; + } } + oct_idx=oct->next_leaf; + } - oct_idx=leaf_list; + row+=4; + if (otex_w < row) { - print_line("begin at row "+itos(row)); - int longest_line_reused=0; - int col=0; - int processed=0; + otex_w*=2; + } else { + + baked_light_texture_w=otex_w; + baked_light_texture_h=nearest_power_of_2(row); + print_line("w: "+itos(otex_w)); + print_line("h: "+itos(row)); + break; + } - while(oct_idx) { - BakedLightBaker::Octant *oct = &octants[oct_idx]; - if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { - //was not processed - uint32_t current_idx=oct_idx; - int reused=0; + } - while(current_idx) { - BakedLightBaker::Octant *o = &octants[current_idx]; - if (col+1 >= otex_w) { - col=0; - row+=4; - } - o->texture_x=col; - o->texture_y=row; - processed++; - if (o->bake_neighbour) { - reused++; - } - col+=o->bake_neighbour ? 1 : 2; //reuse neighbour - current_idx=o->bake_neighbour; - } + { - if (reused>longest_line_reused) { - longest_line_reused=reused; - } - } - oct_idx=oct->next_leaf; - } + otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally + Vector3 lattice_cell_size=octree_aabb.size; + for(int i=0;i<lattice_size;i++) { + + lattice_cell_size*=0.5; + } - print_line("processed "+itos(processed)); - print_line("longest reused: "+itos(longest_line_reused)); + + while(true) { + + //let's plot the leafs first, given the octree is not so obvious which size it will have + int row=4+4*(1<<lattice_size); + int col=0; col=0; row+=4; @@ -1478,7 +1560,25 @@ double BakedLightBaker::get_normalization(int p_light_idx) const { return nrg; } -void BakedLightBaker::throw_rays(int p_amount) { + + +double BakedLightBaker::get_modifier(int p_light_idx) const { + + double nrg=0; + + const LightData &dl=lights[p_light_idx]; + double cell_area = cell_size*cell_size;; + //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area); + nrg=cell_area; + nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel + nrg*=dl.constant; + //nrg*=5; + + + return nrg; +} + +void BakedLightBaker::throw_rays(ThreadStack& thread_stack,int p_amount) { @@ -1488,6 +1588,8 @@ void BakedLightBaker::throw_rays(int p_amount) { int amount = p_amount * total_light_area / dl.area; + double mod = 1.0/double(get_modifier(i)); + mod*=p_amount/float(amount); switch(dl.type) { @@ -1502,12 +1604,15 @@ void BakedLightBaker::throw_rays(int p_amount) { from+=dl.left*(r2*2.0-1.0); Vector3 to = from+dl.dir*dl.length; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; + dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.length,col,NULL,0,0,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.length,col,NULL,0,0,max_bounces,true); } } break; case VS::LIGHT_OMNI: { @@ -1543,13 +1648,14 @@ void BakedLightBaker::throw_rays(int p_amount) { #endif Vector3 to = dl.pos+dir*dl.radius; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); } @@ -1574,13 +1680,14 @@ void BakedLightBaker::throw_rays(int p_amount) { Vector3 to = dl.pos+dir*dl.radius; Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; + float m = mod*dl.energy; + col.r*=m; + col.g*=m; + col.b*=m; dl.rays_thrown++; - total_rays++; - _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + baked_light_baker_add_64i(&total_rays,1); + _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); } @@ -1622,6 +1729,10 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) { edge_damp=baked_light->get_edge_damp(); normal_damp=baked_light->get_normal_damp(); octree_extra_margin=baked_light->get_cell_extra_margin(); + tint=baked_light->get_tint(); + ao_radius=baked_light->get_ao_radius(); + ao_strength=baked_light->get_ao_strength(); + linear_color=baked_light->get_bake_flag(BakedLight::BAKE_LINEAR_COLOR); baked_textures.clear(); for(int i=0;i<baked_light->get_lightmaps_count();i++) { @@ -1651,13 +1762,134 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) { } -void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { +void BakedLightBaker::update_octree_sampler(DVector<int> &p_sampler) { + + BakedLightBaker::Octant *octants=octant_pool.ptr(); + double norm = 1.0/double(total_rays); + + + + if (p_sampler.size()==0 || first_bake_to_map) { + + Vector<int> tmp_smp; + tmp_smp.resize(32); //32 for header + + for(int i=0;i<32;i++) { + tmp_smp[i]=0; + } + + for(int i=octant_pool_size-1;i>=0;i--) { + + if (i==0) + tmp_smp[1]=tmp_smp.size(); + + Octant &octant=octants[i]; + octant.sampler_ofs = tmp_smp.size(); + int idxcol[2]={0,0}; + + int r = CLAMP((octant.full_accum[0]*norm)*2048,0,32767); + int g = CLAMP((octant.full_accum[1]*norm)*2048,0,32767); + int b = CLAMP((octant.full_accum[2]*norm)*2048,0,32767); + + idxcol[0]|=r; + idxcol[1]|=(g<<16)|b; + + if (octant.leaf) { + tmp_smp.push_back(idxcol[0]); + tmp_smp.push_back(idxcol[1]); + } else { + + for(int j=0;j<8;j++) { + if (octant.children[j]) { + idxcol[0]|=(1<<(j+16)); + } + } + tmp_smp.push_back(idxcol[0]); + tmp_smp.push_back(idxcol[1]); + for(int j=0;j<8;j++) { + if (octant.children[j]) { + tmp_smp.push_back(octants[octant.children[j]].sampler_ofs); + if (octants[octant.children[j]].sampler_ofs==0) { + print_line("FUUUUUUUUCK"); + } + } + } + } + + } + + p_sampler.resize(tmp_smp.size()); + DVector<int>::Write w = p_sampler.write(); + int ss = tmp_smp.size(); + for(int i=0;i<ss;i++) { + w[i]=tmp_smp[i]; + } + + first_bake_to_map=false; + + } + + double gamma = baked_light->get_gamma_adjust(); + double mult = baked_light->get_energy_multiplier(); + float saturation = baked_light->get_saturation(); + + DVector<int>::Write w = p_sampler.write(); + + encode_uint32(octree_depth,(uint8_t*)&w[2]); + encode_uint32(linear_color,(uint8_t*)&w[3]); + + encode_float(octree_aabb.pos.x,(uint8_t*)&w[4]); + encode_float(octree_aabb.pos.y,(uint8_t*)&w[5]); + encode_float(octree_aabb.pos.z,(uint8_t*)&w[6]); + encode_float(octree_aabb.size.x,(uint8_t*)&w[7]); + encode_float(octree_aabb.size.y,(uint8_t*)&w[8]); + encode_float(octree_aabb.size.z,(uint8_t*)&w[9]); + + //norm*=multiplier; + + for(int i=octant_pool_size-1;i>=0;i--) { + + Octant &octant=octants[i]; + int idxcol[2]={w[octant.sampler_ofs],w[octant.sampler_ofs+1]}; + + double rf=pow(octant.full_accum[0]*norm*mult,gamma); + double gf=pow(octant.full_accum[1]*norm*mult,gamma); + double bf=pow(octant.full_accum[2]*norm*mult,gamma); + + double gray = (rf+gf+bf)/3.0; + rf = gray + (rf-gray)*saturation; + gf = gray + (gf-gray)*saturation; + bf = gray + (bf-gray)*saturation; + + + int r = CLAMP((rf)*2048,0,32767); + int g = CLAMP((gf)*2048,0,32767); + int b = CLAMP((bf)*2048,0,32767); + + idxcol[0]=((idxcol[0]>>16)<<16)|r; + idxcol[1]=(g<<16)|b; + w[octant.sampler_ofs]=idxcol[0]; + w[octant.sampler_ofs+1]=idxcol[1]; + } + +} + +void BakedLightBaker::update_octree_images(DVector<uint8_t> &p_octree,DVector<uint8_t> &p_light) { int len = baked_octree_texture_w*baked_octree_texture_h*4; - p_image.resize(len); - DVector<uint8_t>::Write w = p_image.write(); + p_octree.resize(len); + + int ilen = baked_light_texture_w*baked_light_texture_h*4; + p_light.resize(ilen); + + + DVector<uint8_t>::Write w = p_octree.write(); zeromem(w.ptr(),len); + + DVector<uint8_t>::Write iw = p_light.write(); + zeromem(iw.ptr(),ilen); + float gamma = baked_light->get_gamma_adjust(); float mult = baked_light->get_energy_multiplier(); @@ -1668,6 +1900,13 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { w[i+3]=0xFF; } + for(int i=0;i<ilen;i+=4) { + iw[i+0]=0xFF; + iw[i+1]=0; + iw[i+2]=0xFF; + iw[i+3]=0xFF; + } + float multiplier=1.0; if (baked_light->get_format()==BakedLight::FORMAT_HDR8) @@ -1678,6 +1917,9 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { encode_float(1<<lattice_size,&w[12]); encode_uint32(octree_depth-lattice_size,&w[16]); encode_uint32(multiplier,&w[20]); + encode_uint16(baked_light_texture_w,&w[24]); //if present, use the baked light texture + encode_uint16(baked_light_texture_h,&w[26]); + encode_uint32(0,&w[28]); //baked light texture format encode_float(octree_aabb.pos.x,&w[32]); encode_float(octree_aabb.pos.y,&w[36]); @@ -1690,6 +1932,7 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { BakedLightBaker::Octant *octants=octant_pool.ptr(); int octant_count=octant_pool_size; uint8_t *ptr = w.ptr(); + uint8_t *lptr = iw.ptr(); int child_offsets[8]={ @@ -1703,7 +1946,18 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { baked_octree_texture_w*8+baked_octree_texture_w*4+4, }; - Vector<double> norm_arr; + int lchild_offsets[8]={ + 0, + 4, + baked_light_texture_w*4, + baked_light_texture_w*4+4, + baked_light_texture_w*8+0, + baked_light_texture_w*8+4, + baked_light_texture_w*8+baked_light_texture_w*4, + baked_light_texture_w*8+baked_light_texture_w*4+4, + }; + + /*Vector<double> norm_arr; norm_arr.resize(lights.size()); for(int i=0;i<lights.size();i++) { @@ -1711,39 +1965,43 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { } const double *normptr=norm_arr.ptr(); - +*/ + double norm = 1.0/double(total_rays); int lz=lights.size(); mult/=multiplier; + double saturation = baked_light->get_saturation(); for(int i=0;i<octant_count;i++) { Octant &oct=octants[i]; if (oct.texture_x==0 && oct.texture_y==0) continue; - int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2; + if (oct.leaf) { + int ofs = (oct.texture_y * baked_light_texture_w + oct.texture_x)<<2; + ERR_CONTINUE(ofs<0 || ofs >ilen); //write colors for(int j=0;j<8;j++) { //if (!oct.children[j]) // continue; - uint8_t *iptr=&ptr[ofs+child_offsets[j]]; - float r=0; - float g=0; - float b=0; - - for(int k=0;k<lz;k++) { - r+=oct.light[k].accum[j][0]*normptr[k]; - g+=oct.light[k].accum[j][1]*normptr[k]; - b+=oct.light[k].accum[j][2]*normptr[k]; - } + uint8_t *iptr=&lptr[ofs+lchild_offsets[j]]; + + float r=oct.light_accum[j][0]*norm; + float g=oct.light_accum[j][1]*norm; + float b=oct.light_accum[j][2]*norm; r=pow(r*mult,gamma); g=pow(g*mult,gamma); b=pow(b*mult,gamma); + double gray = (r+g+b)/3.0; + r = gray + (r-gray)*saturation; + g = gray + (g-gray)*saturation; + b = gray + (b-gray)*saturation; + float ic[3]={ r, g, @@ -1757,6 +2015,8 @@ void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { } else { + int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2; + ERR_CONTINUE(ofs<0 || ofs >len); //write indices for(int j=0;j<8;j++) { @@ -1822,49 +2082,61 @@ void BakedLightBaker::_bake_thread_func(void *arg) { BakedLightBaker *ble = (BakedLightBaker*)arg; - ble->rays_at_snap_time=ble->total_rays; - ble->snap_time=OS::get_singleton()->get_ticks_usec(); - while(!ble->bake_thread_exit) { - ble->throw_rays(1000); - uint64_t t=OS::get_singleton()->get_ticks_usec(); - if (t-ble->snap_time>1000000) { + ThreadStack thread_stack; - double time = (t-ble->snap_time)/1000000.0; + thread_stack.ray_stack = memnew_arr(uint32_t,ble->bvh_depth); + thread_stack.bvh_stack = memnew_arr(BVH*,ble->bvh_depth); + thread_stack.octant_stack = memnew_arr(uint32_t,ble->octree_depth*2 ); + thread_stack.octantptr_stack = memnew_arr(uint32_t,ble->octree_depth*2 ); - int rays=ble->total_rays-ble->rays_at_snap_time; - ble->rays_sec=int(rays/time); - ble->snap_time=OS::get_singleton()->get_ticks_usec(); - ble->rays_at_snap_time=ble->total_rays; - } + while(!ble->bake_thread_exit) { + + ble->throw_rays(thread_stack,1000); } + memdelete_arr(thread_stack.ray_stack ); + memdelete_arr(thread_stack.bvh_stack ); + memdelete_arr(thread_stack.octant_stack ); + memdelete_arr(thread_stack.octantptr_stack ); + } void BakedLightBaker::_start_thread() { - if (thread!=NULL) + if (threads.size()!=0) return; bake_thread_exit=false; - thread=Thread::create(_bake_thread_func,this); + int thread_count = EDITOR_DEF("light_baker/custom_bake_threads",0); + if (thread_count<=0 || thread_count>64) + thread_count=OS::get_singleton()->get_processor_count(); + + //thread_count=1; + threads.resize(thread_count); + for(int i=0;i<threads.size();i++) { + threads[i]=Thread::create(_bake_thread_func,this); + } } void BakedLightBaker::_stop_thread() { - if (thread==NULL) + if (threads.size()==0) return; bake_thread_exit=true; - Thread::wait_to_finish(thread); - thread=NULL; + for(int i=0;i<threads.size();i++) { + Thread::wait_to_finish(threads[i]); + } + threads.clear(); } void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) { uint8_t *ptr = &image[(y*width+x)*4]; - int lc = lights.size(); + //int lc = lights.size(); + double norm = 1.0/double(total_rays); Color color; @@ -1888,11 +2160,9 @@ void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int heigh for(int i=0;i<8;i++) { - for(int j=0;j<lc;j++) { - cols[i].x+=octant.light[j].accum[i][0]*p_norm_ptr[j]; - cols[i].y+=octant.light[j].accum[i][1]*p_norm_ptr[j]; - cols[i].z+=octant.light[j].accum[i][2]*p_norm_ptr[j]; - } + cols[i].x+=octant.light_accum[i][0]*norm; + cols[i].y+=octant.light_accum[i][1]*norm; + cols[i].z+=octant.light_accum[i][2]*norm; } @@ -2355,12 +2625,13 @@ void BakedLightBaker::clear() { memdelete_arr(octantptr_stack); if (bvh_stack) memdelete_arr(bvh_stack); - +/* + * ??? for(int i=0;i<octant_pool.size();i++) { - if (octant_pool[i].leaf) { - memdelete_arr( octant_pool[i].light ); - } Vector<double> norm_arr; - norm_arr.resize(lights.size()); + //if (octant_pool[i].leaf) { + // memdelete_arr( octant_pool[i].light ); + //} Vector<double> norm_arr; + //norm_arr.resize(lights.size()); for(int i=0;i<lights.size();i++) { norm_arr[i] = 1.0/get_normalization(i); @@ -2368,6 +2639,7 @@ void BakedLightBaker::clear() { const double *normptr=norm_arr.ptr(); } +*/ octant_pool.clear(); octant_pool_size=0; bvh=NULL; @@ -2388,8 +2660,9 @@ void BakedLightBaker::clear() { baked_octree_texture_h=0; paused=false; baking=false; - thread=NULL; + bake_thread_exit=false; + first_bake_to_map=true; baked_light=Ref<BakedLight>(); total_rays=0; @@ -2414,12 +2687,11 @@ BakedLightBaker::BakedLightBaker() { baked_octree_texture_h=0; paused=false; baking=false; - thread=NULL; + bake_thread_exit=false; - rays_at_snap_time=0; - snap_time=0; - rays_sec=0; total_rays=0; + first_bake_to_map=true; + linear_color=false; } diff --git a/tools/editor/plugins/baked_light_baker.h b/tools/editor/plugins/baked_light_baker.h index e0a9d91cd4..8fbeeddc6a 100644 --- a/tools/editor/plugins/baked_light_baker.h +++ b/tools/editor/plugins/baked_light_baker.h @@ -15,17 +15,19 @@ public: OCTANT_POOL_CHUNK=1000000 }; - struct OctantLight { + //struct OctantLight { - double accum[8][3]; - }; + // double accum[8][3]; + //}; struct Octant { bool leaf; AABB aabb; uint16_t texture_x; uint16_t texture_y; + int sampler_ofs; float normal_accum[8][3]; + double full_accum[3]; int parent; union { struct { @@ -33,7 +35,7 @@ public: float offset[3]; int bake_neighbour; bool first_neighbour; - OctantLight *light; + double light_accum[8][3]; }; int children[8]; }; @@ -234,32 +236,49 @@ public: Transform base_inv; int leaf_list; int octree_depth; + int bvh_depth; int cell_count; uint32_t *ray_stack; + BVH **bvh_stack; uint32_t *octant_stack; uint32_t *octantptr_stack; + + struct ThreadStack { + uint32_t *octant_stack; + uint32_t *octantptr_stack; + uint32_t *ray_stack; + BVH **bvh_stack; + }; + Map<Vector3,Vector3> endpoint_normal; Map<Vector3,uint64_t> endpoint_normal_bits; - BVH **bvh_stack; + float cell_size; float plot_size; //multiplied by cell size float octree_extra_margin; int max_bounces; - uint64_t total_rays; + int64_t total_rays; bool use_diffuse; bool use_specular; bool use_translucency; + bool linear_color; int baked_octree_texture_w; int baked_octree_texture_h; + int baked_light_texture_w; + int baked_light_texture_h; int lattice_size; float edge_damp; float normal_damp; + float tint; + float ao_radius; + float ao_strength; bool paused; bool baking; + bool first_bake_to_map; Map<Ref<Material>,MeshMaterial*> mat_map; Map<Ref<Texture>,MeshTexture*> tex_map; @@ -285,19 +304,16 @@ public: //void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,int p_octant=0); - void _plot_light(int p_light_index,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Plane& p_plane); + void _plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Color& p_tint_light,bool p_only_full,const Plane& p_plane); //void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light); - float _throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); + float _throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false); float total_light_area; - uint64_t rays_at_snap_time; - uint64_t snap_time; - int rays_sec; + Vector<Thread*> threads; - Thread *thread; bool bake_thread_exit; static void _bake_thread_func(void *arg); @@ -306,18 +322,20 @@ public: public: - void throw_rays(int p_amount); + void throw_rays(ThreadStack &thread_stack, int p_amount); double get_normalization(int p_light_idx) const; + double get_modifier(int p_light_idx) const; void bake(const Ref<BakedLight>& p_light,Node *p_base); bool is_baking(); void set_pause(bool p_pause); bool is_paused(); - int get_rays_sec() { return rays_sec; } + uint64_t get_rays_thrown() { return total_rays; } Error transfer_to_lightmaps(); - void update_octree_image(DVector<uint8_t> &p_image); + void update_octree_sampler(DVector<int> &p_sampler); + void update_octree_images(DVector<uint8_t> &p_octree,DVector<uint8_t> &p_light); Ref<BakedLight> get_baked_light() { return baked_light; } diff --git a/tools/editor/plugins/baked_light_baker_cmpxchg.cpp b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp new file mode 100644 index 0000000000..42d3fc5276 --- /dev/null +++ b/tools/editor/plugins/baked_light_baker_cmpxchg.cpp @@ -0,0 +1,85 @@ + +#include "typedefs.h" + + +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 + +void baked_light_baker_add_64f(double *dst,double value) { + + + union { + int64_t i; + double f; + } swapy; + + + while(true) { + swapy.f=*dst; + int64_t from = swapy.i; + swapy.f+=value; + int64_t to=swapy.i; + if (__sync_bool_compare_and_swap((int64_t*)dst,from,to)) + break; + } +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + while(!__sync_bool_compare_and_swap(dst,*dst,(*dst)+value)) {} + +} + +#elif defined(WINDOWS_ENABLED) + +#include "windows.h" + +void baked_light_baker_add_64f(double *dst,double value) { + + union { + int64_t i; + double f; + } swapy; + + + while(true) { + swapy.f=*dst; + int64_t from = swapy.i; + swapy.f+=value; + int64_t to=swapy.i; + int64_t result = InterlockedCompareExchange64((int64_t*)dst,to,from); + if (result==from) + break; + } + +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + while(true) { + int64_t from = *dst; + int64_t to = from+value; + int64_t result = InterlockedCompareExchange64(dst,to,from); + if (result==from) + break; + } +} + + +#else + +//in goder (the god of programmers) we trust +#warning seems this platform or compiler does not support safe cmpxchg, your baked lighting may be funny + +void baked_light_baker_add_64f(double *dst,double value) { + + *dst+=value; + +} + +void baked_light_baker_add_64i(int64_t *dst,int64_t value) { + + *dst+=value; + +} + +#endif diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp index 3d48f2e732..0f02899dc2 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.cpp +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -34,7 +34,7 @@ void BakedLightEditor::_node_removed(Node *p_node) { void BakedLightEditor::_notification(int p_option) { - if (p_option==NOTIFICATION_ENTER_SCENE) { + if (p_option==NOTIFICATION_ENTER_TREE) { button_bake->set_icon(get_icon("Bake","EditorIcons")); button_reset->set_icon(get_icon("Reload","EditorIcons")); @@ -111,7 +111,10 @@ void BakedLightEditor::_notification(int p_option) { #endif ERR_FAIL_COND(node->get_baked_light().is_null()); - baker->update_octree_image(octree_texture); + baker->update_octree_images(octree_texture,light_texture); + baker->update_octree_sampler(octree_sampler); + // print_line("sampler size: "+itos(octree_sampler.size()*4)); + #if 1 //debug Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,octree_texture); @@ -121,11 +124,19 @@ void BakedLightEditor::_notification(int p_option) { #endif - bake_info->set_text("rays/s: "+itos(baker->get_rays_sec())); + + + uint64_t rays_snap = baker->get_rays_thrown(); + int rays_sec = (rays_snap-last_rays_time)*1.0-(update_timeout); + last_rays_time=rays_snap; + + bake_info->set_text("rays/s: "+itos(rays_sec)); update_timeout=1; print_line("MSUPDATE: "+itos(OS::get_singleton()->get_ticks_msec()-t)); t=OS::get_singleton()->get_ticks_msec(); node->get_baked_light()->set_octree(octree_texture); + node->get_baked_light()->set_light(light_texture); + node->get_baked_light()->set_sampler_octree(octree_sampler); node->get_baked_light()->set_edited(true); print_line("MSSET: "+itos(OS::get_singleton()->get_ticks_msec()-t)); @@ -195,6 +206,9 @@ void BakedLightEditor::_bake_pressed() { baker->bake(node->get_baked_light(),node); node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE); update_timeout=0; + + last_rays_time=0; + set_process(true); } diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h index 7912bd92e5..27ab88d70b 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.h +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -23,6 +23,8 @@ class BakedLightEditor : public Control { float update_timeout; DVector<uint8_t> octree_texture; + DVector<uint8_t> light_texture; + DVector<int> octree_sampler; BakedLightBaker *baker; AcceptDialog *err_dialog; @@ -33,6 +35,9 @@ class BakedLightEditor : public Control { Button *button_make_lightmaps; Label *bake_info; + uint64_t last_rays_time; + + BakedLightInstance *node; diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index e2944af422..32d5641e68 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -36,6 +36,110 @@ #include "globals.h" #include "os/input.h" #include "tools/editor/editor_settings.h" +#include "scene/gui/grid_container.h" + +class SnapDialog : public ConfirmationDialog { + + OBJ_TYPE(SnapDialog,ConfirmationDialog); + +protected: + friend class CanvasItemEditor; + SpinBox *grid_offset_x; + SpinBox *grid_offset_y; + SpinBox *grid_step_x; + SpinBox *grid_step_y; + SpinBox *rotation_offset; + SpinBox *rotation_step; + +public: + SnapDialog() : ConfirmationDialog() { + const int SPIN_BOX_GRID_RANGE = 256; + const int SPIN_BOX_ROTATION_RANGE = 360; + Label *label; + VBoxContainer *container; + GridContainer *child_container; + + set_title("Configure Snap"); + get_ok()->set_text("Close"); + container = memnew(VBoxContainer); + add_child(container); + + child_container = memnew(GridContainer); + child_container->set_columns(3); + container->add_child(child_container); + + label = memnew(Label); + label->set_text("Grid Offset:"); + child_container->add_child(label); + grid_offset_x=memnew(SpinBox); + grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE); + grid_offset_x->set_max(SPIN_BOX_GRID_RANGE); + grid_offset_x->set_suffix("px"); + child_container->add_child(grid_offset_x); + grid_offset_y=memnew(SpinBox); + grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE); + grid_offset_y->set_max(SPIN_BOX_GRID_RANGE); + grid_offset_y->set_suffix("px"); + child_container->add_child(grid_offset_y); + + label = memnew(Label); + label->set_text("Grid Step:"); + child_container->add_child(label); + grid_step_x=memnew(SpinBox); + grid_step_x->set_min(-SPIN_BOX_GRID_RANGE); + grid_step_x->set_max(SPIN_BOX_GRID_RANGE); + grid_step_x->set_suffix("px"); + child_container->add_child(grid_step_x); + grid_step_y=memnew(SpinBox); + grid_step_y->set_min(-SPIN_BOX_GRID_RANGE); + grid_step_y->set_max(SPIN_BOX_GRID_RANGE); + grid_step_y->set_suffix("px"); + child_container->add_child(grid_step_y); + + container->add_child(memnew(HSeparator)); + + child_container = memnew(GridContainer); + child_container->set_columns(2); + container->add_child(child_container); + + label = memnew(Label); + label->set_text("Rotation Offset:"); + child_container->add_child(label); + rotation_offset=memnew(SpinBox); + rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE); + rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE); + rotation_offset->set_suffix("deg"); + child_container->add_child(rotation_offset); + + label = memnew(Label); + label->set_text("Rotation Step:"); + child_container->add_child(label); + rotation_step=memnew(SpinBox); + rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE); + rotation_step->set_max(SPIN_BOX_ROTATION_RANGE); + rotation_step->set_suffix("deg"); + child_container->add_child(rotation_step); + } + + void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) { + grid_offset_x->set_val(p_grid_offset.x); + grid_offset_y->set_val(p_grid_offset.y); + grid_step_x->set_val(p_grid_step.x); + grid_step_y->set_val(p_grid_step.y); + rotation_offset->set_val(p_rotation_offset * (180 / Math_PI)); + rotation_step->set_val(p_rotation_step * (180 / Math_PI)); + } + + void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) { + p_grid_offset.x = grid_offset_x->get_val(); + p_grid_offset.y = grid_offset_y->get_val(); + p_grid_step.x = grid_step_x->get_val(); + p_grid_step.y = grid_step_y->get_val(); + p_rotation_offset = rotation_offset->get_val() / (180 / Math_PI); + p_rotation_step = rotation_step->get_val() / (180 / Math_PI); + } +}; + void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) { if (!is_visible()) @@ -75,9 +179,24 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) { return memnew( CanvasItemEditorSelectedItem ); } -bool CanvasItemEditor::is_snap_active() const { +inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) { + float offset = p_snap_relative ? p_start : p_offset; + return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target; +} + +Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const { + if (snap_grid) { + p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x); + p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y); + } + if (snap_pixel) + p_target = p_target.snapped(Size2(1, 1)); - return edit_menu->get_popup()->is_item_checked(edit_menu->get_popup()->get_item_index(SNAP_USE)); + return p_target; +} + +float CanvasItemEditor::snap_angle(float p_target, float p_start) const { + return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target; } Dictionary CanvasItemEditor::get_state() const { @@ -86,9 +205,15 @@ Dictionary CanvasItemEditor::get_state() const { state["zoom"]=zoom; state["ofs"]=Point2(h_scroll->get_val(),v_scroll->get_val()); // state["ofs"]=-transform.get_origin(); - state["use_snap"]=is_snap_active(); - state["snap"]=snap; - state["pixel_snap"]=pixel_snap; + state["snap_offset"]=snap_offset; + state["snap_step"]=snap_step; + state["snap_rotation_offset"]=snap_rotation_offset; + state["snap_rotation_step"]=snap_rotation_step; + state["snap_grid"]=snap_grid; + state["snap_show_grid"]=snap_show_grid; + state["snap_rotation"]=snap_rotation; + state["snap_relative"]=snap_relative; + state["snap_pixel"]=snap_pixel; return state; } void CanvasItemEditor::set_state(const Dictionary& p_state){ @@ -105,19 +230,50 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){ v_scroll->set_val(ofs.y); } - if (state.has("use_snap")) { + if (state.has("snap_step")) { + snap_step=state["snap_step"]; + } + + if (state.has("snap_offset")) { + snap_offset=state["snap_offset"]; + } + + if (state.has("snap_rotation_step")) { + snap_rotation_step=state["snap_rotation_step"]; + } + + if (state.has("snap_rotation_offset")) { + snap_rotation_offset=state["snap_rotation_offset"]; + } + + if (state.has("snap_grid")) { + snap_grid=state["snap_grid"]; int idx = edit_menu->get_popup()->get_item_index(SNAP_USE); - edit_menu->get_popup()->set_item_checked(idx,state["use_snap"]); + edit_menu->get_popup()->set_item_checked(idx,snap_grid); } - if (state.has("snap")) { - snap=state["snap"]; + if (state.has("snap_show_grid")) { + snap_show_grid=state["snap_show_grid"]; + int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID); + edit_menu->get_popup()->set_item_checked(idx,snap_show_grid); } - if (state.has("pixel_snap")) { - pixel_snap=state["pixel_snap"]; + if (state.has("snap_rotation")) { + snap_rotation=state["snap_rotation"]; + int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + edit_menu->get_popup()->set_item_checked(idx,snap_rotation); + } + + if (state.has("snap_relative")) { + snap_relative=state["snap_relative"]; + int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE); + edit_menu->get_popup()->set_item_checked(idx,snap_relative); + } + + if (state.has("snap_pixel")) { + snap_pixel=state["snap_pixel"]; int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - edit_menu->get_popup()->set_item_checked(idx,pixel_snap); + edit_menu->get_popup()->set_item_checked(idx,snap_pixel); } } @@ -286,9 +442,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -300,7 +454,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE Vector2 drag = p_dir; if (p_snap) - drag*=snap; + drag*=snap_step; undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state()); @@ -347,9 +501,7 @@ Point2 CanvasItemEditor::_find_topleftmost_point() { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; @@ -377,9 +529,7 @@ int CanvasItemEditor::get_item_count() { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; ic++; @@ -398,9 +548,7 @@ CanvasItem *CanvasItemEditor::get_single_item() { for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; if (single_item) @@ -554,6 +702,11 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *c) { } +void CanvasItemEditor::_snap_changed() { + ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); + viewport->update(); +} + void CanvasItemEditor::_dialog_value_changed(double) { if (updating_value_dialog) @@ -561,11 +714,6 @@ void CanvasItemEditor::_dialog_value_changed(double) { switch(last_option) { - case SNAP_CONFIGURE: { - - snap=dialog_val->get_val(); - viewport->update(); - } break; case ZOOM_SET: { zoom=dialog_val->get_val()/100.0; @@ -661,9 +809,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); @@ -735,9 +881,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -943,9 +1087,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -1055,7 +1197,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { editor_selection->clear(); editor_selection->add_node(c); //reselect - if (get_scene()->is_editor_hint()) { + if (get_tree()->is_editor_hint()) { editor->call("edit_node",c); } @@ -1068,9 +1210,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -1126,9 +1266,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -1153,39 +1291,21 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { if (drag==DRAG_ROTATE) { Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin(); - - Matrix32 rot; - rot.elements[1] = (dfrom - center).normalized(); - rot.elements[0] = rot.elements[1].tangent(); - float ang = rot.xform_inv(dto-center).atan2(); - canvas_item->edit_rotate(ang); - display_rotate_to = dto; - display_rotate_from = center; + if (Node2D *node = canvas_item->cast_to<Node2D>()) { + Matrix32 rot; + rot.elements[1] = (dfrom - center).normalized(); + rot.elements[0] = rot.elements[1].tangent(); + node->set_rot(snap_angle(rot.xform_inv(dto-center).atan2(), node->get_rot())); + display_rotate_to = dto; + display_rotate_from = center; + viewport->update(); + } continue; } - if (pixel_snap || (is_snap_active() && snap>0)) { - - if (drag!=DRAG_ALL) { - dfrom=drag_point_from; - dto=snapify(dto); - } else { - - Vector2 newpos = drag_point_from + (dto-dfrom); - Vector2 disp; - if (!is_snap_active() || snap<1) { - - disp.x = Math::fposmod(newpos.x,1); - disp.y = Math::fposmod(newpos.y,1); - - } else { - disp.x = Math::fposmod(newpos.x,snap); - disp.y = Math::fposmod(newpos.y,snap); - } - dto-=disp; - } - } + dfrom = drag_point_from; + dto = snap_point(dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0)), drag_point_from); Vector2 drag_vector = canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - @@ -1293,8 +1413,6 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { - - if (!dragging_bone) { local_rect.pos=begin; @@ -1477,32 +1595,32 @@ void CanvasItemEditor::_viewport_draw() { _update_scrollbars(); RID ci=viewport->get_canvas_item(); - if (snap>0 && is_snap_active() && true ) { - + if (snap_show_grid) { Size2 s = viewport->get_size(); - int last_cell; Matrix32 xform = transform.affine_inverse(); - for(int i=0;i<s.width;i++) { - int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(i,0)).x/snap)); - if (i==0) + if (snap_step.x!=0) { + for(int i=0;i<s.width;i++) { + int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3)); last_cell=cell; - if (last_cell!=cell) - viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3)); - last_cell=cell; + } } - for(int i=0;i<s.height;i++) { - - int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(0,i)).y/snap)); - if (i==0) + if (snap_step.y!=0) { + for(int i=0;i<s.height;i++) { + int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3)); last_cell=cell; - if (last_cell!=cell) - viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3)); - last_cell=cell; + } } - } if (viewport->has_focus()) { @@ -1530,9 +1648,7 @@ void CanvasItemEditor::_viewport_draw() { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -1749,9 +1865,7 @@ void CanvasItemEditor::_notification(int p_what) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); @@ -1791,7 +1905,7 @@ void CanvasItemEditor::_notification(int p_what) { } } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { select_sb->set_texture( get_icon("EditorRect2D","EditorIcons") ); for(int i=0;i<4;i++) { @@ -1814,7 +1928,7 @@ void CanvasItemEditor::_notification(int p_what) { if (p_what==NOTIFICATION_READY) { - get_scene()->connect("node_removed",this,"_node_removed"); + get_tree()->connect("node_removed",this,"_node_removed"); } if (p_what==NOTIFICATION_DRAW) { @@ -1996,59 +2110,40 @@ void CanvasItemEditor::_update_scroll(float) { } -Point2 CanvasItemEditor::snapify(const Point2& p_pos) const { - - bool active=is_snap_active(); - - Vector2 pos = p_pos; - - if (!active || snap<1) { - - if (pixel_snap) { - - pos.x=Math::stepify(pos.x,1); - pos.y=Math::stepify(pos.y,1); - } - - return pos; - } - - - pos.x=Math::stepify(pos.x,snap); - pos.y=Math::stepify(pos.y,snap); - return pos; - - -} - - void CanvasItemEditor::_popup_callback(int p_op) { last_option=MenuOption(p_op); switch(p_op) { case SNAP_USE: { - + snap_grid = !snap_grid; int idx = edit_menu->get_popup()->get_item_index(SNAP_USE); - edit_menu->get_popup()->set_item_checked( idx,!edit_menu->get_popup()->is_item_checked(0)); + edit_menu->get_popup()->set_item_checked(idx,snap_grid); + } break; + case SNAP_SHOW_GRID: { + snap_show_grid = !snap_show_grid; + int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID); + edit_menu->get_popup()->set_item_checked(idx,snap_show_grid); viewport->update(); } break; + case SNAP_USE_ROTATION: { + snap_rotation = !snap_rotation; + int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + edit_menu->get_popup()->set_item_checked(idx,snap_rotation); + } break; + case SNAP_RELATIVE: { + snap_relative = !snap_relative; + int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE); + edit_menu->get_popup()->set_item_checked(idx,snap_relative); + } break; case SNAP_USE_PIXEL: { - pixel_snap = ! pixel_snap; + snap_pixel = !snap_pixel; int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - edit_menu->get_popup()->set_item_checked(idx,pixel_snap); + edit_menu->get_popup()->set_item_checked(idx,snap_pixel); } break; case SNAP_CONFIGURE: { - updating_value_dialog=true; - - dialog_label->set_text("Snap (Pixels):"); - dialog_val->set_min(1); - dialog_val->set_step(1); - dialog_val->set_max(4096); - dialog_val->set_val(snap); - value_dialog->popup_centered(Size2(200,85)); - updating_value_dialog=false; - + ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); + snap_dialog->popup_centered(Size2(200,160)); } break; case ZOOM_IN: { zoom=zoom*(1.0/0.5); @@ -2092,9 +2187,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; canvas_item->set_meta("_edit_lock_",true); @@ -2109,9 +2202,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; @@ -2129,9 +2220,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; canvas_item->set_meta("_edit_group_",true); @@ -2146,9 +2235,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; canvas_item->set_meta("_edit_group_",Variant()); @@ -2166,9 +2253,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; @@ -2236,9 +2321,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; if (canvas_item->cast_to<Node2D>()) { @@ -2307,7 +2390,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case ANIM_INSERT_ROT: { - key_pos = key_rot_button->is_pressed(); + key_rot = key_rot_button->is_pressed(); } break; case ANIM_INSERT_SCALE: { @@ -2348,9 +2431,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; @@ -2400,9 +2481,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; if (canvas_item->cast_to<Node2D>()) { @@ -2528,9 +2607,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); - if (!canvas_item) - continue; - if (!canvas_item->is_visible()) + if (!canvas_item || !canvas_item->is_visible()) continue; @@ -2604,6 +2681,7 @@ void CanvasItemEditor::_bind_methods() { ObjectTypeDB::bind_method("_unhandled_key_input",&CanvasItemEditor::_unhandled_key_input); ObjectTypeDB::bind_method("_viewport_draw",&CanvasItemEditor::_viewport_draw); ObjectTypeDB::bind_method("_viewport_input_event",&CanvasItemEditor::_viewport_input_event); + ObjectTypeDB::bind_method("_snap_changed",&CanvasItemEditor::_snap_changed); ADD_SIGNAL( MethodInfo("item_lock_status_changed") ); ADD_SIGNAL( MethodInfo("item_group_status_changed") ); @@ -2683,6 +2761,16 @@ void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { hb->add_child(p_control); } +HSplitContainer *CanvasItemEditor::get_palette_split() { + + return palette_split; +} + +VSplitContainer *CanvasItemEditor::get_bottom_split() { + + return bottom_split; +} + CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { tool = TOOL_SELECT; @@ -2697,15 +2785,24 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { add_child( hb ); hb->set_area_as_parent_rect(); + bottom_split = memnew( VSplitContainer ); + bottom_split->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(bottom_split); + + palette_split = memnew( HSplitContainer); + palette_split->set_v_size_flags(SIZE_EXPAND_FILL); + bottom_split->add_child(palette_split); + Control *vp_base = memnew (Control); - add_child(vp_base); vp_base->set_v_size_flags(SIZE_EXPAND_FILL); + palette_split->add_child(vp_base); Control *vp = memnew (Control); vp_base->add_child(vp); vp->set_area_as_parent_rect(); vp->add_child(p_editor->get_scene_root()); + viewport = memnew( Control ); vp_base->add_child(viewport); viewport->set_area_as_parent_rect(); @@ -2790,6 +2887,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { PopupMenu *p; p = edit_menu->get_popup(); p->add_check_item("Use Snap",SNAP_USE); + p->add_check_item("Show Grid",SNAP_SHOW_GRID); + p->add_check_item("Use Rotation Snap",SNAP_USE_ROTATION); + p->add_check_item("Snap Relative",SNAP_RELATIVE); p->add_item("Configure Snap..",SNAP_CONFIGURE); p->add_separator(); p->add_check_item("Use Pixel Snap",SNAP_USE_PIXEL); @@ -2878,7 +2978,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_separator(); p->add_item("Copy Pose",ANIM_COPY_POSE); p->add_item("Paste Pose",ANIM_PASTE_POSE); - p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_ALT|KEY_K); + p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_SHIFT|KEY_K); + + snap_dialog = memnew(SnapDialog); + snap_dialog->connect("confirmed",this,"_snap_changed"); + add_child(snap_dialog); value_dialog = memnew( AcceptDialog ); value_dialog->set_title("Set a Value"); @@ -2904,7 +3008,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_scale=false; zoom=1; - snap=10; + snap_offset=Vector2(0, 0); + snap_step=Vector2(10, 10); + snap_rotation_offset=0; + snap_rotation_step=15 / (180 / Math_PI); + snap_grid=false; + snap_show_grid=false; + snap_rotation=false; + snap_pixel=false; updating_value_dialog=false; box_selecting=false; //zoom=0.5; @@ -2912,7 +3023,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { editor->get_animation_editor()->connect("keying_changed",this,"_keying_changed"); set_process_unhandled_key_input(true); can_move_pivot=false; - pixel_snap=false; drag=DRAG_NONE; } diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 15ac7b1bb3..f25296abdc 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -75,6 +75,9 @@ class CanvasItemEditor : public VBoxContainer { enum MenuOption { SNAP_USE, + SNAP_SHOW_GRID, + SNAP_USE_ROTATION, + SNAP_RELATIVE, SNAP_CONFIGURE, SNAP_USE_PIXEL, ZOOM_IN, @@ -143,8 +146,15 @@ class CanvasItemEditor : public VBoxContainer { Matrix32 transform; float zoom; - int snap; - bool pixel_snap; + Vector2 snap_offset; + Vector2 snap_step; + float snap_rotation_step; + float snap_rotation_offset; + bool snap_grid; + bool snap_show_grid; + bool snap_rotation; + bool snap_relative; + bool snap_pixel; bool box_selecting; Point2 box_selecting_to; bool key_pos; @@ -247,6 +257,8 @@ class CanvasItemEditor : public VBoxContainer { CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform); void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items); + ConfirmationDialog *snap_dialog; + AcceptDialog *value_dialog; Label *dialog_label; SpinBox *dialog_val; @@ -261,7 +273,6 @@ class CanvasItemEditor : public VBoxContainer { DragType _find_drag_type(const Matrix32& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point); - Point2 snapify(const Point2& p_pos) const; void _popup_callback(int p_op); bool updating_scroll; void _update_scroll(float); @@ -271,6 +282,7 @@ class CanvasItemEditor : public VBoxContainer { void _append_canvas_item(CanvasItem *p_item); void _dialog_value_changed(double); + void _snap_changed(); UndoRedo *undo_redo; Point2 _find_topleftmost_point(); @@ -289,6 +301,10 @@ class CanvasItemEditor : public VBoxContainer { void _viewport_input_event(const InputEvent& p_event); void _viewport_draw(); + + HSplitContainer *palette_split; + VSplitContainer *bottom_split; + friend class CanvasItemEditorPlugin; protected: @@ -330,8 +346,8 @@ protected: static CanvasItemEditor *singleton; public: - bool is_snap_active() const; - int get_snap() const { return snap; } + Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const; + float snap_angle(float p_target, float p_start = 0) const; Matrix32 get_canvas_transform() const { return transform; } @@ -341,6 +357,9 @@ public: void add_control_to_menu_panel(Control *p_control); + HSplitContainer *get_palette_split(); + VSplitContainer *get_bottom_split(); + Control *get_viewport_control() { return viewport; } diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp index 080ed7d11c..a533c6aa1e 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -4,6 +4,7 @@ #include "os/file_access.h" #include "tools/editor/editor_settings.h" + void CollisionPolygon2DEditor::_notification(int p_what) { switch(p_what) { @@ -13,7 +14,7 @@ void CollisionPolygon2DEditor::_notification(int p_what) { button_create->set_icon( get_icon("Edit","EditorIcons")); button_edit->set_icon( get_icon("MovePoint","EditorIcons")); button_edit->set_pressed(true); - + get_tree()->connect("node_removed",this,"_node_removed"); } break; case NOTIFICATION_FIXED_PROCESS: { @@ -28,22 +29,12 @@ void CollisionPolygon2DEditor::_node_removed(Node *p_node) { if(p_node==node) { node=NULL; hide(); + canvas_item_editor->get_viewport_control()->update(); } } -Vector2 CollisionPolygon2DEditor::snap_point(const Vector2& p_point) const { - - if (canvas_item_editor->is_snap_active()) { - - return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap()); - - } else { - return p_point; - } -} - void CollisionPolygon2DEditor::_menu_option(int p_option) { switch(p_option) { @@ -83,6 +74,9 @@ void CollisionPolygon2DEditor::_wip_close() { bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) { + if (!node) + return false; + switch(p_event.type) { case InputEvent::MOUSE_BUTTON: { @@ -94,7 +88,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) { Vector2 gpoint = Point2(mb.x,mb.y); Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint=snap_point(cpoint); + cpoint=canvas_item_editor->snap_point(cpoint); cpoint = node->get_global_transform().affine_inverse().xform(cpoint); Vector<Vector2> poly = node->get_polygon(); @@ -297,7 +291,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) { Vector2 gpoint = Point2(mm.x,mm.y); Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint=snap_point(cpoint); + cpoint=canvas_item_editor->snap_point(cpoint); edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); canvas_item_editor->get_viewport_control()->update(); @@ -364,6 +358,7 @@ void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active=false; edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); } else { node=NULL; @@ -379,6 +374,7 @@ void CollisionPolygon2DEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_menu_option"),&CollisionPolygon2DEditor::_menu_option); ObjectTypeDB::bind_method(_MD("_canvas_draw"),&CollisionPolygon2DEditor::_canvas_draw); + ObjectTypeDB::bind_method(_MD("_node_removed"),&CollisionPolygon2DEditor::_node_removed); } @@ -393,11 +389,13 @@ CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) { add_child(button_create); button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE)); button_create->set_toggle_mode(true); + button_create->set_tooltip("Create a new polygon from scratch"); button_edit = memnew( ToolButton ); add_child(button_edit); button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT)); button_edit->set_toggle_mode(true); + button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."); //add_constant_override("separation",0); diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h index 052019b6c5..f34405b355 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h @@ -53,7 +53,6 @@ protected: static void _bind_methods(); public: - Vector2 snap_point(const Vector2& p_point) const; bool forward_input_event(const InputEvent& p_event); void edit(Node *p_collision_polygon); CollisionPolygon2DEditor(EditorNode *p_editor); diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp index 16b9622312..126328bac3 100644 --- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_editor_plugin.cpp @@ -31,6 +31,8 @@ #include "os/file_access.h" #include "tools/editor/editor_settings.h" #include "scene/3d/camera.h" +#include "canvas_item_editor_plugin.h" + void CollisionPolygonEditor::_notification(int p_what) { switch(p_what) { @@ -40,7 +42,7 @@ void CollisionPolygonEditor::_notification(int p_what) { button_create->set_icon( get_icon("Edit","EditorIcons")); button_edit->set_icon( get_icon("MovePoint","EditorIcons")); button_edit->set_pressed(true); - get_scene()->connect("node_removed",this,"_node_removed"); + get_tree()->connect("node_removed",this,"_node_removed"); } break; @@ -68,19 +70,6 @@ void CollisionPolygonEditor::_node_removed(Node *p_node) { } -Vector2 CollisionPolygonEditor::snap_point(const Vector2& p_point) const { - - return p_point; - /* - if (canvas_item_editor->is_snap_active()) { - - return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap()); - - } else { - return p_point; - } ??? */ -} - void CollisionPolygonEditor::_menu_option(int p_option) { switch(p_option) { @@ -120,6 +109,8 @@ void CollisionPolygonEditor::_wip_close() { bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) { + if (!node) + return false; Transform gt = node->get_global_transform(); float depth = node->get_depth()*0.5; @@ -146,7 +137,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const Vector2 cpoint(spoint.x,spoint.y); - //cpoint=snap_point(cpoint); snap? + cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint); Vector<Vector2> poly = node->get_polygon(); @@ -360,7 +351,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const Vector2 cpoint(spoint.x,spoint.y); - //cpoint=snap_point(cpoint); + cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint); edited_point_pos = cpoint; _polygon_draw(); diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.h b/tools/editor/plugins/collision_polygon_editor_plugin.h index 54b0706149..1c12ee0041 100644 --- a/tools/editor/plugins/collision_polygon_editor_plugin.h +++ b/tools/editor/plugins/collision_polygon_editor_plugin.h @@ -90,7 +90,6 @@ protected: static void _bind_methods(); public: - Vector2 snap_point(const Vector2& p_point) const; virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event); void edit(Node *p_collision_polygon); CollisionPolygonEditor(EditorNode *p_editor); diff --git a/tools/editor/plugins/item_list_editor_plugin.cpp b/tools/editor/plugins/item_list_editor_plugin.cpp index a059470cec..a8b34ef503 100644 --- a/tools/editor/plugins/item_list_editor_plugin.cpp +++ b/tools/editor/plugins/item_list_editor_plugin.cpp @@ -157,7 +157,7 @@ void ItemListEditor::_add_pressed() { void ItemListEditor::_notification(int p_notification) { - if (p_notification==NOTIFICATION_ENTER_SCENE) { + if (p_notification==NOTIFICATION_ENTER_TREE) { add_button->set_icon(get_icon("Add","EditorIcons")); del_button->set_icon(get_icon("Del","EditorIcons")); @@ -210,6 +210,7 @@ void ItemListEditor::_bind_methods() { } bool ItemListEditor::handles(Object *p_object) const { + return false; for(int i=0;i<item_plugins.size();i++) { if (item_plugins[i]->handles(p_object)) { return true; diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp new file mode 100644 index 0000000000..bf882857d9 --- /dev/null +++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -0,0 +1,491 @@ +#include "light_occluder_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "os/file_access.h" +#include "tools/editor/editor_settings.h" + +void LightOccluder2DEditor::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_READY: { + + button_create->set_icon( get_icon("Edit","EditorIcons")); + button_edit->set_icon( get_icon("MovePoint","EditorIcons")); + button_edit->set_pressed(true); + get_tree()->connect("node_removed",this,"_node_removed"); + create_poly->connect("confirmed",this,"_create_poly"); + + } break; + case NOTIFICATION_FIXED_PROCESS: { + + + } break; + } + +} +void LightOccluder2DEditor::_node_removed(Node *p_node) { + + if(p_node==node) { + node=NULL; + hide(); + canvas_item_editor->get_viewport_control()->update(); + } + +} + + +void LightOccluder2DEditor::_menu_option(int p_option) { + + switch(p_option) { + + case MODE_CREATE: { + + mode=MODE_CREATE; + button_create->set_pressed(true); + button_edit->set_pressed(false); + } break; + case MODE_EDIT: { + + mode=MODE_EDIT; + button_create->set_pressed(false); + button_edit->set_pressed(true); + } break; + + } +} + +void LightOccluder2DEditor::_wip_close(bool p_closed) { + + undo_redo->create_action("Create Poly"); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon()); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed()); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed); + + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + wip.clear(); + wip_active=false; + mode=MODE_EDIT; + button_edit->set_pressed(true); + button_create->set_pressed(false); + edited_point=-1; +} + +bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) { + + + if (!node) + return false; + + if (node->get_occluder_polygon().is_null()) { + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?"); + create_poly->popup_centered_minsize(); + } + return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1); + } + switch(p_event.type) { + + case InputEvent::MOUSE_BUTTON: { + + const InputEventMouseButton &mb=p_event.mouse_button; + + Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + + Vector2 gpoint = Point2(mb.x,mb.y); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint=canvas_item_editor->snap_point(cpoint); + cpoint = node->get_global_transform().affine_inverse().xform(cpoint); + + Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon()); + + //first check if a point is to be added (segment split) + real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8); + + switch(mode) { + + + case MODE_CREATE: { + + if (mb.button_index==BUTTON_LEFT && mb.pressed) { + + + if (!wip_active) { + + wip.clear(); + wip.push_back( cpoint ); + wip_active=true; + edited_point_pos=cpoint; + canvas_item_editor->get_viewport_control()->update(); + edited_point=1; + return true; + } else { + + + if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) { + //wip closed + _wip_close(true); + + return true; + } else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) { + //wip closed + _wip_close(false); + return true; + + } else { + + wip.push_back( cpoint ); + edited_point=wip.size(); + canvas_item_editor->get_viewport_control()->update(); + return true; + + //add wip point + } + } + } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) { + _wip_close(true); + } + + + + } break; + + case MODE_EDIT: { + + if (mb.button_index==BUTTON_LEFT) { + if (mb.pressed) { + + if (mb.mod.control) { + + + if (poly.size() < 3) { + + undo_redo->create_action("Edit Poly"); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + poly.push_back(cpoint); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + return true; + } + + //search edges + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + for(int i=0;i<poly.size();i++) { + + Vector2 points[2] ={ xform.xform(poly[i]), + xform.xform(poly[(i+1)%poly.size()]) }; + + Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points); + if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2) + continue; //not valid to reuse point + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_idx=i; + } + + + } + + if (closest_idx>=0) { + + pre_move_edit=poly; + poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos)); + edited_point=closest_idx+1; + edited_point_pos=xform.affine_inverse().xform(closest_pos); + node->get_occluder_polygon()->set_polygon(Variant(poly)); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } else { + + //look for points to move + + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + for(int i=0;i<poly.size();i++) { + + Vector2 cp =xform.xform(poly[i]); + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_idx=i; + } + + } + + if (closest_idx>=0) { + + pre_move_edit=poly; + edited_point=closest_idx; + edited_point_pos=xform.affine_inverse().xform(closest_pos); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } + } else { + + if (edited_point!=-1) { + + //apply + + ERR_FAIL_INDEX_V(edited_point,poly.size(),false); + poly[edited_point]=edited_point_pos; + undo_redo->create_action("Edit Poly"); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + + edited_point=-1; + return true; + } + } + } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) { + + + + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + for(int i=0;i<poly.size();i++) { + + Vector2 cp =xform.xform(poly[i]); + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_idx=i; + } + + } + + if (closest_idx>=0) { + + + undo_redo->create_action("Edit Poly (Remove Point)"); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + poly.remove(closest_idx); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + return true; + } + + } + + + + } break; + } + + + + } break; + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_event.mouse_motion; + + if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) { + + Vector2 gpoint = Point2(mm.x,mm.y); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint=canvas_item_editor->snap_point(cpoint); + edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); + + canvas_item_editor->get_viewport_control()->update(); + + } + + } break; + } + + return false; +} +void LightOccluder2DEditor::_canvas_draw() { + + if (!node || !node->get_occluder_polygon().is_valid()) + return; + + Control *vpc = canvas_item_editor->get_viewport_control(); + + Vector<Vector2> poly; + + if (wip_active) + poly=wip; + else + poly=Variant(node->get_occluder_polygon()->get_polygon()); + + + Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + Ref<Texture> handle= get_icon("EditorHandle","EditorIcons"); + + int len = poly.size(); + + for(int i=0;i<poly.size();i++) { + + + Vector2 p,p2; + p = i==edited_point ? edited_point_pos : poly[i]; + if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point)) + p2=edited_point_pos; + else + p2 = poly[(i+1)%poly.size()]; + + Vector2 point = xform.xform(p); + Vector2 next_point = xform.xform(p2); + + Color col=Color(1,0.3,0.1,0.8); + + if (i==poly.size()-1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) { + + } else { + vpc->draw_line(point,next_point,col,2); + } + vpc->draw_texture(handle,point-handle->get_size()*0.5); + } +} + + + +void LightOccluder2DEditor::edit(Node *p_collision_polygon) { + + if (!canvas_item_editor) { + canvas_item_editor=CanvasItemEditor::get_singleton(); + } + + if (p_collision_polygon) { + + node=p_collision_polygon->cast_to<LightOccluder2D>(); + if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw"); + wip.clear(); + wip_active=false; + edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); + } else { + node=NULL; + + if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw"); + + } + +} + +void LightOccluder2DEditor::_create_poly() { + + if (!node) + return; + undo_redo->create_action("Create Occluder Polygon"); + undo_redo->add_do_method(node,"set_occluder_polygon",Ref<OccluderPolygon2D>(memnew( OccluderPolygon2D))); + undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF())); + undo_redo->commit_action(); +} + +void LightOccluder2DEditor::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_menu_option"),&LightOccluder2DEditor::_menu_option); + ObjectTypeDB::bind_method(_MD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw); + ObjectTypeDB::bind_method(_MD("_node_removed"),&LightOccluder2DEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_create_poly"),&LightOccluder2DEditor::_create_poly); + +} + + +LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) { + + canvas_item_editor=NULL; + editor=p_editor; + undo_redo = editor->get_undo_redo(); + + add_child( memnew( VSeparator )); + button_create = memnew( ToolButton ); + add_child(button_create); + button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE)); + button_create->set_toggle_mode(true); + button_create->set_tooltip("Create a new polygon from scratch"); + + button_edit = memnew( ToolButton ); + add_child(button_edit); + button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT)); + button_edit->set_toggle_mode(true); + button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."); + + create_poly = memnew( ConfirmationDialog ); + add_child(create_poly); + create_poly->get_ok()->set_text("Create"); + + + //add_constant_override("separation",0); + +#if 0 + options = memnew( MenuButton ); + add_child(options); + options->set_area_as_parent_rect(); + options->set_text("Polygon"); + //options->get_popup()->add_item("Parse BBCODE",PARSE_BBCODE); + options->get_popup()->connect("item_pressed", this,"_menu_option"); +#endif + + mode = MODE_EDIT; + wip_active=false; + +} + + +void LightOccluder2DEditorPlugin::edit(Object *p_object) { + + collision_polygon_editor->edit(p_object->cast_to<Node>()); +} + +bool LightOccluder2DEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("LightOccluder2D"); +} + +void LightOccluder2DEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + collision_polygon_editor->show(); + } else { + + collision_polygon_editor->hide(); + collision_polygon_editor->edit(NULL); + } + +} + +LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) { + + editor=p_node; + collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); + + collision_polygon_editor->hide(); + + + +} + + +LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin() +{ +} + diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.h b/tools/editor/plugins/light_occluder_2d_editor_plugin.h new file mode 100644 index 0000000000..5fb5631d05 --- /dev/null +++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.h @@ -0,0 +1,87 @@ +#ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H +#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H + + + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/2d/light_occluder_2d.h" +#include "scene/gui/tool_button.h" +#include "scene/gui/button_group.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class CanvasItemEditor; + +class LightOccluder2DEditor : public HBoxContainer { + + OBJ_TYPE(LightOccluder2DEditor, HBoxContainer ); + + UndoRedo *undo_redo; + enum Mode { + + MODE_CREATE, + MODE_EDIT, + + }; + + Mode mode; + + ToolButton *button_create; + ToolButton *button_edit; + + CanvasItemEditor *canvas_item_editor; + EditorNode *editor; + Panel *panel; + LightOccluder2D *node; + MenuButton *options; + + int edited_point; + Vector2 edited_point_pos; + Vector<Vector2> pre_move_edit; + Vector<Vector2> wip; + bool wip_active; + + ConfirmationDialog *create_poly; + + void _wip_close(bool p_closed); + void _canvas_draw(); + void _menu_option(int p_option); + void _create_poly(); + +protected: + void _notification(int p_what); + void _node_removed(Node *p_node); + static void _bind_methods(); +public: + + Vector2 snap_point(const Vector2& p_point) const; + bool forward_input_event(const InputEvent& p_event); + void edit(Node *p_collision_polygon); + LightOccluder2DEditor(EditorNode *p_editor); +}; + +class LightOccluder2DEditorPlugin : public EditorPlugin { + + OBJ_TYPE( LightOccluder2DEditorPlugin, EditorPlugin ); + + LightOccluder2DEditor *collision_polygon_editor; + EditorNode *editor; + +public: + + virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + + virtual String get_name() const { return "LightOccluder2D"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + LightOccluder2DEditorPlugin(EditorNode *p_node); + ~LightOccluder2DEditorPlugin(); + +}; + +#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp index b8a5bd3bbe..f8c75e1cf5 100644 --- a/tools/editor/plugins/mesh_editor_plugin.cpp +++ b/tools/editor/plugins/mesh_editor_plugin.cpp @@ -33,7 +33,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { Ref<Mesh> mesh = node->get_mesh(); if (mesh.is_null()) { err_dialog->set_text("Mesh is empty!"); - err_dialog->popup_centered(Size2(100,50)); + err_dialog->popup_centered(Size2(100,80)); return; } @@ -47,7 +47,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { CollisionShape *cshape = memnew( CollisionShape ); cshape->set_shape(shape); body->add_child(cshape); - Node *owner = node==get_scene()->get_edited_scene_root() ? node : node->get_owner(); + Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Create Static Trimesh"); @@ -68,7 +68,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { CollisionShape *cshape = memnew( CollisionShape ); cshape->set_shape(shape); body->add_child(cshape); - Node *owner = node==get_scene()->get_edited_scene_root() ? node : node->get_owner(); + Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Create Static Trimesh"); @@ -83,7 +83,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: { - if (node==get_scene()->get_edited_scene_root()) { + if (node==get_tree()->get_edited_scene_root()) { err_dialog->set_text("This doesn't work on scene root!"); err_dialog->popup_centered(Size2(100,50)); return; @@ -109,7 +109,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: { - if (node==get_scene()->get_edited_scene_root()) { + if (node==get_tree()->get_edited_scene_root()) { err_dialog->set_text("This doesn't work on scene root!"); err_dialog->popup_centered(Size2(100,50)); return; @@ -146,7 +146,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { NavigationMeshInstance *nmi = memnew( NavigationMeshInstance ); nmi->set_navigation_mesh(nmesh); - Node *owner = node==get_scene()->get_edited_scene_root() ? node : node->get_owner(); + Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Create Navigation Mesh"); @@ -158,13 +158,54 @@ void MeshInstanceEditor::_menu_option(int p_option) { ur->add_undo_method(node,"remove_child",nmi); ur->commit_action(); } break; + case MENU_OPTION_CREATE_OUTLINE_MESH: { + + outline_dialog->popup_centered(Size2(200,80)); + } break; + } + +} + +void MeshInstanceEditor::_create_outline_mesh() { + + Ref<Mesh> mesh = node->get_mesh(); + if (mesh.is_null()) { + err_dialog->set_text("MeshInstance lacks a Mesh!"); + err_dialog->popup_centered(Size2(100,50)); + return; } + Ref<Mesh> mesho = mesh->create_outline(outline_size->get_val()); + + if (mesho.is_null()) { + err_dialog->set_text("Could not create outline!"); + err_dialog->popup_centered(Size2(100,50)); + return; + } + + MeshInstance *mi = memnew( MeshInstance ); + mi->set_mesh(mesho); + Node *owner=node->get_owner(); + if (get_tree()->get_edited_scene_root()==node) { + owner=node; + } + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + ur->create_action("Create Outline"); + + ur->add_do_method(node,"add_child",mi); + ur->add_do_method(mi,"set_owner",owner); + + ur->add_do_reference(mi); + ur->add_undo_method(node,"remove_child",mi); + ur->commit_action(); } void MeshInstanceEditor::_bind_methods() { ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option); + ObjectTypeDB::bind_method("_create_outline_mesh",&MeshInstanceEditor::_create_outline_mesh); } MeshInstanceEditor::MeshInstanceEditor() { @@ -182,9 +223,26 @@ MeshInstanceEditor::MeshInstanceEditor() { options->get_popup()->add_item("Create Convex Collision Sibling",MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE); options->get_popup()->add_separator(); options->get_popup()->add_item("Create Navigation Mesh",MENU_OPTION_CREATE_NAVMESH); + options->get_popup()->add_separator(); + options->get_popup()->add_item("Create Outline Mesh..",MENU_OPTION_CREATE_OUTLINE_MESH); options->get_popup()->connect("item_pressed", this,"_menu_option"); + outline_dialog = memnew( ConfirmationDialog ); + outline_dialog->set_title("Outline Size: "); + outline_size = memnew( SpinBox ); + outline_size->set_min(0.001); + outline_size->set_max(1024); + outline_size->set_step(0.001); + outline_size->set_val(0.05); + outline_dialog->add_child(outline_size); + outline_dialog->set_child_rect(outline_size); + add_child(outline_dialog); + outline_dialog->connect("confirmed",this,"_create_outline_mesh"); + + err_dialog = memnew( AcceptDialog ); + add_child(err_dialog); + } diff --git a/tools/editor/plugins/mesh_editor_plugin.h b/tools/editor/plugins/mesh_editor_plugin.h index 557eb90148..e502b5dc2b 100644 --- a/tools/editor/plugins/mesh_editor_plugin.h +++ b/tools/editor/plugins/mesh_editor_plugin.h @@ -20,8 +20,12 @@ class MeshInstanceEditor : public Node { MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE, MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE, MENU_OPTION_CREATE_NAVMESH, + MENU_OPTION_CREATE_OUTLINE_MESH, }; + ConfirmationDialog *outline_dialog; + SpinBox *outline_size; + AcceptDialog *err_dialog; @@ -33,6 +37,8 @@ class MeshInstanceEditor : public Node { void _menu_option(int p_option); + void _create_outline_mesh(); + friend class MeshInstanceEditorPlugin; MenuButton * options; diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp new file mode 100644 index 0000000000..bc15741d0f --- /dev/null +++ b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -0,0 +1,540 @@ +#include "navigation_polygon_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "os/file_access.h" +#include "tools/editor/editor_settings.h" + +void NavigationPolygonEditor::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_READY: { + + button_create->set_icon( get_icon("Edit","EditorIcons")); + button_edit->set_icon( get_icon("MovePoint","EditorIcons")); + button_edit->set_pressed(true); + get_tree()->connect("node_removed",this,"_node_removed"); + create_nav->connect("confirmed",this,"_create_nav"); + + } break; + case NOTIFICATION_FIXED_PROCESS: { + + + } break; + } + +} +void NavigationPolygonEditor::_node_removed(Node *p_node) { + + if(p_node==node) { + node=NULL; + hide(); + canvas_item_editor->get_viewport_control()->update(); + } + +} + +void NavigationPolygonEditor::_create_nav() { + + if (!node) + return; + + undo_redo->create_action("Create Navigation Polygon"); + undo_redo->add_do_method(node,"set_navigation_polygon",Ref<NavigationPolygon>(memnew( NavigationPolygon))); + undo_redo->add_undo_method(node,"set_navigation_polygon",Variant(REF())); + undo_redo->commit_action(); +} + +void NavigationPolygonEditor::_menu_option(int p_option) { + + switch(p_option) { + + case MODE_CREATE: { + + mode=MODE_CREATE; + button_create->set_pressed(true); + button_edit->set_pressed(false); + } break; + case MODE_EDIT: { + + mode=MODE_EDIT; + button_create->set_pressed(false); + button_edit->set_pressed(true); + } break; + + } +} + +void NavigationPolygonEditor::_wip_close() { + + + if (wip.size()>=3) { + + undo_redo->create_action("Create Poly"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"remove_outline",node->get_navigation_polygon()->get_outline_count()); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"add_outline",wip); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + mode=MODE_EDIT; + button_edit->set_pressed(true); + button_create->set_pressed(false); + } + + wip.clear(); + wip_active=false; + edited_point=-1; +} + +bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) { + + + if (!node) + return false; + + if (node->get_navigation_polygon().is_null()) { + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?"); + create_nav->popup_centered_minsize(); + } + return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);; + } + + + switch(p_event.type) { + + case InputEvent::MOUSE_BUTTON: { + + const InputEventMouseButton &mb=p_event.mouse_button; + + Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + + Vector2 gpoint = Point2(mb.x,mb.y); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint=canvas_item_editor->snap_point(cpoint); + cpoint = node->get_global_transform().affine_inverse().xform(cpoint); + + + + //first check if a point is to be added (segment split) + real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8); + + switch(mode) { + + + case MODE_CREATE: { + + if (mb.button_index==BUTTON_LEFT && mb.pressed) { + + + if (!wip_active) { + + wip.clear(); + wip.push_back( cpoint ); + wip_active=true; + edited_point_pos=cpoint; + edited_outline=-1; + canvas_item_editor->get_viewport_control()->update(); + edited_point=1; + return true; + } else { + + + if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) { + //wip closed + _wip_close(); + + return true; + } else { + + wip.push_back( cpoint ); + edited_point=wip.size(); + canvas_item_editor->get_viewport_control()->update(); + return true; + + //add wip point + } + } + } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) { + _wip_close(); + } + + + + } break; + + case MODE_EDIT: { + + if (mb.button_index==BUTTON_LEFT) { + if (mb.pressed) { + + if (mb.mod.control) { + + + //search edges + int closest_outline=-1; + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + + for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) { + + + DVector<Vector2> points=node->get_navigation_polygon()->get_outline(j); + + int pc=points.size(); + DVector<Vector2>::Read poly=points.read(); + + for(int i=0;i<pc;i++) { + + Vector2 points[2] ={ xform.xform(poly[i]), + xform.xform(poly[(i+1)%pc]) }; + + Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points); + if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2) + continue; //not valid to reuse point + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_outline=j; + closest_pos=cp; + closest_idx=i; + } + + + } + } + + if (closest_idx>=0) { + + pre_move_edit=node->get_navigation_polygon()->get_outline(closest_outline); + DVector<Point2> poly = pre_move_edit; + poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos)); + edited_point=closest_idx+1; + edited_outline=closest_outline; + edited_point_pos=xform.affine_inverse().xform(closest_pos); + node->get_navigation_polygon()->set_outline(closest_outline,poly); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } else { + + //look for points to move + int closest_outline=-1; + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + + for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) { + + + DVector<Vector2> points=node->get_navigation_polygon()->get_outline(j); + + int pc=points.size(); + DVector<Vector2>::Read poly=points.read(); + + for(int i=0;i<pc;i++) { + + + Vector2 cp =xform.xform(poly[i]); + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_outline=j; + closest_idx=i; + } + } + } + + if (closest_idx>=0) { + + pre_move_edit=node->get_navigation_polygon()->get_outline(closest_outline); + edited_point=closest_idx; + edited_outline=closest_outline; + edited_point_pos=xform.affine_inverse().xform(closest_pos); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } + } else { + + if (edited_point!=-1) { + + //apply + + DVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline); + ERR_FAIL_INDEX_V(edited_point,poly.size(),false); + poly.set(edited_point,edited_point_pos); + undo_redo->create_action("Edit Poly"); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"set_outline",edited_outline,poly); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"set_outline",edited_outline,pre_move_edit); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + + edited_point=-1; + return true; + } + } + } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) { + + int closest_outline=-1; + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + + for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) { + + + DVector<Vector2> points=node->get_navigation_polygon()->get_outline(j); + + int pc=points.size(); + DVector<Vector2>::Read poly=points.read(); + + for(int i=0;i<pc;i++) { + + + Vector2 cp =xform.xform(poly[i]); + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_outline=j; + closest_idx=i; + } + } + } + + if (closest_idx>=0) { + + + DVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline); + + if (poly.size()>3) { + undo_redo->create_action("Edit Poly (Remove Point)"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"set_outline",closest_outline,poly); + poly.remove(closest_idx); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"set_outline",closest_outline,poly); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + } else { + + undo_redo->create_action("Remove Poly And Point"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"add_outline_at_index",poly,closest_outline); + poly.remove(closest_idx); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"remove_outline",closest_outline); + undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines"); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + + } + return true; + } + } + + + + } break; + } + + + + } break; + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_event.mouse_motion; + + if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) { + + Vector2 gpoint = Point2(mm.x,mm.y); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint=canvas_item_editor->snap_point(cpoint); + edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); + + canvas_item_editor->get_viewport_control()->update(); + + } + + } break; + } + + return false; +} +void NavigationPolygonEditor::_canvas_draw() { + + if (!node) + return; + + Control *vpc = canvas_item_editor->get_viewport_control(); + if (node->get_navigation_polygon().is_null()) + return; + + Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + Ref<Texture> handle= get_icon("EditorHandle","EditorIcons"); + + + + for(int j=-1;j<node->get_navigation_polygon()->get_outline_count();j++) { + Vector<Vector2> poly; + + if (wip_active && j==edited_outline) { + poly=wip; + } else { + if (j==-1) + continue; + poly = Variant(node->get_navigation_polygon()->get_outline(j)); + } + + int len = poly.size(); + + for(int i=0;i<poly.size();i++) { + + + Vector2 p,p2; + p = (j==edited_outline && i==edited_point) ? edited_point_pos : poly[i]; + if (j==edited_outline && ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))) + p2=edited_point_pos; + else + p2 = poly[(i+1)%poly.size()]; + + Vector2 point = xform.xform(p); + Vector2 next_point = xform.xform(p2); + + Color col=Color(1,0.3,0.1,0.8); + vpc->draw_line(point,next_point,col,2); + vpc->draw_texture(handle,point-handle->get_size()*0.5); + } + } +} + + + +void NavigationPolygonEditor::edit(Node *p_collision_polygon) { + + if (!canvas_item_editor) { + canvas_item_editor=CanvasItemEditor::get_singleton(); + } + + if (p_collision_polygon) { + + node=p_collision_polygon->cast_to<NavigationPolygonInstance>(); + if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw"); + wip.clear(); + wip_active=false; + edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); + + } else { + node=NULL; + + if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw"); + + } + +} + +void NavigationPolygonEditor::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_menu_option"),&NavigationPolygonEditor::_menu_option); + ObjectTypeDB::bind_method(_MD("_canvas_draw"),&NavigationPolygonEditor::_canvas_draw); + ObjectTypeDB::bind_method(_MD("_node_removed"),&NavigationPolygonEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_create_nav"),&NavigationPolygonEditor::_create_nav); + +} + +NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) { + + canvas_item_editor=NULL; + editor=p_editor; + undo_redo = editor->get_undo_redo(); + + add_child( memnew( VSeparator )); + button_create = memnew( ToolButton ); + add_child(button_create); + button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE)); + button_create->set_toggle_mode(true); + button_create->set_tooltip("Create a new polygon from scratch"); + + button_edit = memnew( ToolButton ); + add_child(button_edit); + button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT)); + button_edit->set_toggle_mode(true); + button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."); + create_nav = memnew( ConfirmationDialog ); + add_child(create_nav); + create_nav->get_ok()->set_text("Create"); + + + //add_constant_override("separation",0); + +#if 0 + options = memnew( MenuButton ); + add_child(options); + options->set_area_as_parent_rect(); + options->set_text("Polygon"); + //options->get_popup()->add_item("Parse BBCODE",PARSE_BBCODE); + options->get_popup()->connect("item_pressed", this,"_menu_option"); +#endif + + mode = MODE_EDIT; + wip_active=false; + edited_outline=-1; + +} + + +void NavigationPolygonEditorPlugin::edit(Object *p_object) { + + collision_polygon_editor->edit(p_object->cast_to<Node>()); +} + +bool NavigationPolygonEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("NavigationPolygonInstance"); +} + +void NavigationPolygonEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + collision_polygon_editor->show(); + } else { + + collision_polygon_editor->hide(); + collision_polygon_editor->edit(NULL); + } + +} + +NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) { + + editor=p_node; + collision_polygon_editor = memnew( NavigationPolygonEditor(p_node) ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); + + collision_polygon_editor->hide(); + + + +} + + +NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin() +{ +} + diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.h b/tools/editor/plugins/navigation_polygon_editor_plugin.h new file mode 100644 index 0000000000..f742cb011d --- /dev/null +++ b/tools/editor/plugins/navigation_polygon_editor_plugin.h @@ -0,0 +1,90 @@ +#ifndef NAVIGATIONPOLYGONEDITORPLUGIN_H +#define NAVIGATIONPOLYGONEDITORPLUGIN_H + + + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/2d/navigation_polygon.h" +#include "scene/gui/tool_button.h" +#include "scene/gui/button_group.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class CanvasItemEditor; + +class NavigationPolygonEditor : public HBoxContainer { + + OBJ_TYPE(NavigationPolygonEditor, HBoxContainer ); + + UndoRedo *undo_redo; + enum Mode { + + MODE_CREATE, + MODE_EDIT, + + }; + + Mode mode; + + ToolButton *button_create; + ToolButton *button_edit; + + ConfirmationDialog *create_nav; + + CanvasItemEditor *canvas_item_editor; + EditorNode *editor; + Panel *panel; + NavigationPolygonInstance *node; + MenuButton *options; + + int edited_outline; + int edited_point; + Vector2 edited_point_pos; + DVector<Vector2> pre_move_edit; + Vector<Vector2> wip; + bool wip_active; + + + void _wip_close(); + void _canvas_draw(); + void _create_nav(); + + void _menu_option(int p_option); + +protected: + void _notification(int p_what); + void _node_removed(Node *p_node); + static void _bind_methods(); +public: + + bool forward_input_event(const InputEvent& p_event); + void edit(Node *p_collision_polygon); + NavigationPolygonEditor(EditorNode *p_editor); +}; + +class NavigationPolygonEditorPlugin : public EditorPlugin { + + OBJ_TYPE( NavigationPolygonEditorPlugin, EditorPlugin ); + + NavigationPolygonEditor *collision_polygon_editor; + EditorNode *editor; + +public: + + virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + + virtual String get_name() const { return "NavigationPolygonInstance"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + NavigationPolygonEditorPlugin(EditorNode *p_node); + ~NavigationPolygonEditorPlugin(); + +}; + + +#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H diff --git a/tools/editor/plugins/particles_2d_editor_plugin.cpp b/tools/editor/plugins/particles_2d_editor_plugin.cpp index b23847231b..a7adfcd172 100644 --- a/tools/editor/plugins/particles_2d_editor_plugin.cpp +++ b/tools/editor/plugins/particles_2d_editor_plugin.cpp @@ -26,173 +26,173 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "particles_2d_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-#include "io/image_loader.h"
-
-
-void Particles2DEditorPlugin::edit(Object *p_object) {
-
- if (p_object) {
- particles=p_object->cast_to<Particles2D>();
- } else {
- particles=NULL;
- }
-}
-
-bool Particles2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Particles2D");
-}
-
-void Particles2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- sep->show();
- menu->show();
- } else {
-
- menu->hide();
- sep->hide();
- }
-
-}
-
-void Particles2DEditorPlugin::_file_selected(const String& p_file) {
-
- print_line("file: "+p_file);
-
- int epc=epoints->get_val();
-
- Image img;
- Error err = ImageLoader::load_image(p_file,&img);
- ERR_EXPLAIN("Error loading image: "+p_file);
- ERR_FAIL_COND(err!=OK);
-
- img.convert(Image::FORMAT_GRAYSCALE_ALPHA);
- ERR_FAIL_COND(img.get_format()!=Image::FORMAT_GRAYSCALE_ALPHA);
- Size2i s = Size2(img.get_width(),img.get_height());
- ERR_FAIL_COND(s.width==0 || s.height==0);
-
- DVector<uint8_t> data = img.get_data();
- DVector<uint8_t>::Read r = data.read();
-
- Vector<Point2i> valid_positions;
- valid_positions.resize(s.width*s.height);
- int vpc=0;
-
-
- for(int i=0;i<s.width*s.height;i++) {
-
- uint8_t a = r[i*2+1];
- if (a>128) {
- valid_positions[vpc++]=Point2i(i%s.width,i/s.width);
- }
- }
-
- valid_positions.resize(vpc);
-
- ERR_EXPLAIN("No pixels with transparency > 128 in image..");
- ERR_FAIL_COND(valid_positions.size()==0);
-
- DVector<Point2> epoints;
- epoints.resize(epc);
- DVector<Point2>::Write w = epoints.write();
-
- Size2 extents = Size2(img.get_width()*0.5,img.get_height()*0.5);
-
- for(int i=0;i<epc;i++) {
-
- Point2 p = valid_positions[Math::rand()%vpc];
- p-=s/2;
- w[i]=p/extents;
- }
-
- w = DVector<Point2>::Write();
-
- undo_redo->create_action("Set Emission Mask");
- undo_redo->add_do_method(particles,"set_emission_points",epoints);
- undo_redo->add_do_method(particles,"set_emission_half_extents",extents);
- undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points());
- undo_redo->add_undo_method(particles,"set_emission_half_extents",particles->get_emission_half_extents());
- undo_redo->commit_action();
-
-}
-
-void Particles2DEditorPlugin::_menu_callback(int p_idx) {
-
- switch(p_idx) {
- case MENU_LOAD_EMISSION_MASK: {
-
-
- file->popup_centered_ratio();
-
- } break;
- case MENU_CLEAR_EMISSION_MASK: {
-
- undo_redo->create_action("Clear Emission Mask");
- undo_redo->add_do_method(particles,"set_emission_points",DVector<Vector2>());
- undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points());
- undo_redo->commit_action();
- } break;
- }
-
-}
-
-
-void Particles2DEditorPlugin::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_SCENE) {
-
- menu->get_popup()->connect("item_pressed",this,"_menu_callback");
- file->connect("file_selected",this,"_file_selected");
- }
-}
-
-void Particles2DEditorPlugin::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("_menu_callback"),&Particles2DEditorPlugin::_menu_callback);
- ObjectTypeDB::bind_method(_MD("_file_selected"),&Particles2DEditorPlugin::_file_selected);
-}
-
-
-
-Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) {
-
- particles=NULL;
- editor=p_node;
- undo_redo=editor->get_undo_redo();
- sep = memnew( VSeparator );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(sep);
- sep->hide();
-
- menu = memnew( MenuButton );
- menu->get_popup()->add_item("Load Emission Mask",MENU_LOAD_EMISSION_MASK);
- menu->get_popup()->add_item("Clear Emission Mask",MENU_CLEAR_EMISSION_MASK);
- menu->set_text("Particles");
-
- file = memnew(FileDialog);
- add_child(file);
- List<String> ext;
- ImageLoader::get_recognized_extensions(&ext);
- for(List<String>::Element *E=ext.front();E;E=E->next()) {
- file->add_filter("*."+E->get()+"; "+E->get().to_upper());
- }
- file->set_mode(FileDialog::MODE_OPEN_FILE);
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(menu);
- epoints = memnew( SpinBox );
- epoints->set_min(1);
- epoints->set_max(8192);
- epoints->set_step(1);
- epoints->set_val(512);
- file->get_vbox()->add_margin_child("Generated Point Count:",epoints);
- menu->hide();
-
-}
-
-
-Particles2DEditorPlugin::~Particles2DEditorPlugin()
-{
-}
-
+#include "particles_2d_editor_plugin.h" +#include "canvas_item_editor_plugin.h" +#include "io/image_loader.h" + + +void Particles2DEditorPlugin::edit(Object *p_object) { + + if (p_object) { + particles=p_object->cast_to<Particles2D>(); + } else { + particles=NULL; + } +} + +bool Particles2DEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("Particles2D"); +} + +void Particles2DEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + + sep->show(); + menu->show(); + } else { + + menu->hide(); + sep->hide(); + } + +} + +void Particles2DEditorPlugin::_file_selected(const String& p_file) { + + print_line("file: "+p_file); + + int epc=epoints->get_val(); + + Image img; + Error err = ImageLoader::load_image(p_file,&img); + ERR_EXPLAIN("Error loading image: "+p_file); + ERR_FAIL_COND(err!=OK); + + img.convert(Image::FORMAT_GRAYSCALE_ALPHA); + ERR_FAIL_COND(img.get_format()!=Image::FORMAT_GRAYSCALE_ALPHA); + Size2i s = Size2(img.get_width(),img.get_height()); + ERR_FAIL_COND(s.width==0 || s.height==0); + + DVector<uint8_t> data = img.get_data(); + DVector<uint8_t>::Read r = data.read(); + + Vector<Point2i> valid_positions; + valid_positions.resize(s.width*s.height); + int vpc=0; + + + for(int i=0;i<s.width*s.height;i++) { + + uint8_t a = r[i*2+1]; + if (a>128) { + valid_positions[vpc++]=Point2i(i%s.width,i/s.width); + } + } + + valid_positions.resize(vpc); + + ERR_EXPLAIN("No pixels with transparency > 128 in image.."); + ERR_FAIL_COND(valid_positions.size()==0); + + DVector<Point2> epoints; + epoints.resize(epc); + DVector<Point2>::Write w = epoints.write(); + + Size2 extents = Size2(img.get_width()*0.5,img.get_height()*0.5); + + for(int i=0;i<epc;i++) { + + Point2 p = valid_positions[Math::rand()%vpc]; + p-=s/2; + w[i]=p/extents; + } + + w = DVector<Point2>::Write(); + + undo_redo->create_action("Set Emission Mask"); + undo_redo->add_do_method(particles,"set_emission_points",epoints); + undo_redo->add_do_method(particles,"set_emission_half_extents",extents); + undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points()); + undo_redo->add_undo_method(particles,"set_emission_half_extents",particles->get_emission_half_extents()); + undo_redo->commit_action(); + +} + +void Particles2DEditorPlugin::_menu_callback(int p_idx) { + + switch(p_idx) { + case MENU_LOAD_EMISSION_MASK: { + + + file->popup_centered_ratio(); + + } break; + case MENU_CLEAR_EMISSION_MASK: { + + undo_redo->create_action("Clear Emission Mask"); + undo_redo->add_do_method(particles,"set_emission_points",DVector<Vector2>()); + undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points()); + undo_redo->commit_action(); + } break; + } + +} + + +void Particles2DEditorPlugin::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_TREE) { + + menu->get_popup()->connect("item_pressed",this,"_menu_callback"); + file->connect("file_selected",this,"_file_selected"); + } +} + +void Particles2DEditorPlugin::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_menu_callback"),&Particles2DEditorPlugin::_menu_callback); + ObjectTypeDB::bind_method(_MD("_file_selected"),&Particles2DEditorPlugin::_file_selected); +} + + + +Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) { + + particles=NULL; + editor=p_node; + undo_redo=editor->get_undo_redo(); + sep = memnew( VSeparator ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(sep); + sep->hide(); + + menu = memnew( MenuButton ); + menu->get_popup()->add_item("Load Emission Mask",MENU_LOAD_EMISSION_MASK); + menu->get_popup()->add_item("Clear Emission Mask",MENU_CLEAR_EMISSION_MASK); + menu->set_text("Particles"); + + file = memnew(FileDialog); + add_child(file); + List<String> ext; + ImageLoader::get_recognized_extensions(&ext); + for(List<String>::Element *E=ext.front();E;E=E->next()) { + file->add_filter("*."+E->get()+"; "+E->get().to_upper()); + } + file->set_mode(FileDialog::MODE_OPEN_FILE); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(menu); + epoints = memnew( SpinBox ); + epoints->set_min(1); + epoints->set_max(8192); + epoints->set_step(1); + epoints->set_val(512); + file->get_vbox()->add_margin_child("Generated Point Count:",epoints); + menu->hide(); + +} + + +Particles2DEditorPlugin::~Particles2DEditorPlugin() +{ +} + diff --git a/tools/editor/plugins/particles_editor_plugin.cpp b/tools/editor/plugins/particles_editor_plugin.cpp index 418ad11704..ebb45bc316 100644 --- a/tools/editor/plugins/particles_editor_plugin.cpp +++ b/tools/editor/plugins/particles_editor_plugin.cpp @@ -110,7 +110,7 @@ void ParticlesEditor::_populate() { void ParticlesEditor::_notification(int p_notification) { - if (p_notification==NOTIFICATION_ENTER_SCENE) { + if (p_notification==NOTIFICATION_ENTER_TREE) { } } diff --git a/tools/editor/plugins/path_2d_editor_plugin.cpp b/tools/editor/plugins/path_2d_editor_plugin.cpp index 33ea5f3588..a38ec5bb7a 100644 --- a/tools/editor/plugins/path_2d_editor_plugin.cpp +++ b/tools/editor/plugins/path_2d_editor_plugin.cpp @@ -62,17 +62,6 @@ void Path2DEditor::_node_removed(Node *p_node) { } -Vector2 Path2DEditor::snap_point(const Vector2& p_point) const { - - if (canvas_item_editor->is_snap_active()) { - - return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap()); - - } else { - return p_point; - } -} - bool Path2DEditor::forward_input_event(const InputEvent& p_event) { if (!node) @@ -93,8 +82,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = Point2(mb.x,mb.y); - Vector2 cpoint = !mb.mod.alt? snap_point(xform.affine_inverse().xform(gpoint)) - : node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) ); + Vector2 cpoint = !mb.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)) + : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) ); //first check if a point is to be added (segment split) real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8); @@ -195,7 +184,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { Ref<Curve2D> curve = node->get_curve(); - Vector2 new_pos = moving_from + xform.basis_xform( gpoint - moving_screen_from ); + Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from); switch(action) { case ACTION_MOVING_POINT: { @@ -250,9 +239,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { if (!wip_active) { wip.clear(); - wip.push_back( snap_point(cpoint) ); + wip.push_back( canvas_item_editor->snap_point(cpoint) ); wip_active=true; - edited_point_pos=snap_point(cpoint); + edited_point_pos=canvas_item_editor->snap_point(cpoint); canvas_item_editor->update(); edited_point=1; return true; @@ -265,7 +254,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { return true; } else { - wip.push_back( snap_point(cpoint) ); + wip.push_back( canvas_item_editor->snap_point(cpoint) ); edited_point=wip.size(); canvas_item_editor->update(); return true; @@ -327,9 +316,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { if (closest_idx>=0) { pre_move_edit=poly; - poly.insert(closest_idx+1,snap_point(xform.affine_inverse().xform(closest_pos))); + poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos))); edited_point=closest_idx+1; - edited_point_pos=snap_point(xform.affine_inverse().xform(closest_pos)); + edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)); node->set_polygon(poly); canvas_item_editor->update(); return true; @@ -434,12 +423,12 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = Point2(mm.x,mm.y); - Vector2 cpoint = !mm.mod.alt? snap_point(xform.affine_inverse().xform(gpoint)) - : node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) ); + Vector2 cpoint = !mm.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)) + : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) ); Ref<Curve2D> curve = node->get_curve(); - Vector2 new_pos = moving_from + xform.basis_xform( gpoint - moving_screen_from ); + Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from); switch(action) { @@ -471,7 +460,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) { Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = Point2(mm.x,mm.y); - edited_point_pos = snap_point(xform.affine_inverse().xform(gpoint)); + edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint)); canvas_item_editor->update(); } diff --git a/tools/editor/plugins/path_2d_editor_plugin.h b/tools/editor/plugins/path_2d_editor_plugin.h index 73de2cc838..6ff69b96a2 100644 --- a/tools/editor/plugins/path_2d_editor_plugin.h +++ b/tools/editor/plugins/path_2d_editor_plugin.h @@ -94,7 +94,6 @@ protected: static void _bind_methods(); public: - Vector2 snap_point(const Vector2& p_point) const; bool forward_input_event(const InputEvent& p_event); void edit(Node *p_path2d); Path2DEditor(EditorNode *p_editor); diff --git a/tools/editor/plugins/path_editor_plugin.cpp b/tools/editor/plugins/path_editor_plugin.cpp index 7b0ff971d2..3f540a3bf4 100644 --- a/tools/editor/plugins/path_editor_plugin.cpp +++ b/tools/editor/plugins/path_editor_plugin.cpp @@ -500,7 +500,7 @@ void PathEditorPlugin::_close_curve() { void PathEditorPlugin::_notification(int p_what) {
- if (p_what==NOTIFICATION_ENTER_SCENE) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
curve_create->connect("pressed",this,"_mode_changed",make_binds(0));
curve_edit->connect("pressed",this,"_mode_changed",make_binds(1));
diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.cpp b/tools/editor/plugins/polygon_2d_editor_plugin.cpp index 7dd8dd3035..3858bf2c68 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/polygon_2d_editor_plugin.cpp @@ -69,17 +69,6 @@ void Polygon2DEditor::_node_removed(Node *p_node) { } -Vector2 Polygon2DEditor::snap_point(const Vector2& p_point) const { - - if (canvas_item_editor->is_snap_active()) { - - return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap()); - - } else { - return p_point; - } -} - void Polygon2DEditor::_menu_option(int p_option) { switch(p_option) { @@ -187,6 +176,8 @@ void Polygon2DEditor::_wip_close() { bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) { + if (node==NULL) + return false; switch(p_event.type) { @@ -199,7 +190,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) { Vector2 gpoint = Point2(mb.x,mb.y); Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint=snap_point(cpoint); + cpoint=canvas_item_editor->snap_point(cpoint); cpoint = node->get_global_transform().affine_inverse().xform(cpoint); @@ -403,7 +394,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) { Vector2 gpoint = Point2(mm.x,mm.y); Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint=snap_point(cpoint); + cpoint=canvas_item_editor->snap_point(cpoint); edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); canvas_item_editor->get_viewport_control()->update(); @@ -701,11 +692,16 @@ void Polygon2DEditor::edit(Node *p_collision_polygon) { node=p_collision_polygon->cast_to<Polygon2D>(); if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw"); + node->connect("exit_tree",this,"_node_removed",varray(),CONNECT_ONESHOT); wip.clear(); wip_active=false; edited_point=-1; } else { + + if (node) + node->disconnect("exit_tree",this,"_node_removed"); + node=NULL; if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) @@ -723,12 +719,14 @@ void Polygon2DEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_uv_draw"),&Polygon2DEditor::_uv_draw); ObjectTypeDB::bind_method(_MD("_uv_input"),&Polygon2DEditor::_uv_input); ObjectTypeDB::bind_method(_MD("_uv_scroll_changed"),&Polygon2DEditor::_uv_scroll_changed); + ObjectTypeDB::bind_method(_MD("_node_removed"),&Polygon2DEditor::_node_removed); } Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { + node=NULL; canvas_item_editor=NULL; editor=p_editor; undo_redo = editor->get_undo_redo(); diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.h b/tools/editor/plugins/polygon_2d_editor_plugin.h index 88d1c20493..8f807cb7e8 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.h +++ b/tools/editor/plugins/polygon_2d_editor_plugin.h @@ -92,7 +92,6 @@ protected: static void _bind_methods(); public: - Vector2 snap_point(const Vector2& p_point) const; bool forward_input_event(const InputEvent& p_event); void edit(Node *p_collision_polygon); Polygon2DEditor(EditorNode *p_editor); diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.cpp b/tools/editor/plugins/resource_preloader_editor_plugin.cpp index b0841933ec..d9726cac21 100644 --- a/tools/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/tools/editor/plugins/resource_preloader_editor_plugin.cpp @@ -45,7 +45,7 @@ void ResourcePreloaderEditor::_notification(int p_what) { } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { load->set_icon( get_icon("Folder","EditorIcons") ); _delete->set_icon( get_icon("Del","EditorIcons") ); } diff --git a/tools/editor/plugins/sample_editor_plugin.cpp b/tools/editor/plugins/sample_editor_plugin.cpp index e3fad58a89..83adeee789 100644 --- a/tools/editor/plugins/sample_editor_plugin.cpp +++ b/tools/editor/plugins/sample_editor_plugin.cpp @@ -46,7 +46,7 @@ void SampleEditor::_notification(int p_what) { } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { play->set_icon( get_icon("Play","EditorIcons") ); stop->set_icon( get_icon("Stop","EditorIcons") ); } diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp index 84143dcd4b..96d72595ab 100644 --- a/tools/editor/plugins/sample_library_editor_plugin.cpp +++ b/tools/editor/plugins/sample_library_editor_plugin.cpp @@ -47,7 +47,7 @@ void SampleLibraryEditor::_notification(int p_what) { } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { play->set_icon( get_icon("Play","EditorIcons") ); stop->set_icon( get_icon("Stop","EditorIcons") ); load->set_icon( get_icon("Folder","EditorIcons") ); @@ -129,7 +129,7 @@ void SampleLibraryEditor::_button_pressed(Object *p_item,int p_column, int p_id) player->play(name,true); } else if (p_column==1) { - get_scene()->get_root()->get_child(0)->call("_resource_selected",sample_library->get_sample(name)); + get_tree()->get_root()->get_child(0)->call("_resource_selected",sample_library->get_sample(name)); } @@ -186,7 +186,7 @@ void SampleLibraryEditor::_item_edited() { Ref<Sample> samp = sample_library->get_sample(tree->get_selected()->get_metadata(0)); - get_scene()->get_root()->get_child(0)->call("_resource_selected",samp); + get_tree()->get_root()->get_child(0)->call("_resource_selected",samp); } @@ -235,6 +235,7 @@ void SampleLibraryEditor::_update_library() { List<StringName> names; sample_library->get_sample_list(&names); + names.sort_custom<StringName::AlphCompare>(); for(List<StringName>::Element *E=names.front();E;E=E->next()) { diff --git a/tools/editor/plugins/sample_player_editor_plugin.cpp b/tools/editor/plugins/sample_player_editor_plugin.cpp index f3d6fe65da..2e31467dc7 100644 --- a/tools/editor/plugins/sample_player_editor_plugin.cpp +++ b/tools/editor/plugins/sample_player_editor_plugin.cpp @@ -32,7 +32,7 @@ void SamplePlayerEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { play->set_icon( get_icon("Play","EditorIcons") ); stop->set_icon( get_icon("Stop","EditorIcons") ); } @@ -94,6 +94,7 @@ void SamplePlayerEditor::_update_sample_library() { List<StringName> samplenames; sl->get_sample_list(&samplenames); + samplenames.sort_custom<StringName::AlphCompare>(); for(List<StringName>::Element *E=samplenames.front();E;E=E->next()) { samples->add_item(E->get()); } diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 24e09111e2..72b3025f2f 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -115,7 +115,7 @@ void ScriptEditorQuickOpen::_confirmed() { void ScriptEditorQuickOpen::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); } @@ -188,7 +188,7 @@ void ScriptTextEditor::apply_code() { if (script.is_null()) return; - print_line("applying code"); +// print_line("applying code"); script->set_source_code(get_text_edit()->get_text()); script->update_exports(); } @@ -209,6 +209,8 @@ void ScriptTextEditor::_load_theme_settings() { get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/text_color",Color(0,0,0))); get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/text_selected_color",Color(1,1,1))); get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/selection_color",Color(0.2,0.2,1))); + get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/brace_mismatch_color",Color(1,0.2,0.2))); + get_text_edit()->add_color_override("current_line_color",EDITOR_DEF("text_editor/current_line_color",Color(0.3,0.5,0.8,0.15))); Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2)); @@ -237,7 +239,7 @@ void ScriptTextEditor::_load_theme_settings() { //colorize engine types Color type_color= EDITOR_DEF("text_editor/engine_type_color",Color(0.0,0.2,0.4)); - List<String> types; + List<String> types; ObjectTypeDB::get_type_list(&types); for(List<String>::Element *E=types.front();E;E=E->next()) { @@ -384,9 +386,35 @@ void ScriptTextEditor::_validate_script() { _update_name(); } -void ScriptTextEditor::_code_complete_script(const String& p_code, const String& p_keyword,int p_line, List<String>* r_options) { - Error err = script->get_language()->complete_keyword(p_code,p_line,script->get_path().get_base_dir(),p_keyword,r_options); +static Node* _find_node_for_script(Node* p_base, Node*p_current, const Ref<Script>& p_script) { + + if (p_current->get_owner()!=p_base && p_base!=p_current) + return NULL; + Ref<Script> c = p_current->get_script(); + if (c==p_script) + return p_current; + for(int i=0;i<p_current->get_child_count();i++) { + Node *found = _find_node_for_script(p_base,p_current->get_child(i),p_script); + if (found) + return found; + } + + return NULL; +} + +void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) { + + Node *base = get_tree()->get_edited_scene_root(); + if (base) { + base = _find_node_for_script(base,base,script); + } + String hint; + Error err = script->get_language()->complete_code(p_code,script->get_path().get_base_dir(),base,r_options,hint); + if (hint!="") { + get_text_edit()->set_code_hint(hint); + print_line("hint: "+hint.replace(String::chr(0xFFFF),"|")); + } } @@ -602,12 +630,27 @@ bool ScriptEditor::_test_script_times_on_disk() { - if (!all_ok) - disk_changed->call_deferred("popup_centered_ratio",0.5); + if (!all_ok) { + if (bool(EDITOR_DEF("text_editor/auto_reload_changed_scripts",false))) { + script_editor->_reload_scripts(); + } else { + disk_changed->call_deferred("popup_centered_ratio",0.5); + } + } return all_ok; } +void ScriptEditor::swap_lines(TextEdit *tx, int line1, int line2) +{ + String tmp = tx->get_line(line1); + String tmp2 = tx->get_line(line2); + tx->set_line(line2, tmp); + tx->set_line(line1, tmp2); + + tx->cursor_set_line(line2); +} + void ScriptEditor::_menu_option(int p_option) { @@ -661,13 +704,10 @@ void ScriptEditor::_menu_option(int p_option) { } break; case EDIT_UNDO: { - - current->get_text_edit()->undo(); } break; case EDIT_REDO: { current->get_text_edit()->redo(); - } break; case EDIT_CUT: { @@ -686,6 +726,223 @@ void ScriptEditor::_menu_option(int p_option) { current->get_text_edit()->select_all(); } break; + case EDIT_MOVE_LINE_UP: { + + TextEdit *tx = current->get_text_edit(); + Ref<Script> scr = current->get_edited_script(); + if (scr.is_null()) + return; + + if (tx->is_selection_active()) + { + int from_line = tx->get_selection_from_line(); + int from_col = tx->get_selection_from_column(); + int to_line = tx->get_selection_to_line(); + int to_column = tx->get_selection_to_column(); + + for (int i = from_line; i <= to_line; i++) + { + int line_id = i; + int next_id = i - 1; + + if (line_id == 0 || next_id < 0) + return; + + swap_lines(tx, line_id, next_id); + } + int from_line_up = from_line > 0 ? from_line-1 : from_line; + int to_line_up = to_line > 0 ? to_line-1 : to_line; + tx->select(from_line_up, from_col, to_line_up, to_column); + } + else + { + int line_id = tx->cursor_get_line(); + int next_id = line_id - 1; + + if (line_id == 0 || next_id < 0) + return; + + swap_lines(tx, line_id, next_id); + } + tx->update(); + + } break; + case EDIT_MOVE_LINE_DOWN: { + + TextEdit *tx = current->get_text_edit(); + Ref<Script> scr = current->get_edited_script(); + if (scr.is_null()) + return; + + if (tx->is_selection_active()) + { + int from_line = tx->get_selection_from_line(); + int from_col = tx->get_selection_from_column(); + int to_line = tx->get_selection_to_line(); + int to_column = tx->get_selection_to_column(); + + for (int i = to_line; i >= from_line; i--) + { + int line_id = i; + int next_id = i + 1; + + if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count()) + return; + + swap_lines(tx, line_id, next_id); + } + int from_line_down = from_line < tx->get_line_count() ? from_line+1 : from_line; + int to_line_down = to_line < tx->get_line_count() ? to_line+1 : to_line; + tx->select(from_line_down, from_col, to_line_down, to_column); + } + else + { + int line_id = tx->cursor_get_line(); + int next_id = line_id + 1; + + if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count()) + return; + + swap_lines(tx, line_id, next_id); + } + tx->update(); + + } break; + case EDIT_INDENT_LEFT: { + + TextEdit *tx = current->get_text_edit(); + Ref<Script> scr = current->get_edited_script(); + if (scr.is_null()) + return; + + int begin, end; + begin = tx->get_selection_from_line(); + if (tx->is_selection_active()) + { + end = tx->get_selection_to_line(); + for (int i = begin; i <= end; i++) + { + String line_text = tx->get_line(i); + // begins with tab + if (line_text.begins_with("\t")) + { + line_text = line_text.substr(1, line_text.length()); + tx->set_line(i, line_text); + } + // begins with 4 spaces + else if (line_text.begins_with(" ")) + { + line_text = line_text.substr(4, line_text.length()); + tx->set_line(i, line_text); + } + } + } + else + { + begin = tx->cursor_get_line(); + String line_text = tx->get_line(begin); + // begins with tab + if (line_text.begins_with("\t")) + { + line_text = line_text.substr(1, line_text.length()); + tx->set_line(begin, line_text); + } + // begins with 4 spaces + else if (line_text.begins_with(" ")) + { + line_text = line_text.substr(4, line_text.length()); + tx->set_line(begin, line_text); + } + } + tx->update(); + //tx->deselect(); + + } break; + case EDIT_INDENT_RIGHT: { + + TextEdit *tx = current->get_text_edit(); + Ref<Script> scr = current->get_edited_script(); + if (scr.is_null()) + return; + + int begin, end; + begin = tx->get_selection_from_line(); + if (tx->is_selection_active()) + { + end = tx->get_selection_to_line(); + for (int i = begin; i <= end; i++) + { + String line_text = tx->get_line(i); + line_text = '\t' + line_text; + tx->set_line(i, line_text); + } + } + else + { + begin = tx->cursor_get_line(); + String line_text = tx->get_line(begin); + line_text = '\t' + line_text; + tx->set_line(begin, line_text); + } + tx->update(); + //tx->deselect(); + + } break; + case EDIT_CLONE_DOWN: { + + TextEdit *tx = current->get_text_edit(); + Ref<Script> scr = current->get_edited_script(); + if (scr.is_null()) + return; + int line = tx->cursor_get_line(); + int next_line = line + 1; + + if (line == tx->get_line_count() || next_line > tx->get_line_count()) + return; + + String line_clone = tx->get_line(line); + tx->insert_at(line_clone, next_line); + tx->update(); + + } break; + case EDIT_TOGGLE_COMMENT: { + + TextEdit *tx = current->get_text_edit(); + Ref<Script> scr = current->get_edited_script(); + if (scr.is_null()) + return; + + int begin, end; + begin = tx->get_selection_from_line(); + if (tx->is_selection_active()) + { + end = tx->get_selection_to_line(); + for (int i = begin; i <= end; i++) + { + String line_text = tx->get_line(i); + + if (line_text.begins_with("#")) + line_text = line_text.substr(1, line_text.length()); + else + line_text = "#" + line_text; + tx->set_line(i, line_text); + } + } + else + { + begin = tx->cursor_get_line(); + String line_text = tx->get_line(begin); + + if (line_text.begins_with("#")) + line_text = line_text.substr(1, line_text.length()); + else + line_text = "#" + line_text; + tx->set_line(begin, line_text); + } + tx->update(); + //tx->deselect(); + + } break; case EDIT_COMPLETE: { current->get_text_edit()->query_code_comple(); @@ -782,9 +1039,12 @@ void ScriptEditor::_menu_option(int p_option) { editor->emit_signal("request_help", text); } break; case WINDOW_CLOSE: { - - erase_tab_confirm->set_text("Close Tab?:\n\""+current->get_name()+"\""); - erase_tab_confirm->popup_centered(Point2(250,80)); + if (current->get_text_edit()->get_version()!=current->get_text_edit()->get_saved_version()) { + erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\""); + erase_tab_confirm->popup_centered(Point2(250,80)); + } else { + _close_current_tab(); + } } break; case WINDOW_MOVE_LEFT: { @@ -822,7 +1082,7 @@ void ScriptEditor::_tab_changed(int p_which) { void ScriptEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { editor->connect("play_pressed",this,"_editor_play"); editor->connect("pause_pressed",this,"_editor_pause"); @@ -837,7 +1097,7 @@ void ScriptEditor::_notification(int p_what) { _update_window_menu(); } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { editor->disconnect("play_pressed",this,"_editor_play"); editor->disconnect("pause_pressed",this,"_editor_pause"); @@ -895,7 +1155,7 @@ Dictionary ScriptEditor::get_state() const { } else { - const Node *owner = _find_node_with_script(get_scene()->get_root(),script.get_ref_ptr()); + const Node *owner = _find_node_with_script(get_tree()->get_root(),script.get_ref_ptr()); if (owner) paths.push_back(owner->get_path()); @@ -931,7 +1191,7 @@ void ScriptEditor::set_state(const Dictionary& p_state) { if (source.get_type()==Variant::NODE_PATH) { - Node *owner=get_scene()->get_root()->get_node(source); + Node *owner=get_tree()->get_root()->get_node(source); if (!owner) continue; @@ -1289,7 +1549,7 @@ void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const int pos = script->get_language()->find_function(p_function,code); if (pos==-1) { //does not exist - + ste->get_text_edit()->deselect(); pos=ste->get_text_edit()->get_line_count()+2; String func = script->get_language()->make_function("",p_function,p_args); //code=code+func; @@ -1327,7 +1587,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(file_menu); file_menu->set_text("File"); file_menu->get_popup()->add_item("Open",FILE_OPEN); - file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_S); + file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_MASK_CMD|KEY_S); file_menu->get_popup()->add_item("Save As..",FILE_SAVE_AS); file_menu->get_popup()->add_item("Save All",FILE_SAVE_ALL,KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_S); file_menu->get_popup()->connect("item_pressed", this,"_menu_option"); @@ -1335,8 +1595,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { edit_menu = memnew( MenuButton ); menu_hb->add_child(edit_menu); edit_menu->set_text("Edit"); - edit_menu->get_popup()->add_item("Undo"); - edit_menu->get_popup()->add_item("Redo"); + edit_menu->get_popup()->add_item("Undo",EDIT_UNDO,KEY_MASK_CMD|KEY_Z); + edit_menu->get_popup()->add_item("Redo",EDIT_REDO,KEY_MASK_CMD|KEY_Y); edit_menu->get_popup()->add_separator(); edit_menu->get_popup()->add_item("Cut",EDIT_CUT,KEY_MASK_CMD|KEY_X); edit_menu->get_popup()->add_item("Copy",EDIT_COPY,KEY_MASK_CMD|KEY_C); @@ -1344,7 +1604,18 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { edit_menu->get_popup()->add_separator(); edit_menu->get_popup()->add_item("Select All",EDIT_SELECT_ALL,KEY_MASK_CMD|KEY_A); edit_menu->get_popup()->add_separator(); + edit_menu->get_popup()->add_item("Move Up",EDIT_MOVE_LINE_UP,KEY_MASK_ALT|KEY_UP); + edit_menu->get_popup()->add_item("Move Down",EDIT_MOVE_LINE_DOWN,KEY_MASK_ALT|KEY_DOWN); + edit_menu->get_popup()->add_item("Indent Left",EDIT_INDENT_LEFT,KEY_MASK_ALT|KEY_LEFT); + edit_menu->get_popup()->add_item("Indent Right",EDIT_INDENT_RIGHT,KEY_MASK_ALT|KEY_RIGHT); + edit_menu->get_popup()->add_item("Toggle Comment",EDIT_TOGGLE_COMMENT,KEY_MASK_CMD|KEY_K); + edit_menu->get_popup()->add_item("Clone Down",EDIT_CLONE_DOWN,KEY_MASK_CMD|KEY_B); + edit_menu->get_popup()->add_separator(); +#ifdef OSX_ENABLED + edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CTRL|KEY_SPACE); +#else edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CMD|KEY_SPACE); +#endif edit_menu->get_popup()->add_item("Auto Indent",EDIT_AUTO_INDENT,KEY_MASK_CMD|KEY_I); edit_menu->get_popup()->connect("item_pressed", this,"_menu_option"); @@ -1540,6 +1811,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { script_editor->hide(); + EDITOR_DEF("text_editor/auto_reload_changed_scripts",false); EDITOR_DEF("external_editor/use_external_editor",false); EDITOR_DEF("external_editor/exec_path",""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"external_editor/exec_path",PROPERTY_HINT_GLOBAL_FILE)); diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index 69b8739d67..136d966587 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -85,7 +85,7 @@ protected: virtual void _validate_script(); - virtual void _code_complete_script(const String& p_code,const String& p_keyword, int p_line, List<String>* r_options); + virtual void _code_complete_script(const String& p_code, List<String>* r_options); virtual void _load_theme_settings(); void _notification(int p_what); @@ -123,6 +123,12 @@ class ScriptEditor : public VBoxContainer { EDIT_SELECT_ALL, EDIT_COMPLETE, EDIT_AUTO_INDENT, + EDIT_TOGGLE_COMMENT, + EDIT_MOVE_LINE_UP, + EDIT_MOVE_LINE_DOWN, + EDIT_INDENT_RIGHT, + EDIT_INDENT_LEFT, + EDIT_CLONE_DOWN, SEARCH_FIND, SEARCH_FIND_NEXT, SEARCH_REPLACE, @@ -212,7 +218,7 @@ public: void get_breakpoints(List<String> *p_breakpoints); - + void swap_lines(TextEdit *tx, int line1, int line2); void save_external_data(); diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp index 17c4291378..2fcd4e8cd1 100644 --- a/tools/editor/plugins/shader_editor_plugin.cpp +++ b/tools/editor/plugins/shader_editor_plugin.cpp @@ -57,9 +57,9 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader>& p_shader,ShaderLangu _load_theme_settings(); - if (p_type==ShaderLanguage::SHADER_MATERIAL_LIGHT) + if (p_type==ShaderLanguage::SHADER_MATERIAL_LIGHT || p_type==ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT) get_text_edit()->set_text(shader->get_light_code()); - else if (p_type==ShaderLanguage::SHADER_MATERIAL_VERTEX) + else if (p_type==ShaderLanguage::SHADER_MATERIAL_VERTEX || p_type==ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX) get_text_edit()->set_text(shader->get_vertex_code()); else get_text_edit()->set_text(shader->get_fragment_code()); @@ -80,6 +80,8 @@ void ShaderTextEditor::_load_theme_settings() { get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/text_color",Color(0,0,0))); get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/text_selected_color",Color(1,1,1))); get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/selection_color",Color(0.2,0.2,1))); + get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/brace_mismatch_color",Color(1,0.2,0.2))); + get_text_edit()->add_color_override("current_line_color",EDITOR_DEF("text_editor/current_line_color",Color(0.3,0.5,0.8,0.15))); Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2)); @@ -130,24 +132,22 @@ void ShaderTextEditor::_validate_script() { String errortxt; int line,col; - String code; - if (type==ShaderLanguage::SHADER_MATERIAL_LIGHT) - code=get_text_edit()->get_text(); - else if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) - code=get_text_edit()->get_text(); - else - code=get_text_edit()->get_text(); - + String code=get_text_edit()->get_text(); //List<StringName> params; //shader->get_param_list(¶ms); + print_line("compile: type: "+itos(type)+" code:\n"+code); + Error err = ShaderLanguage::compile(code,type,NULL,NULL,&errortxt,&line,&col); if (err!=OK) { - String error_text="error("+itos(line)+","+itos(col)+"): "+errortxt; + String error_text="error("+itos(line+1)+","+itos(col)+"): "+errortxt; set_error(error_text); + get_text_edit()->set_line_as_marked(line,true); } else { + for(int i=0;i<get_text_edit()->get_line_count();i++) + get_text_edit()->set_line_as_marked(i,false); set_error(""); } @@ -229,25 +229,7 @@ void ShaderEditor::_menu_option(int p_option) { goto_line_dialog->popup_find_line(current->get_text_edit()); } break; - case SHADER_POST_PROCESS_MODE:{ - - fragment_editor->set_edited_shader(shader,ShaderLanguage::SHADER_POST_PROCESS); - fragment_editor->_validate_script(); - apply_shaders(); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_MATERIAL_MODE), false); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_POST_PROCESS_MODE), true); - - - } break; - case SHADER_MATERIAL_MODE: { - fragment_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_FRAGMENT); - fragment_editor->_validate_script(); - apply_shaders(); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_MATERIAL_MODE), true); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_POST_PROCESS_MODE), false); - - } break; } } @@ -258,7 +240,7 @@ void ShaderEditor::_tab_changed(int p_which) { void ShaderEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { close->set_normal_texture( get_icon("Close","EditorIcons")); close->set_hover_texture( get_icon("CloseHover","EditorIcons")); @@ -404,18 +386,17 @@ void ShaderEditor::edit(const Ref<Shader>& p_shader) { shader=p_shader; if (shader->get_mode()==Shader::MODE_MATERIAL) { + vertex_editor->set_edited_shader(p_shader,ShaderLanguage::SHADER_MATERIAL_VERTEX); fragment_editor->set_edited_shader(p_shader,ShaderLanguage::SHADER_MATERIAL_FRAGMENT); light_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_LIGHT); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_MATERIAL_MODE), true); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_POST_PROCESS_MODE), false); - } else { + } else if (shader->get_mode()==Shader::MODE_CANVAS_ITEM) { - fragment_editor->set_edited_shader(p_shader,ShaderLanguage::SHADER_POST_PROCESS); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_MATERIAL_MODE), false); - settings_menu->get_popup()->set_item_checked( settings_menu->get_popup()->get_item_index(SHADER_POST_PROCESS_MODE), true); + vertex_editor->set_edited_shader(p_shader,ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX); + fragment_editor->set_edited_shader(p_shader,ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT); + light_editor->set_edited_shader(shader,ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT); } - vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX); + //vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX); // see if already has it @@ -491,15 +472,6 @@ ShaderEditor::ShaderEditor() { search_menu->get_popup()->add_item("Goto Line..",SEARCH_GOTO_LINE,KEY_MASK_CMD|KEY_G); search_menu->get_popup()->connect("item_pressed", this,"_menu_option"); - settings_menu = memnew( MenuButton ); - add_child(settings_menu); - settings_menu->set_pos(Point2(90,-1)); - settings_menu->set_text("Shader"); - settings_menu->get_popup()->add_check_item("Material Mode",SHADER_MATERIAL_MODE); - settings_menu->get_popup()->set_item_checked(settings_menu->get_popup()->get_item_index(SHADER_MATERIAL_MODE),true); - settings_menu->get_popup()->add_check_item("Post Process Mode",SHADER_POST_PROCESS_MODE); - - settings_menu->get_popup()->connect("item_pressed", this,"_menu_option"); tab_container->connect("tab_changed", this,"_tab_changed"); @@ -546,7 +518,13 @@ void ShaderEditorPlugin::edit(Object *p_object) { bool ShaderEditorPlugin::handles(Object *p_object) const { - return p_object->is_type("Shader"); + Shader *shader=p_object->cast_to<Shader>(); + if (!shader) + return false; + if (_2d) + return shader->get_mode()==Shader::MODE_CANVAS_ITEM; + else + return shader->get_mode()==Shader::MODE_MATERIAL; } void ShaderEditorPlugin::make_visible(bool p_visible) { @@ -592,12 +570,15 @@ void ShaderEditorPlugin::apply_changes() { shader_editor->apply_shaders(); } -ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) { +ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node, bool p_2d) { editor=p_node; shader_editor = memnew( ShaderEditor ); - - SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor); + _2d=p_2d; + if (p_2d) + add_custom_control(CONTAINER_CANVAS_EDITOR_BOTTOM,shader_editor); + else + add_custom_control(CONTAINER_SPATIAL_EDITOR_BOTTOM,shader_editor); // editor->get_viewport()->add_child(shader_editor); // shader_editor->set_area_as_parent_rect(); diff --git a/tools/editor/plugins/shader_editor_plugin.h b/tools/editor/plugins/shader_editor_plugin.h index 49caee5da6..daaa0ccb94 100644 --- a/tools/editor/plugins/shader_editor_plugin.h +++ b/tools/editor/plugins/shader_editor_plugin.h @@ -79,9 +79,6 @@ class ShaderEditor : public Control { SEARCH_REPLACE, //SEARCH_LOCATE_SYMBOL, SEARCH_GOTO_LINE, - SHADER_MATERIAL_MODE, - SHADER_POST_PROCESS_MODE, - SHADER_SHADE_MODEL_MODE, }; @@ -134,6 +131,7 @@ class ShaderEditorPlugin : public EditorPlugin { OBJ_TYPE( ShaderEditorPlugin, EditorPlugin ); + bool _2d; ShaderEditor *shader_editor; EditorNode *editor; public: @@ -152,7 +150,7 @@ public: virtual void save_external_data(); virtual void apply_changes(); - ShaderEditorPlugin(EditorNode *p_node); + ShaderEditorPlugin(EditorNode *p_node,bool p_2d); ~ShaderEditorPlugin(); }; diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 2686ca895e..e829c06e6f 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -28,1082 +28,2363 @@ /*************************************************************************/ #include "shader_graph_editor_plugin.h" -#if 0 + #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" +#include "spatial_editor_plugin.h" +#include "os/keyboard.h" +#include "canvas_item_editor_plugin.h" -class _ShaderTester : public ShaderCodeGenerator { -public: +void GraphColorRampEdit::_input_event(const InputEvent& p_event) { - Set<int> *_set; + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { - virtual void begin() {} - virtual Error add_node(VS::ShaderNodeType p_type,int p_node_pos,int p_id,const Variant& p_param,const Vector<int>& p_in_connections,const Vector<int>& p_out_connections,const Vector<int>& p_out_connection_outputs) { if (_set) _set->insert(p_id); return OK; } - virtual void end() {} + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("ramp_changed"); + accept_event(); + } - _ShaderTester() { _set=NULL; } -}; + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + int x = p_event.mouse_button.x; + int total_w = get_size().width-get_size().height-3; + if (x>total_w+3) { + + if (grabbed==-1) + return; + Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10); + picker->set_color(points[grabbed].color); + popup->set_pos(get_global_pos()-Size2(0,ms.height)); + popup->set_size(ms); + popup->popup(); + return; + } + float ofs = CLAMP(x/float(total_w),0,1); -void ShaderEditor::edit(Ref<Shader> p_shader) { + grabbed=-1; + grabbing=true; + int pos=-1; + for(int i=0;i<points.size();i++) { + if (ABS(x-points[i].offset*total_w)<4) { + grabbed=i; + } + if (points[i].offset<ofs) + pos=i; + } - shader=p_shader; + grabbed_at=ofs; + //grab or select + if (grabbed!=-1) { + return; + } + //insert - if (shader.is_null()) - hide(); - else { - _read_shader_graph(); - } -} + Point p; + p.offset=ofs; -Size2 ShaderEditor::_get_maximum_size() { + Point prev; + Point next; - Size2 max; + if (pos==-1) { - for(List<int>::Element *E=order.front();E;E=E->next()) { + prev.color=Color(0,0,0); + prev.offset=0; + if (points.size()) { + next=points[0]; + } else { + next.color=Color(1,1,1); + next.offset=1.0; + } + } else { - Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) ); + if (pos==points.size()-1) { + next.color=Color(1,1,1); + next.offset=1.0; + } else { + next=points[pos+1]; + } + prev=points[pos]; + + } - if (click_type==CLICK_NODE && click_node==E->get()) { + p.color=prev.color.linear_interpolate(next.color,(p.offset-prev.offset)/(next.offset-prev.offset)); - pos+=click_motion-click_pos; + points.push_back(p); + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==ofs) { + grabbed=i; + break; + } } - pos+=get_node_size(E->get()); - if (pos.x>max.x) - max.x=pos.x; - if (pos.y>max.y) - max.y=pos.y; + + emit_signal("ramp_changed"); } - return max; -} + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) { -Size2 ShaderEditor::get_node_size(int p_node) const { + if (grabbing) { + grabbing=false; + emit_signal("ramp_changed"); + } + update(); + } - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - Ref<Font> font = get_font("font","PopupMenu"); - Color font_color = get_color("font_color","PopupMenu"); + if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) { - Size2 size = style->get_minimum_size(); + int total_w = get_size().width-get_size().height-3; - int count=1; // title - count += VisualServer::shader_get_input_count( type) + VisualServer::shader_get_output_count( type); + int x = p_event.mouse_motion.x; + float newofs = CLAMP(x/float(total_w),0,1); - float max_w=font->get_string_size( VisualServer::shader_node_get_type_info(type).name ).width; + bool valid=true; + for(int i=0;i<points.size();i++) { - for(int i=0;i<VisualServer::shader_get_input_count(type);i++) - max_w = MAX( max_w, font->get_string_size( VisualServer::shader_get_input_name(type,i) ).width ); + if (points[i].offset==newofs && i!=grabbed) { + valid=false; + } + } + + if (!valid) + return; + points[grabbed].offset=newofs; - for(int i=0;i<VisualServer::shader_get_output_count(type);i++) - max_w = MAX( max_w, font->get_string_size( VisualServer::shader_get_output_name(type,i) ).width ); + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==newofs) { + grabbed=i; + break; + } + } + emit_signal("ramp_changed"); + update(); + } +} +void GraphColorRampEdit::_notification(int p_what){ - switch(type) { + if (p_what==NOTIFICATION_ENTER_TREE) { + picker->connect("color_changed",this,"_color_changed"); + } + if (p_what==NOTIFICATION_DRAW) { - case VS::NODE_IN: - case VS::NODE_OUT: - case VS::NODE_VEC_IN: - case VS::NODE_VEC_OUT: - case VS::NODE_PARAMETER: - case VS::NODE_VEC_PARAMETER: - case VS::NODE_COLOR_PARAMETER: - case VS::NODE_TEXTURE_PARAMETER: - case VS::NODE_TEXTURE_2D_PARAMETER: - case VS::NODE_TEXTURE_CUBE_PARAMETER: - case VS::NODE_TRANSFORM_PARAMETER: - case VS::NODE_LABEL: { - max_w=MAX( max_w, font->get_string_size( shader_graph.node_get_param(p_node) ).width ); - count++; - } break; - case VS::NODE_TIME: - case VS::NODE_CONSTANT: - case VS::NODE_VEC_CONSTANT: - case VS::NODE_COLOR_CONSTANT: - case VS::NODE_TRANSFORM_CONSTANT: { - count++; - } break; - case VS::NODE_TEXTURE: - case VS::NODE_VEC_TEXTURE_2D: - case VS::NODE_VEC_TEXTURE_CUBE: { + Point prev; + prev.offset=0; + prev.color=Color(0,0,0); + int w = get_size().x; + int h = get_size().y; - RefPtr res = shader_graph.node_get_param(p_node); - Ref<Texture> texture = res; - if (texture.is_null() || texture->get_width()==0) { + int total_w = get_size().width-get_size().height-3; - size.y+=max_w; + for(int i=-1;i<points.size();i++) { + + Point next; + if (i+1==points.size()) { + next.color=Color(1,1,1); + next.offset=1; } else { + next=points[i+1]; + } - size.y+=max_w * texture->get_height() / texture->get_width(); + if (prev.offset==next.offset) { + prev=next; + continue; } - } break; - default: {} + Vector<Vector2> points; + Vector<Color> colors; + points.push_back(Vector2(prev.offset*total_w,h)); + points.push_back(Vector2(prev.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,h)); + colors.push_back(prev.color); + colors.push_back(prev.color); + colors.push_back(next.color); + colors.push_back(next.color); + draw_primitive(points,colors,Vector<Point2>()); + prev=next; + } + + for(int i=0;i<points.size();i++) { + + Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8); + + draw_line(Vector2(points[i].offset*total_w,0),Vector2(points[i].offset*total_w,h-1),Color(0,0,0,0.7)); + draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w-1,h-1),col); + draw_line(Vector2(points[i].offset*total_w+1,h/2),Vector2(points[i].offset*total_w+1,h-1),col); + draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w+1,h/2),col); + draw_line(Vector2(points[i].offset*total_w-1,h-1),Vector2(points[i].offset*total_w+1,h-1),col); + + } + + if (grabbed!=-1) { + + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } + + if (has_focus()) { + + draw_line(Vector2(-1,-1),Vector2(total_w+1,-1),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+1,-1),Vector2(total_w+1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6)); + } + + } +} + +Size2 GraphColorRampEdit::get_minimum_size() const { + + return Vector2(0,16); +} + + +void GraphColorRampEdit::_color_changed(const Color& p_color) { + + if (grabbed==-1) + return; + points[grabbed].color=p_color; + update(); + emit_signal("ramp_changed"); + +} + +void GraphColorRampEdit::set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors) { + + ERR_FAIL_COND(p_offsets.size()!=p_colors.size()); + points.clear(); + for(int i=0;i<p_offsets.size();i++) { + Point p; + p.offset=p_offsets[i]; + p.color=p_colors[i]; + points.push_back(p); } - size.x+=max_w; - size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu")); + points.sort(); + update(); +} - return size; +Vector<float> GraphColorRampEdit::get_offsets() const{ + Vector<float> ret; + for(int i=0;i<points.size();i++) + ret.push_back(points[i].offset); + return ret; } +Vector<Color> GraphColorRampEdit::get_colors() const{ + Vector<Color> ret; + for(int i=0;i<points.size();i++) + ret.push_back(points[i].color); + return ret; +} -Error ShaderEditor::validate_graph() { - _ShaderTester st; - active_nodes.clear(); - st._set=&active_nodes; - return shader_graph.generate(&st); +void GraphColorRampEdit::_bind_methods(){ + + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphColorRampEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_color_changed"),&GraphColorRampEdit::_color_changed); + ADD_SIGNAL(MethodInfo("ramp_changed")); } -void ShaderEditor::_draw_node(int p_node) { +GraphColorRampEdit::GraphColorRampEdit(){ + + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); + + popup = memnew( PopupPanel ); + picker = memnew( ColorPicker ); + popup->add_child(picker); + popup->set_child_rect(picker); + add_child(popup); - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - Ref<StyleBox> style = active_nodes.has(p_node)?get_stylebox("panel","PopupMenu"):get_stylebox("panel_disabled","PopupMenu"); - Ref<Font> font = get_font("font","PopupMenu"); - Color font_color = get_color("font_color","PopupMenu"); - Color font_color_title = get_color("font_color_hover","PopupMenu"); - Size2 size=get_node_size(p_node); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset; +} +//////////// - if (click_type==CLICK_NODE && click_node==p_node) { +void GraphCurveMapEdit::_input_event(const InputEvent& p_event) { - pos+=click_motion-click_pos; + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { + + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("curve_changed"); + accept_event(); } - RID ci = get_canvas_item(); - style->draw(ci,Rect2(pos,size)); + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size(); + p.y=1.0-p.y; + grabbed=-1; + grabbing=true; - Point2 ofs=style->get_offset()+pos; - Point2 ascent=Point2(0,font->get_ascent()); - float w = size.width-style->get_minimum_size().width; - float h = font->get_height()+get_constant("vseparation","PopupMenu"); + for(int i=0;i<points.size();i++) { - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, VisualServer::shader_node_get_type_info(type).name,font_color_title); - ofs.y+=h; + Vector2 ps = p*get_size(); + Vector2 pt = Vector2(points[i].offset,points[i].height)*get_size(); + if (ps.distance_to(pt)<4) { + grabbed=i; + } + + } + + + //grab or select + if (grabbed!=-1) { + return; + } + //insert - Ref<Texture> vec_icon = get_icon("NodeVecSlot","EditorIcons"); - Ref<Texture> real_icon = get_icon("NodeRealSlot","EditorIcons"); - float icon_h_ofs = Math::floor(( font->get_height()-vec_icon->get_height())/2.0 )+1; + Point np; + np.offset=p.x; + np.height=p.y; - for(int i=0;i<VisualServer::shader_get_input_count(type);i++) { + points.push_back(np); + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==p.x && points[i].height==p.y) { + grabbed=i; + break; + } + } + + emit_signal("curve_changed"); - String name = VisualServer::shader_get_input_name(type,i); - font->draw_halign( ci, ofs+ascent, HALIGN_LEFT,w, name,font_color); - Ref<Texture> icon = VisualServer::shader_is_input_vector(type,i)?vec_icon:real_icon; - icon->draw(ci,ofs+Point2(-real_icon->get_width(),icon_h_ofs)); - ofs.y+=h; } - for(int i=0;i<VisualServer::shader_get_output_count(type);i++) { + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) { - String name = VisualServer::shader_get_output_name(type,i); - font->draw_halign( ci, ofs+ascent, HALIGN_RIGHT,w, name,font_color); - Ref<Texture> icon = VisualServer::shader_is_output_vector(type,i)?vec_icon:real_icon; - icon->draw(ci,ofs+Point2(w,icon_h_ofs)); - ofs.y+=h; + if (grabbing) { + grabbing=false; + emit_signal("curve_changed"); + } + update(); } - switch(type) { - - case VS::NODE_IN: - case VS::NODE_OUT: - case VS::NODE_PARAMETER: - case VS::NODE_VEC_IN: - case VS::NODE_COLOR_PARAMETER: - case VS::NODE_VEC_OUT: - case VS::NODE_TEXTURE_PARAMETER: - case VS::NODE_TEXTURE_2D_PARAMETER: - case VS::NODE_TEXTURE_CUBE_PARAMETER: - case VS::NODE_TRANSFORM_CONSTANT: - case VS::NODE_TRANSFORM_PARAMETER: - case VS::NODE_VEC_PARAMETER: - case VS::NODE_LABEL: { - String text = shader_graph.node_get_param(p_node); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - } break; - case VS::NODE_TIME: - case VS::NODE_CONSTANT: { - String text = rtos(shader_graph.node_get_param(p_node)); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); + if (p_event.type==InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) { - } break; - case VS::NODE_VEC_CONSTANT: { - String text = Vector3(shader_graph.node_get_param(p_node)); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - } break; - case VS::NODE_COLOR_CONSTANT: { + Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size(); + p.y=1.0-p.y; - Color color = shader_graph.node_get_param(p_node); - Rect2 r(ofs,Size2(w,h)); - VisualServer::get_singleton()->canvas_item_add_rect(ci,r,color); - } break; - case VS::NODE_TEXTURE: - case VS::NODE_VEC_TEXTURE_2D: - case VS::NODE_VEC_TEXTURE_CUBE: { - - Rect2 r(ofs,Size2(w,(pos.y+size.y-style->get_margin(MARGIN_BOTTOM))-ofs.y)); - Vector<Point2> points; - Vector<Point2> uvs; - points.resize(4); - uvs.resize(4); - points[0]=r.pos; - points[1]=r.pos+Point2(r.size.x,0); - points[2]=r.pos+r.size; - points[3]=r.pos+Point2(0,r.size.y); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - Ref<Texture> texture = shader_graph.node_get_param(p_node).operator RefPtr(); - if (texture.is_null() || texture->get_width()==0) { - texture=get_icon("Click2Edit","EditorIcons"); + p.x = CLAMP(p.x,0.0,1.0); + p.y = CLAMP(p.y,0.0,1.0); + + bool valid=true; + + for(int i=0;i<points.size();i++) { + + if (points[i].offset==p.x && points[i].height==p.y && i!=grabbed) { + valid=false; } + } - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); - } break; - default: {} + if (!valid) + return; + + points[grabbed].offset=p.x; + points[grabbed].height=p.y; + + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==p.x && points[i].height==p.y) { + grabbed=i; + break; + } + } + + emit_signal("curve_changed"); + + update(); } } -void ShaderEditor::_node_param_changed() { +void GraphCurveMapEdit::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d) { + + float geometry[4][4]; + float tmp1[4][4]; + float tmp2[4][4]; + float deltas[4][4]; + double x, dx, dx2, dx3; + double y, dy, dy2, dy3; + double d, d2, d3; + int lastx, lasty; + int newx, newy; + int ntimes; + int i,j; + + int xmax=get_size().x; + int ymax=get_size().y; + + /* construct the geometry matrix from the segment */ + for (i = 0; i < 4; i++) { + geometry[i][2] = 0; + geometry[i][3] = 0; + } - shader_graph.node_set_param( click_node,property_editor->get_variant() ); - update(); - _write_shader_graph(); + geometry[0][0] = (p_a[0] * xmax); + geometry[1][0] = (p_b[0] * xmax); + geometry[2][0] = (p_c[0] * xmax); + geometry[3][0] = (p_d[0] * xmax); + + geometry[0][1] = (p_a[1] * ymax); + geometry[1][1] = (p_b[1] * ymax); + geometry[2][1] = (p_c[1] * ymax); + geometry[3][1] = (p_d[1] * ymax); + + /* subdivide the curve ntimes (1000) times */ + ntimes = 4 * xmax; + /* ntimes can be adjusted to give a finer or coarser curve */ + d = 1.0 / ntimes; + d2 = d * d; + d3 = d * d * d; + + /* construct a temporary matrix for determining the forward differencing deltas */ + tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; + tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; + tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; + tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; + + /* compose the basis and geometry matrices */ + + static const float CR_basis[4][4] = + { + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, + }; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); + } + } + /* compose the above results to get the deltas matrix */ + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); + } + } + + + /* extract the x deltas */ + x = deltas[0][0]; + dx = deltas[1][0]; + dx2 = deltas[2][0]; + dx3 = deltas[3][0]; + + /* extract the y deltas */ + y = deltas[0][1]; + dy = deltas[1][1]; + dy2 = deltas[2][1]; + dy3 = deltas[3][1]; + + + lastx = CLAMP (x, 0, xmax); + lasty = CLAMP (y, 0, ymax); + +/* if (fix255) + { + cd->curve[cd->outline][lastx] = lasty; + } + else + { + cd->curve_ptr[cd->outline][lastx] = lasty; + if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax); + } +*/ + /* loop over the curve */ + for (i = 0; i < ntimes; i++) + { + /* increment the x values */ + x += dx; + dx += dx2; + dx2 += dx3; + + /* increment the y values */ + y += dy; + dy += dy2; + dy2 += dy3; + + newx = CLAMP ((Math::round (x)), 0, xmax); + newy = CLAMP ((Math::round (y)), 0, ymax); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) + { +#if 0 + /* + if(fix255) + { + /* use fixed array size (for the curve graph) */ + cd->curve[cd->outline][newx] = newy; + } + else + { + /* use dynamic allocated curve_ptr (for the real curve) */ + cd->curve_ptr[cd->outline][newx] = newy; + + if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy); + } +#endif + draw_line(Vector2(lastx,ymax-lasty),Vector2(newx,ymax-newy),Color(0.8,0.8,0.8,0.8),2.0); + } + + lastx = newx; + lasty = newy; + } } -ShaderEditor::ClickType ShaderEditor::_locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const { - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - Ref<Texture> real_icon = get_icon("NodeRealSlot","EditorIcons"); - Ref<Font> font = get_font("font","PopupMenu"); - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - float extra_left=MAX( real_icon->get_width()-style->get_margin(MARGIN_LEFT), 0 ); - float extra_right=MAX( real_icon->get_width()-style->get_margin(MARGIN_RIGHT), 0 ); +void GraphCurveMapEdit::_notification(int p_what){ + if (p_what==NOTIFICATION_DRAW) { - for(const List<int>::Element *E=order.back();E;E=E->prev()) { + draw_style_box(get_stylebox("bg","Tree"),Rect2(Point2(),get_size())); - Size2 size=get_node_size(E->get()); - size.width+=extra_left+extra_right; - Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) )-offset; - pos.x-=extra_left; + int w = get_size().x; + int h = get_size().y; - Rect2 rect( pos, size ); - if (!rect.has_point(p_click)) - continue; - VisualServer::ShaderNodeType type=shader_graph.node_get_type(E->get()); - if (p_node_id) - *p_node_id=E->get(); - float y=p_click.y-(pos.y+style->get_margin(MARGIN_TOP)); - if (y<h) - return CLICK_NODE; - y-=h; + Vector2 prev=Vector2(0,0); + Vector2 prev2=Vector2(0,0); - for(int i=0;i<VisualServer::shader_get_input_count(type);i++) { + for(int i=-1;i<points.size();i++) { - if (y<h) { - if (p_slot_index) - *p_slot_index=i; - return CLICK_INPUT_SLOT; + Vector2 next; + Vector2 next2; + if (i+1>=points.size()) { + next=Vector2(1,1); + } else { + next=Vector2(points[i+1].offset,points[i+1].height); } - y-=h; + + if (i+2>=points.size()) { + next2=Vector2(1,1); + } else { + next2=Vector2(points[i+2].offset,points[i+2].height); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2,prev,next,next2); + + prev2=prev; + prev=next; } - for(int i=0;i<VisualServer::shader_get_output_count(type);i++) { + for(int i=0;i<points.size();i++) { - if (y<h) { - if (p_slot_index) - *p_slot_index=i; - return CLICK_OUTPUT_SLOT; - } - y-=h; + Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8); + + + draw_rect(Rect2( Vector2(points[i].offset,1.0-points[i].height)*get_size()-Vector2(2,2),Vector2(5,5)),col); } - if (p_click.y<(rect.pos.y+rect.size.height-style->get_margin(MARGIN_BOTTOM))) - return CLICK_PARAMETER; - else - return CLICK_NODE; +/* if (grabbed!=-1) { + + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } +*/ + if (has_focus()) { + + draw_line(Vector2(-1,-1),Vector2(w+1,-1),Color(1,1,1,0.6)); + draw_line(Vector2(w+1,-1),Vector2(w+1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6)); + } } +} - return CLICK_NONE; +Size2 GraphCurveMapEdit::get_minimum_size() const { + return Vector2(64,64); } -Point2 ShaderEditor::_get_slot_pos(int p_node_id,bool p_input,int p_slot) { - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - float w = get_node_size(p_node_id).width; - Ref<Font> font = get_font("font","PopupMenu"); - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - Ref<Texture> vec_icon = get_icon("NodeVecSlot","EditorIcons"); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node_id), shader_graph.node_get_pos_y(p_node_id) )-offset; - pos+=style->get_offset(); - pos.y+=h; - if(p_input) { +void GraphCurveMapEdit::set_points(const Vector<Vector2>& p_points) { - pos.y+=p_slot*h; - pos+=Point2( -vec_icon->get_width()/2.0, h/2.0).floor(); - return pos; - } else { - pos.y+=VisualServer::shader_get_input_count( shader_graph.node_get_type(p_node_id ) )*h; + points.clear(); + for(int i=0;i<p_points.size();i++) { + Point p; + p.offset=p_points[i].x; + p.height=p_points[i].y; + points.push_back(p); } - pos.y+=p_slot*h; - pos+=Point2( w-style->get_minimum_size().width+vec_icon->get_width()/2.0, h/2.0).floor(); - - return pos; + points.sort(); + update(); +} +Vector<Vector2> GraphCurveMapEdit::get_points() const { + Vector<Vector2> ret; + for(int i=0;i<points.size();i++) + ret.push_back(Vector2(points[i].offset,points[i].height)); + return ret; } -void ShaderEditor::_node_edit_property(int p_node) { +void GraphCurveMapEdit::_bind_methods(){ - Ref<StyleBox> style = get_stylebox("panel","PopupMenu"); - Size2 size = get_node_size(p_node); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset; + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphCurveMapEdit::_input_event); + ADD_SIGNAL(MethodInfo("curve_changed")); +} - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); +GraphCurveMapEdit::GraphCurveMapEdit(){ - PropertyInfo ph = VisualServer::get_singleton()->shader_node_get_type_info(type); - if (ph.type==Variant::NIL) - return; - if (ph.type==Variant::_RID) - ph.type=Variant::OBJECT; + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); - property_editor->edit(NULL,ph.name,ph.type,shader_graph.node_get_param(p_node),ph.hint,ph.hint_string); +} - Point2 popup_pos=Point2( pos.x+(size.width-property_editor->get_size().width)/2.0,pos.y+(size.y-style->get_margin(MARGIN_BOTTOM))).floor(); - popup_pos+=get_global_pos(); - property_editor->set_pos(popup_pos); - property_editor->popup(); +////cbacks +/// +void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Constant",true); + ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value); + ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; } -bool ShaderEditor::has_point(const Point2& p_point) const { +void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){ - int n,si; + Vector3 val; + for(int i=0;i<p_arr.size();i++) { + val[i]=p_arr[i].call("get_val"); + } - return _locate_click(p_point,&n,&si)!=CLICK_NONE; -} + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Constant",true); + ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val); + ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; -void ShaderEditor::_input_event(InputEvent p_event) { - - switch(p_event.type) { - - case InputEvent::MOUSE_BUTTON: { - - if (p_event.mouse_button.pressed) { - - - if (p_event.mouse_button.button_index==1) { - click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - click_motion=click_pos; - click_type = _locate_click(click_pos,&click_node,&click_slot); - if( click_type!=CLICK_NONE) { - - order.erase(click_node); - order.push_back(click_node); - update(); - } - switch(click_type) { - case CLICK_INPUT_SLOT: { - click_pos=_get_slot_pos(click_node,true,click_slot); - } break; - case CLICK_OUTPUT_SLOT: { - click_pos=_get_slot_pos(click_node,false,click_slot); - } break; - case CLICK_PARAMETER: { - //open editor - _node_edit_property(click_node); - } break; - } - } - if (p_event.mouse_button.button_index==2) { +} +void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Constant",true); + ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color); + ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - if (click_type!=CLICK_NONE) { - click_type=CLICK_NONE; - update(); - } else { - // try to disconnect/remove +} +void ShaderGraphView::_scalar_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Operator"); + ur->add_do_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,graph->scalar_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - Point2 rclick_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - rclick_type = _locate_click(rclick_pos,&rclick_node,&rclick_slot); - if (rclick_type==CLICK_INPUT_SLOT || rclick_type==CLICK_OUTPUT_SLOT) { +} +void ShaderGraphView::_vec_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Operator"); + ur->add_do_method(graph.ptr(),"vec_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"vec_op_node_set_op",type,p_id,graph->vec_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change VecxScalar Operator"); + ur->add_do_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,graph->vec_scalar_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - node_popup->clear(); - node_popup->add_item("Disconnect",NODE_DISCONNECT); - node_popup->set_pos(rclick_pos); - node_popup->popup(); +} +void ShaderGraphView::_rgb_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Operator"); + ur->add_do_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,graph->rgb_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Toggle Rot Only"); + ur->add_do_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,p_enabled); + ur->add_undo_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,graph->xform_vec_mult_node_get_no_translation(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_scalar_func_changed(int p_func, int p_id){ + + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Function"); + ur->add_do_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,p_func); + ur->add_undo_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,graph->scalar_func_node_get_function(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_func_changed(int p_func, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Function"); + ur->add_do_method(graph.ptr(),"vec_func_node_set_function",type,p_id,p_func); + ur->add_undo_method(graph.ptr(),"vec_func_node_set_function",type,p_id,graph->vec_func_node_get_function(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - } +} +void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Uniform",true); + ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value); + ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - if (rclick_type==CLICK_NODE) { - node_popup->clear(); - node_popup->add_item("Remove",NODE_ERASE); - node_popup->set_pos(rclick_pos); - node_popup->popup(); - } +} +void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){ + Vector3 val; + for(int i=0;i<p_arr.size();i++) { + val[i]=p_arr[i].call("get_val"); + } - } - } - } else { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Uniform",true); + ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val); + ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) { +} +void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){ - switch(click_type) { - case CLICK_INPUT_SLOT: - case CLICK_OUTPUT_SLOT: { - Point2 dst_click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - int id; - int slot; - ClickType dst_click_type = _locate_click(dst_click_pos,&id,&slot); - if (dst_click_type==CLICK_INPUT_SLOT && click_type==CLICK_OUTPUT_SLOT) { + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); + ped_popup->popup(); - shader_graph.connect(click_node,click_slot,id,slot); +} +void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){ - Error err = validate_graph(); - if (err==ERR_CYCLIC_LINK) - shader_graph.disconnect(click_node,click_slot,id,slot); - _write_shader_graph(); + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); + ped_popup->popup(); - } - if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) { +} - shader_graph.connect(id,slot,click_node,click_slot); +void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){ - Error err = validate_graph(); - if (err==ERR_CYCLIC_LINK) - shader_graph.disconnect(id,slot,click_node,click_slot); - _write_shader_graph(); - } - } break; - case CLICK_NODE: { - int new_x=shader_graph.node_get_pos_x(click_node)+(click_motion.x-click_pos.x); - int new_y=shader_graph.node_get_pos_y(click_node)+(click_motion.y-click_pos.y); - shader_graph.node_set_pos(click_node,new_x,new_y); - _write_shader_graph(); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Uniform",true); + ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color); + ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_tex_input_change(int p_id, Node *p_button){ - } break; - } - click_type=CLICK_NONE; - update(); - } - } +} +void ShaderGraphView::_cube_input_change(int p_id){ - } - case InputEvent::MOUSE_MOTION: { +} - if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) { +void ShaderGraphView::_variant_edited() { - click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - update(); - } + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) { - } break; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change XForm Uniform"); + ur->add_do_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,graph->xform_const_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); } -} -void ShaderEditor::_notification(int p_what) { + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) { - switch(p_what) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change XForm Uniform"); + ur->add_do_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,graph->xform_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } - case NOTIFICATION_DRAW: { + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) { - _update_scrollbars(); - //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1)); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Texture Uniform"); + ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,graph->texture_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } - for(List<int>::Element *E=order.front();E;E=E->next()) { + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) { - _draw_node(E->get()); - } + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Cubemap Uniform"); + ur->add_do_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,graph->cubemap_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } - if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) { +} - VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),click_pos,click_motion,Color(0.5,1,0.5,0.8),2); - } +void ShaderGraphView::_comment_edited(int p_id,Node* p_button) { - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + TextEdit *te=p_button->cast_to<TextEdit>(); + ur->create_action("Change Comment",true); + ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text()); + ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - const ShaderGraph::Connection &c=E->get(); - Point2 source = _get_slot_pos(c.src_id,false,c.src_slot); - Point2 dest = _get_slot_pos(c.dst_id,true,c.dst_slot); - bool vec = VisualServer::shader_is_input_vector( shader_graph.node_get_type(c.dst_id), c.dst_slot ); - Color col = vec?Color(1,0.5,0.5,0.8):Color(1,1,0.5,0.8); +} - if (click_type==CLICK_NODE && click_node==c.src_id) { +void ShaderGraphView::_color_ramp_changed(int p_id,Node* p_ramp) { - source+=click_motion-click_pos; - } + GraphColorRampEdit *cr=p_ramp->cast_to<GraphColorRampEdit>(); - if (click_type==CLICK_NODE && click_node==c.dst_id) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - dest+=click_motion-click_pos; - } - VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),source,dest,col,2); + Vector<float> offsets=cr->get_offsets(); + Vector<Color> colors=cr->get_colors(); + + DVector<float> new_offsets; + DVector<Color> new_colors; + { + new_offsets.resize(offsets.size()); + new_colors.resize(colors.size()); + DVector<float>::Write ow=new_offsets.write(); + DVector<Color>::Write cw=new_colors.write(); + for(int i=0;i<new_offsets.size();i++) { + ow[i]=offsets[i]; + cw[i]=colors[i]; + } - } - } break; } -} -void ShaderEditor::_update_scrollbars() { + DVector<float> old_offsets=graph->color_ramp_node_get_offsets(type,p_id); + DVector<Color> old_colors=graph->color_ramp_node_get_colors(type,p_id); - Size2 size = get_size(); - Size2 hmin = h_scroll->get_minimum_size(); - Size2 vmin = v_scroll->get_minimum_size(); + if (old_offsets.size()!=new_offsets.size()) + ur->create_action("Add/Remove to Color Ramp"); + else + ur->create_action("Modify Color Ramp",true); - v_scroll->set_begin( Point2(size.width - vmin.width, 0) ); - v_scroll->set_end( Point2(size.width, size.height) ); + ur->add_do_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,new_colors,new_offsets); + ur->add_undo_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,old_colors,old_offsets); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} - h_scroll->set_begin( Point2( 0, size.height - hmin.height) ); - h_scroll->set_end( Point2(size.width-vmin.width, size.height) ); +void ShaderGraphView::_curve_changed(int p_id,Node* p_curve) { + GraphCurveMapEdit *cr=p_curve->cast_to<GraphCurveMapEdit>(); - Size2 min = _get_maximum_size(); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - if (min.height < size.height - hmin.height) { - v_scroll->hide(); - offset.y=0; - } else { + Vector<Point2> points=cr->get_points(); + + DVector<Vector2> new_points; + { + new_points.resize(points.size()); + DVector<Vector2>::Write ow=new_points.write(); + for(int i=0;i<new_points.size();i++) { + ow[i]=points[i]; + } - v_scroll->show(); - v_scroll->set_max(min.height); - v_scroll->set_page(size.height - hmin.height); - offset.y=v_scroll->get_val(); } - if (min.width < size.width - vmin.width) { - h_scroll->hide(); - offset.x=0; - } else { + DVector<Vector2> old_points=graph->curve_map_node_get_points(type,p_id); - h_scroll->show(); - h_scroll->set_max(min.width); - h_scroll->set_page(size.width - vmin.width); - offset.x=h_scroll->get_val(); - } + if (old_points.size()!=new_points.size()) + ur->create_action("Add/Remove to Curve Map"); + else + ur->create_action("Modify Curve Map",true); + + ur->add_do_method(graph.ptr(),"curve_map_node_set_points",type,p_id,new_points); + ur->add_undo_method(graph.ptr(),"curve_map_node_set_points",type,p_id,old_points); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; } -void ShaderEditor::_scroll_moved() { - offset.x=h_scroll->get_val(); - offset.y=v_scroll->get_val(); - update(); +void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) { + + LineEdit *le=p_line_edit->cast_to<LineEdit>(); + ERR_FAIL_COND(!le); + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Input Name"); + ur->add_do_method(graph.ptr(),"input_node_set_name",type,p_id,p_name); + ur->add_undo_method(graph.ptr(),"input_node_set_name",type,p_id,graph->input_node_get_name(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + le->set_text(graph->input_node_get_name(type,p_id)); +} + +void ShaderGraphView::_tex_edited(int p_id,Node* p_button) { + + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture"); } -void ShaderEditor::_bind_methods() { +void ShaderGraphView::_cube_edited(int p_id,Node* p_button) { - ObjectTypeDB::bind_method( "_node_menu_item", &ShaderEditor::_node_menu_item ); - ObjectTypeDB::bind_method( "_node_add_callback", &ShaderEditor::_node_add_callback ); - ObjectTypeDB::bind_method( "_input_event", &ShaderEditor::_input_event ); - ObjectTypeDB::bind_method( "_node_param_changed", &ShaderEditor::_node_param_changed ); - ObjectTypeDB::bind_method( "_scroll_moved", &ShaderEditor::_scroll_moved ); - ObjectTypeDB::bind_method( "_vertex_item", &ShaderEditor::_vertex_item ); - ObjectTypeDB::bind_method( "_fragment_item", &ShaderEditor::_fragment_item ); - ObjectTypeDB::bind_method( "_post_item", &ShaderEditor::_post_item ); + ToolButton *tb = p_button->cast_to<ToolButton>(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"); } -void ShaderEditor::_read_shader_graph() { - shader_graph.clear();; - order.clear(); - List<int> nodes; - shader->get_node_list(&nodes); - int larger_id=0; - for(List<int>::Element *E=nodes.front();E;E=E->next()) { +//////////////view///////////// + + +void ShaderGraphView::_connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - if (E->get() > larger_id) - larger_id = E->get(); + int from_idx=-1; + int to_idx=-1; + for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { - shader_graph.node_add( (VS::ShaderNodeType)shader->node_get_type(E->get()), E->get() ); - shader_graph.node_set_param( E->get(), shader->node_get_param( E->get() ) ); - Point2 pos = shader->node_get_pos(E->get()); - shader_graph.node_set_pos( E->get(), pos.x,pos.y ); - order.push_back(E->get()); + if (p_from==E->get()->get_name()) + from_idx=E->key(); + if (p_to==E->get()->get_name()) + to_idx=E->key(); } - last_id=larger_id+1; + ERR_FAIL_COND(from_idx==-1); + ERR_FAIL_COND(to_idx==-1); - List<Shader::Connection> connections; - shader->get_connections(&connections); + ur->create_action("Connect Graph Nodes"); - for(List<Shader::Connection>::Element *E=connections.front();E;E=E->next()) { + List<ShaderGraph::Connection> conns; - Shader::Connection &c=E->get(); - shader_graph.connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); + graph->get_node_connections(type,&conns); + //disconnect/reconnect dependencies + ur->add_undo_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) { + + if (E->get().dst_id==to_idx && E->get().dst_slot==p_to_slot) { + ur->add_do_method(graph.ptr(),"disconnect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + } } + ur->add_do_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + - validate_graph(); - update(); } -void ShaderEditor::_write_shader_graph() { +void ShaderGraphView::_disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - shader->clear(); - List<int> nodes; - shader_graph.get_node_list(&nodes); - for(List<int>::Element *E=nodes.front();E;E=E->next()) { + int from_idx=-1; + int to_idx=-1; + for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { - shader->node_add((Shader::NodeType)shader_graph.node_get_type(E->get()),E->get()); - shader->node_set_param(E->get(),shader_graph.node_get_param(E->get())); - shader->node_set_pos(E->get(),Point2( shader_graph.node_get_pos_x(E->get()),shader_graph.node_get_pos_y(E->get()) ) ); + if (p_from==E->get()->get_name()) + from_idx=E->key(); + if (p_to==E->get()->get_name()) + to_idx=E->key(); } - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { + ERR_FAIL_COND(from_idx==-1); + ERR_FAIL_COND(to_idx==-1); - const ShaderGraph::Connection &c=E->get(); - shader->connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } -} + if (!graph->is_node_connected(type,from_idx,p_from_slot,to_idx,p_to_slot)) + return; //nothing to disconnect -void ShaderEditor::_add_node_from_text(const String& p_text) { + ur->create_action("Disconnect Graph Nodes"); - ERR_FAIL_COND( p_text.get_slice_count(" ") != 3 ); - bool input = p_text.get_slice(" ",0)=="In:"; - String name = p_text.get_slice(" ",1); - bool vec = p_text.get_slice(" ",2)=="(vec3)"; + List<ShaderGraph::Connection> conns; + + graph->get_node_connections(type,&conns); + //disconnect/reconnect dependencies + ur->add_do_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_undo_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); - _node_add( input? - ( vec? VisualServer::NODE_VEC_IN : VisualServer::NODE_IN ) : - ( vec? VisualServer::NODE_VEC_OUT : VisualServer::NODE_OUT ) ); - shader_graph.node_set_param( last_id-1,name ); - _write_shader_graph(); } -void ShaderEditor::_vertex_item(int p_item) { +void ShaderGraphView::_node_removed(int p_id) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Remove Shader Graph Node"); + + ur->add_do_method(graph.ptr(),"node_remove",type,p_id); + ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,p_id),p_id); + ur->add_undo_method(graph.ptr(),"node_set_state",type,p_id,graph->node_get_state(type,p_id)); + List<ShaderGraph::Connection> conns; + + graph->get_node_connections(type,&conns); + for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) { + + if (E->get().dst_id==p_id || E->get().src_id==p_id) { + ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + } + } + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); - _add_node_from_text(vertex_popup->get_item_text(p_item)); } -void ShaderEditor::_fragment_item(int p_item) { - _add_node_from_text(fragment_popup->get_item_text(p_item)); +void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) { + + + ERR_FAIL_COND(!node_map.has(p_id)); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Move Shader Graph Node"); + ur->add_do_method(this,"_move_node",p_id,p_to); + ur->add_undo_method(this,"_move_node",p_id,p_from); + ur->commit_action(); } -void ShaderEditor::_post_item(int p_item) { - _add_node_from_text(post_popup->get_item_text(p_item)); +void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) { + + ERR_FAIL_COND(!node_map.has(p_id)); + node_map[p_id]->set_offset(p_to); + graph->node_set_pos(type,p_id,p_to); } -void ShaderEditor::_node_menu_item(int p_item) { +void ShaderGraphView::_create_node(int p_id) { - switch(p_item) { - case GRAPH_ADD_NODE: { - add_popup->popup_centered_ratio(); - validate_graph(); - } break; - case NODE_DISCONNECT: { + GraphNode *gn = memnew( GraphNode ); + gn->set_show_close_button(true); + Color typecol[4]={ + Color(0.9,0.4,1), + Color(0.8,1,0.2), + Color(1,0.2,0.2), + Color(0,1,1) + }; + - if (rclick_type==CLICK_INPUT_SLOT) { + switch(graph->node_get_type(type,p_id)) { - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { + case ShaderGraph::NODE_INPUT: { - const ShaderGraph::Connection &c=E->get(); - if( c.dst_id==rclick_node && c.dst_slot==rclick_slot) { + gn->set_title("Input"); - shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } + List<ShaderGraph::SlotInfo> si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + + int idx=0; + for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_IN) { + + Label *l= memnew( Label ); + l->set_text(s.name); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + gn->set_slot(idx,false,0,Color(),true,s.type,typecol[s.type]); + idx++; } - update(); - _write_shader_graph(); - validate_graph(); } - if (rclick_type==CLICK_OUTPUT_SLOT) { + } break; // all inputs (case Shader type dependent) + case ShaderGraph::NODE_SCALAR_CONST: { + gn->set_title("Scalar"); + SpinBox *sb = memnew( SpinBox ); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->scalar_const_node_get_value(type,p_id)); + sb->connect("value_changed",this,"_scalar_const_changed",varray(p_id)); + gn->add_child(sb); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; //scalar constant + case ShaderGraph::NODE_VEC_CONST: { + + gn->set_title("Vector"); + Array v3p(true); + for(int i=0;i<3;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *l = memnew( Label ); + l->set_text(String::chr('X'+i)); + hbc->add_child(l); + SpinBox *sb = memnew( SpinBox ); + sb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->vec_const_node_get_value(type,p_id)[i]); + sb->connect("value_changed",this,"_vec_const_changed",varray(p_id,v3p)); + v3p.push_back(sb); + hbc->add_child(sb); + gn->add_child(hbc); + } + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; //vec3 constant + case ShaderGraph::NODE_RGB_CONST: { + + gn->set_title("Color"); + ColorPickerButton *cpb = memnew( ColorPickerButton ); + cpb->set_color(graph->rgb_const_node_get_value(type,p_id)); + cpb->connect("color_changed",this,"_rgb_const_changed",varray(p_id)); + gn->add_child(cpb); + Label *l = memnew( Label ); + l->set_text("RGB"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; //rgb constant (shows a color picker instead) + case ShaderGraph::NODE_XFORM_CONST: { + gn->set_title("XForm"); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_xform_const_changed",varray(p_id,edit)); + gn->add_child(edit); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + + } break; // 4x4 matrix constant + case ShaderGraph::NODE_TIME: { + + gn->set_title("Time"); + Label *l = memnew( Label ); + l->set_text("(s)"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // time in seconds + case ShaderGraph::NODE_SCREEN_TEX: { + + gn->set_title("ScreenTex"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("RGB"))); + gn->add_child(hbc); + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) + case ShaderGraph::NODE_SCALAR_OP: { + + gn->set_title("ScalarOp"); + static const char* op_name[ShaderGraph::SCALAR_MAX_OP]={ + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Pow", + "Max", + "Min", + "Atan2" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::SCALAR_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } + + ob->select(graph->scalar_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_scalar_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // scalar vs scalar op (mul: { } break; add: { } break; div: { } break; etc) + case ShaderGraph::NODE_VEC_OP: { + + gn->set_title("VecOp"); + static const char* op_name[ShaderGraph::VEC_MAX_OP]={ + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Pow", + "Max", + "Min", + "Cross" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } - List<ShaderGraph::Connection> connections = shader_graph.get_connection_list(); - for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { + ob->select(graph->vec_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_vec_op_changed",varray(p_id)); + gn->add_child(ob); - const ShaderGraph::Connection &c=E->get(); - if( c.src_id==rclick_node && c.src_slot==rclick_slot) { + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); - shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } - } - update(); - _write_shader_graph(); - validate_graph(); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + + } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc) + case ShaderGraph::NODE_VEC_SCALAR_OP: { + + gn->set_title("VecScalarOp"); + static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={ + "Mul", + "Div", + "Pow", + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) { + + ob->add_item(op_name[i],i); } - } break; - case NODE_ERASE: { + ob->select(graph->vec_scalar_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_vec_scalar_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc) + case ShaderGraph::NODE_RGB_OP: { + + gn->set_title("RGB Op"); + static const char* op_name[ShaderGraph::RGB_MAX_OP]={ + "Screen", + "Difference", + "Darken", + "Lighten", + "Overlay", + "Dodge", + "Burn", + "SoftLight", + "HardLight" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::RGB_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } - order.erase(rclick_node); - shader_graph.node_remove(rclick_node); - update(); - _write_shader_graph(); - validate_graph(); - } break; - case GRAPH_CLEAR: { + ob->select(graph->rgb_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_rgb_op_changed",varray(p_id)); + gn->add_child(ob); - order.clear(); - shader_graph.clear(); - last_id=1; - last_x=20; - last_y=20; - update(); - _write_shader_graph(); - validate_graph(); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); - } break; - } -} + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); -void ShaderEditor::_node_add(VisualServer::ShaderNodeType p_type) { + } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc. + case ShaderGraph::NODE_XFORM_MULT: { - shader_graph.node_add(p_type,last_id ); - shader_graph.node_set_pos(last_id ,last_x,last_y); - String test_param; + gn->set_title("XFMult"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); - switch(p_type) { - case VS::NODE_PARAMETER: { + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],false,0,Color()); - test_param="param"; - } break; - case VS::NODE_VEC_PARAMETER: { - test_param="vec"; - } break; - case VS::NODE_COLOR_PARAMETER: { + } break; // mat4 x mat4 + case ShaderGraph::NODE_XFORM_VEC_MULT: { - test_param="color"; - } break; - case VS::NODE_TEXTURE_PARAMETER: { + gn->set_title("XFVecMult"); - test_param="tex"; - } break; - case VS::NODE_TEXTURE_2D_PARAMETER: { + Button *button = memnew( Button("RotOnly")); + button->set_toggle_mode(true); + button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id)); + button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id)); - test_param="tex2D"; - } break; - case VS::NODE_TEXTURE_CUBE_PARAMETER: { + gn->add_child(button); - test_param="cubemap"; - } break; - case VS::NODE_TRANSFORM_PARAMETER: { - test_param="xform"; - } break; - case VS::NODE_LABEL: { + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + gn->add_child( memnew(Label("vec"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); - test_param="label"; } break; - } + case ShaderGraph::NODE_XFORM_VEC_INV_MULT: { + + gn->set_title("XFVecInvMult"); + + + Button *button = memnew( Button("RotOnly")); + button->set_toggle_mode(true); + button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id)); + button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id)); + + gn->add_child(button); + + gn->add_child( memnew(Label("vec"))); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + + } break; // mat4 x vec3 inverse mult (with no-translation option) + case ShaderGraph::NODE_SCALAR_FUNC: { + + gn->set_title("ScalarFunc"); + static const char* func_name[ShaderGraph::SCALAR_MAX_FUNC]={ + "Sin", + "Cos", + "Tan", + "ASin", + "ACos", + "ATan", + "SinH", + "CosH", + "TanH", + "Log", + "Exp", + "Sqrt", + "Abs", + "Sign", + "Floor", + "Round", + "Ceil", + "Frac", + "Satr", + "Neg" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::SCALAR_MAX_FUNC;i++) { + + ob->add_item(func_name[i],i); + } + + ob->select(graph->scalar_func_node_get_function(type,p_id)); + ob->connect("item_selected",this,"_scalar_func_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // scalar function (sin: { } break; cos: { } break; etc) + case ShaderGraph::NODE_VEC_FUNC: { + + + + gn->set_title("VecFunc"); + static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={ + "Normalize", + "Saturate", + "Negate", + "Reciprocal", + "RGB to HSV", + "HSV to RGB", + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) { + + ob->add_item(func_name[i],i); + } + + ob->select(graph->vec_func_node_get_function(type,p_id)); + ob->connect("item_selected",this,"_vec_func_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc) + case ShaderGraph::NODE_VEC_LEN: { + gn->set_title("VecLength"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("len"))); + gn->add_child(hbc); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // vec3 length + case ShaderGraph::NODE_DOT_PROD: { + + gn->set_title("DotProduct"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("dp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // vec3 . vec3 (dot product -> scalar output) + case ShaderGraph::NODE_VEC_TO_SCALAR: { + + gn->set_title("Vec2Scalar"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("vec"))); + hbc->add_spacer(); + Label *l=memnew(Label("x")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("y")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l ); + l=memnew(Label("z")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + + + } break; // 1 vec3 input: { } break; 3 scalar outputs + case ShaderGraph::NODE_SCALAR_TO_VEC: { + + gn->set_title("Scalar2Vec"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("x"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("vec"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("y"))); + gn->add_child( memnew(Label("z"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + } break; // 3 scalar input: { } break; 1 vec3 output + case ShaderGraph::NODE_VEC_TO_XFORM: { + + gn->set_title("Vec2XForm"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("x"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("xf"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("y"))); + gn->add_child( memnew(Label("z"))); + gn->add_child( memnew(Label("ofs"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_XFORM_TO_VEC: { + + gn->set_title("XForm2Vec"); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l=memnew(Label("x")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("y")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l ); + l=memnew(Label("z")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + l=memnew(Label("ofs")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_SCALAR_INTERP: { + + gn->set_title("ScalarInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + gn->add_child( memnew(Label("c"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_VEC_INTERP: { + + gn->set_title("VecInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + gn->add_child( memnew(Label("c"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + } break; // vec3 interpolation (with optional curve) + case ShaderGraph::NODE_COLOR_RAMP: { + + gn->set_title("ColorRamp"); + GraphColorRampEdit * ramp = memnew( GraphColorRampEdit ); + + DVector<real_t> offsets = graph->color_ramp_node_get_offsets(type,p_id); + DVector<Color> colors = graph->color_ramp_node_get_colors(type,p_id); + + int oc = offsets.size(); + + if (oc) { + DVector<real_t>::Read rofs = offsets.read(); + DVector<Color>::Read rcol = colors.read(); + + Vector<float> ofsv; + Vector<Color> colorv; + for(int i=0;i<oc;i++) { + ofsv.push_back(rofs[i]); + colorv.push_back(rcol[i]); + } + + ramp->set_ramp(ofsv,colorv); + + } + + ramp->connect("ramp_changed",this,"_color_ramp_changed",varray(p_id,ramp)); + ramp->set_custom_minimum_size(Size2(128,1)); + gn->add_child(ramp); - if(test_param!="") { - int iter=0; - List<int> l; + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("c"))); + hbc->add_spacer(); + Label *l=memnew(Label("rgb")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("alpha")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); - shader_graph.get_node_list(&l); - bool found; - String test; - do { - iter++; - test=test_param; - if (iter>1) - test+="_"+itos(iter); - found=false; - for(List<int>::Element *E=l.front();E;E=E->next()) { + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,ShaderGraph::SLOT_MAX,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); - String param = shader_graph.node_get_param( E->get() ); - if (param==test) { - found=true; - break; + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_CURVE_MAP: { + + gn->set_title("CurveMap"); + GraphCurveMapEdit * map = memnew( GraphCurveMapEdit ); + + DVector<Vector2> points = graph->curve_map_node_get_points(type,p_id); + + int oc = points.size(); + + if (oc) { + DVector<Vector2>::Read rofs = points.read(); + + + Vector<Vector2> ofsv; + for(int i=0;i<oc;i++) { + ofsv.push_back(rofs[i]); + } + + map->set_points(ofsv); + + } + map->connect("curve_changed",this,"_curve_changed",varray(p_id,map)); + + //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map)); + map->set_custom_minimum_size(Size2(128,64)); + gn->add_child(map); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("c"))); + hbc->add_spacer(); + Label *l=memnew(Label("cmap")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // scalar interpolation (with optional curve) + + case ShaderGraph::NODE_SCALAR_INPUT: { + + gn->set_title("ScalarUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + SpinBox *sb = memnew( SpinBox ); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->scalar_input_node_get_value(type,p_id)); + sb->connect("value_changed",this,"_scalar_input_changed",varray(p_id)); + gn->add_child(sb); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // scalar uniform (assignable in material) + case ShaderGraph::NODE_VEC_INPUT: { + + gn->set_title("VectorUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + Array v3p(true); + for(int i=0;i<3;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *l = memnew( Label ); + l->set_text(String::chr('X'+i)); + hbc->add_child(l); + SpinBox *sb = memnew( SpinBox ); + sb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->vec_input_node_get_value(type,p_id)[i]); + sb->connect("value_changed",this,"_vec_input_changed",varray(p_id,v3p)); + v3p.push_back(sb); + hbc->add_child(sb); + gn->add_child(hbc); + } + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // vec3 uniform (assignable in material) + case ShaderGraph::NODE_RGB_INPUT: { + + gn->set_title("ColorUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + ColorPickerButton *cpb = memnew( ColorPickerButton ); + cpb->set_color(graph->rgb_input_node_get_value(type,p_id)); + cpb->connect("color_changed",this,"_rgb_input_changed",varray(p_id)); + gn->add_child(cpb); + Label *l = memnew( Label ); + l->set_text("RGB"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // color uniform (assignable in material) + case ShaderGraph::NODE_XFORM_INPUT: { + gn->set_title("XFUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_xform_input_changed",varray(p_id,edit)); + gn->add_child(edit); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + + } break; // mat4 uniform (assignable in material) + case ShaderGraph::NODE_TEXTURE_INPUT: { + + gn->set_title("TexUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + TextureFrame *tex = memnew( TextureFrame ); + tex->set_expand(true); + tex->set_custom_minimum_size(Size2(80,80)); + gn->add_child(tex); + tex->set_texture(graph->texture_input_node_get_value(type,p_id)); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_tex_edited",varray(p_id,edit)); + gn->add_child(edit); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(4,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // texture input (assignable in material) + case ShaderGraph::NODE_CUBEMAP_INPUT: { + + gn->set_title("TexUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_cube_edited",varray(p_id,edit)); + gn->add_child(edit); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // cubemap input (assignable in material) + case ShaderGraph::NODE_DEFAULT_TEXTURE: { + + gn->set_title("CanvasItemTex"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) + + case ShaderGraph::NODE_OUTPUT: { + gn->set_title("Output"); + + List<ShaderGraph::SlotInfo> si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + + int idx=0; + for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_OUT) { + + Label *l= memnew( Label ); + l->set_text(s.name); + l->set_align(Label::ALIGN_LEFT); + gn->add_child(l); + gn->set_slot(idx,true,s.type,typecol[s.type],false,0,Color()); + idx++; } } - } while (found); + } break; // output (case Shader type dependent) + case ShaderGraph::NODE_COMMENT: { + gn->set_title("Comment"); + TextEdit *te = memnew(TextEdit); + te->set_custom_minimum_size(Size2(100,100)); + gn->add_child(te); + te->set_text(graph->comment_node_get_text(type,p_id)); + te->connect("text_changed",this,"_comment_edited",varray(p_id,te)); + + } break; // comment - shader_graph.node_set_param(last_id,test); } - order.push_back(last_id); - last_x+=10; - last_y+=10; - last_id++; - last_x=last_x % (int)get_size().width; - last_y=last_y % (int)get_size().height; - update(); - add_popup->hide();; - _write_shader_graph(); -} + gn->connect("dragged",this,"_node_moved",varray(p_id)); + gn->connect("close_request",this,"_node_removed",varray(p_id),CONNECT_DEFERRED); + graph_edit->add_child(gn); + node_map[p_id]=gn; + gn->set_offset(graph->node_get_pos(type,p_id)); -void ShaderEditor::_node_add_callback() { - TreeItem * item = add_types->get_selected(); - ERR_FAIL_COND(!item); - _node_add((VisualServer::ShaderNodeType)(int)item->get_metadata(0)); - add_popup->hide() ; } -ShaderEditor::ShaderEditor() { +void ShaderGraphView::_update_graph() { - set_focus_mode(FOCUS_ALL); - Panel* menu_panel = memnew( Panel ); - menu_panel->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END ); - menu_panel->set_end( Point2(0,22) ); + if (block_update) + return; - add_child( menu_panel ); + for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { - PopupMenu *p; - List<PropertyInfo> defaults; + memdelete(E->get()); + } - MenuButton* node_menu = memnew( MenuButton ); - node_menu->set_text("Graph"); - node_menu->set_pos( Point2( 5,0) ); - menu_panel->add_child( node_menu ); + node_map.clear(); - p=node_menu->get_popup(); - p->add_item("Add Node",GRAPH_ADD_NODE); - p->add_separator(); - p->add_item("Clear",GRAPH_CLEAR); - p->connect("item_pressed", this,"_node_menu_item"); + if (!graph.is_valid()) + return; - MenuButton* vertex_menu = memnew( MenuButton ); - vertex_menu->set_text("Vertex"); - vertex_menu->set_pos( Point2( 49,0) ); - menu_panel->add_child( vertex_menu ); - p=vertex_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_VERTEX,&defaults); + List<int> nl; + graph->get_node_list(type,&nl); - int id=0; - for(int i=0;i<defaults.size();i++) { + for(List<int>::Element *E=nl.front();E;E=E->next()) { - p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); + _create_node(E->get()); } - p->add_separator(); - id++; + graph_edit->clear_connections(); - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_VERTEX,&defaults); - - for(int i=0;i<defaults.size();i++) { + List<ShaderGraph::Connection> connections; + graph->get_node_connections(type,&connections); + for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) { - p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); + ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id)); + graph_edit->connect_node(node_map[E->get().src_id]->get_name(),E->get().src_slot,node_map[E->get().dst_id]->get_name(),E->get().dst_slot); } - vertex_popup=p; - vertex_popup->connect("item_pressed", this,"_vertex_item"); - MenuButton* fragment_menu = memnew( MenuButton ); - fragment_menu->set_text("Fragment"); - fragment_menu->set_pos( Point2( 95 ,0) ); - menu_panel->add_child( fragment_menu ); - p=fragment_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_FRAGMENT,&defaults); - id=0; - for(int i=0;i<defaults.size();i++) { - p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); +} + +void ShaderGraphView::_sg_updated() { + + if (!graph.is_valid()) + return; + switch(graph->get_graph_error(type)) { + case ShaderGraph::GRAPH_OK: status->set_text(""); break; + case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text("Error: Cyclic Connection Link"); break; + case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text("Error: Missing Input Connections"); break; } - p->add_separator(); - id++; - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_FRAGMENT,&defaults); +} - for(int i=0;i<defaults.size();i++) { +void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph){ - p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); + + if (graph.is_valid()) { + graph->disconnect("updated",this,"_sg_updated"); + } + graph=p_graph; + if (graph.is_valid()) { + graph->connect("updated",this,"_sg_updated"); } + _update_graph(); + _sg_updated(); + +} + +void ShaderGraphView::_notification(int p_what) { - fragment_popup=p; - fragment_popup->connect("item_pressed", this,"_fragment_item"); + if (p_what==NOTIFICATION_ENTER_TREE) { - MenuButton* post_menu = memnew( MenuButton ); - post_menu->set_text("Post"); - post_menu->set_pos( Point2( 161,0) ); - menu_panel->add_child( post_menu ); + ped_popup->connect("variant_changed",this,"_variant_edited"); + } + } + +void ShaderGraphView::add_node(int p_type) { + + List<int> existing; + graph->get_node_list(type,&existing); + existing.sort(); + int newid=1; + for(List<int>::Element *E=existing.front();E;E=E->next()) { + if (!E->next() || (E->get()+1!=E->next()->get())){ + newid=E->get()+1; + break; + } + } - p=post_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_POST_PROCESS,&defaults); - id=0; - for(int i=0;i<defaults.size();i++) { + Vector2 init_ofs(20,20); + while(true) { + bool valid=true; + for(List<int>::Element *E=existing.front();E;E=E->next()) { + Vector2 pos = graph->node_get_pos(type,E->get()); + if (init_ofs==pos) { + init_ofs+=Vector2(20,20); + valid=false; + break; + + } + } - p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); + if (valid) + break; } - p->add_separator(); - id++; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Add Shader Graph Node"); + ur->add_do_method(graph.ptr(),"node_add",type,p_type,newid); + ur->add_do_method(graph.ptr(),"node_set_pos",type,newid,init_ofs); + ur->add_undo_method(graph.ptr(),"node_remove",type,newid); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + +} + +void ShaderGraphView::_bind_methods() { + + ObjectTypeDB::bind_method("_update_graph",&ShaderGraphView::_update_graph); + ObjectTypeDB::bind_method("_node_moved",&ShaderGraphView::_node_moved); + ObjectTypeDB::bind_method("_move_node",&ShaderGraphView::_move_node); + ObjectTypeDB::bind_method("_node_removed",&ShaderGraphView::_node_removed); + ObjectTypeDB::bind_method("_connection_request",&ShaderGraphView::_connection_request); + ObjectTypeDB::bind_method("_disconnection_request",&ShaderGraphView::_disconnection_request); + + ObjectTypeDB::bind_method("_scalar_const_changed",&ShaderGraphView::_scalar_const_changed); + ObjectTypeDB::bind_method("_vec_const_changed",&ShaderGraphView::_vec_const_changed); + ObjectTypeDB::bind_method("_rgb_const_changed",&ShaderGraphView::_rgb_const_changed); + ObjectTypeDB::bind_method("_xform_const_changed",&ShaderGraphView::_xform_const_changed); + ObjectTypeDB::bind_method("_scalar_op_changed",&ShaderGraphView::_scalar_op_changed); + ObjectTypeDB::bind_method("_vec_op_changed",&ShaderGraphView::_vec_op_changed); + ObjectTypeDB::bind_method("_vec_scalar_op_changed",&ShaderGraphView::_vec_scalar_op_changed); + ObjectTypeDB::bind_method("_rgb_op_changed",&ShaderGraphView::_rgb_op_changed); + ObjectTypeDB::bind_method("_xform_inv_rev_changed",&ShaderGraphView::_xform_inv_rev_changed); + ObjectTypeDB::bind_method("_scalar_func_changed",&ShaderGraphView::_scalar_func_changed); + ObjectTypeDB::bind_method("_vec_func_changed",&ShaderGraphView::_vec_func_changed); + ObjectTypeDB::bind_method("_scalar_input_changed",&ShaderGraphView::_scalar_input_changed); + ObjectTypeDB::bind_method("_vec_input_changed",&ShaderGraphView::_vec_input_changed); + ObjectTypeDB::bind_method("_xform_input_changed",&ShaderGraphView::_xform_input_changed); + ObjectTypeDB::bind_method("_rgb_input_changed",&ShaderGraphView::_rgb_input_changed); + ObjectTypeDB::bind_method("_tex_input_change",&ShaderGraphView::_tex_input_change); + ObjectTypeDB::bind_method("_cube_input_change",&ShaderGraphView::_cube_input_change); + ObjectTypeDB::bind_method("_input_name_changed",&ShaderGraphView::_input_name_changed); + ObjectTypeDB::bind_method("_tex_edited",&ShaderGraphView::_tex_edited); + ObjectTypeDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited); + ObjectTypeDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited); + ObjectTypeDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited); + ObjectTypeDB::bind_method("_color_ramp_changed",&ShaderGraphView::_color_ramp_changed); + ObjectTypeDB::bind_method("_curve_changed",&ShaderGraphView::_curve_changed); + + ObjectTypeDB::bind_method("_sg_updated",&ShaderGraphView::_sg_updated); +} + +ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) { + + type=p_type; + graph_edit = memnew( GraphEdit ); + block_update=false; + ped_popup = memnew( CustomPropertyEditor ); + graph_edit->add_child(ped_popup); + status = memnew( Label ); + graph_edit->get_top_layer()->add_child(status); + status->set_pos(Vector2(5,5)); + status->add_color_override("font_color_shadow",Color(0,0,0)); + status->add_color_override("font_color",Color(1,0.4,0.3)); + status->add_constant_override("shadow_as_outline",1); + status->add_constant_override("shadow_offset_x",2); + status->add_constant_override("shadow_offset_y",2); + status->set_text(""); +} - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_POST_PROCESS,&defaults); - for(int i=0;i<defaults.size();i++) { +//////////////edit////////////// +void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) { - p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); + for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) { + graph_edits[i]->set_graph(p_shader); } +} + +void ShaderGraphEditor::_add_node(int p_type) { + + ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab()); + + graph_edits[shader_type]->add_node(p_type); +} + + +void ShaderGraphEditor::_notification(int p_what) { + if (p_what==NOTIFICATION_ENTER_TREE) { + + for(int i=0;i<ShaderGraph::NODE_TYPE_MAX;i++) { - post_popup=p; - post_popup->connect("item_pressed", this,"_post_item"); + if (i==ShaderGraph::NODE_OUTPUT) + continue; + if (!_2d && i==ShaderGraph::NODE_DEFAULT_TEXTURE) + continue; + + String nn = node_names[i]; + String ic = nn.get_slice(":",0); + String v = nn.get_slice(":",1); + bool addsep=false; + if (nn.ends_with(":")) { + addsep=true; + } + menu->get_popup()->add_icon_item(get_icon(ic,"EditorIcons"),v,i); + if (addsep) + menu->get_popup()->add_separator(); + } + menu->get_popup()->connect("item_pressed",this,"_add_node"); - /* add popup */ + } +} - add_popup = memnew( Popup ); - add_child(add_popup); - add_popup->set_as_toplevel(true); - Panel *add_panel = memnew( Panel ); - add_popup->add_child(add_panel); - add_panel->set_area_as_parent_rect(); +void ShaderGraphEditor::_bind_methods() { - Label *add_label = memnew (Label ); - add_label->set_pos(Point2(5,5)); - add_label->set_text("Available Nodes:"); - add_panel->add_child(add_label); + ObjectTypeDB::bind_method("_add_node",&ShaderGraphEditor::_add_node); +} - add_types = memnew( Tree ); - add_types->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - add_types->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); - add_types->set_begin( Point2( 20,25 ) ); - add_types->set_end( Point2( 10, 30 ) ); - add_types->set_hide_root(true); - add_types->set_columns(4); - add_types->set_select_mode(Tree::SELECT_ROW); +const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={ + "GraphInput:Input", // all inputs (shader type dependent) + "GraphScalar:Scalar Constant", //scalar constant + "GraphVector:Vector Constant", //vec3 constant + "GraphRgb:RGB Constant", //rgb constant (shows a color picker instead) + "GraphXform:XForm Constant", // 4x4 matrix constant + "GraphTime:Time:", // time in seconds + "GraphTexscreen:Screen Sample", // screen texture sampler (takes uv) (only usable in fragment shader) + "GraphScalarOp:Scalar Operator", // scalar vs scalar op (mul", add", div", etc) + "GraphVecOp:Vector Operator", // vec3 vs vec3 op (mul",ad",div",crossprod",etc) + "GraphVecScalarOp:Scalar+Vector Operator", // vec3 vs scalar op (mul", add", div", etc) + "GraphRgbOp:RGB Operator:", // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc. + "GraphXformMult:XForm Multiply", // mat4 x mat4 + "GraphXformVecMult:XForm+Vector Multiply", // mat4 x vec3 mult (with no-translation option) + "GraphXformVecImult:Form+Vector InvMultiply:", // mat4 x vec3 inverse mult (with no-translation option) + "GraphXformScalarFunc:Scalar Function", // scalar function (sin", cos", etc) + "GraphXformVecFunc:Vector Function", // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc) + "GraphVecLength:Vector Length", // vec3 length + "GraphVecDp:Dot Product:", // vec3 . vec3 (dot product -> scalar output) + "GraphVecToScalars:Vector -> Scalars", // 1 vec3 input", 3 scalar outputs + "GraphScalarsToVec:Scalars -> Vector", // 3 scalar input", 1 vec3 output + "GraphXformToVecs:XForm -> Vectors", // 3 vec input", 1 xform output + "GraphVecsToXform:Vectors -> XForm:", // 3 vec input", 1 xform output + "GraphScalarInterp:Scalar Interpolate", // scalar interpolation (with optional curve) + "GraphVecInterp:Vector Interpolate:", // vec3 interpolation (with optional curve) + "GraphColorRamp:Color Ramp", // vec3 interpolation (with optional curve) + "GraphCurveMap:Curve Remap:", // vec3 interpolation (with optional curve) + "GraphScalarUniform:Scalar Uniform", // scalar uniform (assignable in material) + "GraphVectorUniform:Vector Uniform", // vec3 uniform (assignable in material) + "GraphRgbUniform:RGB Uniform", // color uniform (assignable in material) + "GraphXformUniform:XForm Uniform", // mat4 uniform (assignable in material) + "GraphTextureUniform:Texture Uniform", // texture input (assignable in material) + "GraphCubeUniform:CubeMap Uniform:", // cubemap input (assignable in material) + "GraphDefaultTexture:CanvasItem Texture:", // cubemap input (assignable in material) + "Output", // output (shader type dependent) + "GraphComment:Comment", // comment - TreeItem *add_types_root = add_types->create_item(NULL); - TreeItem *info_item = add_types->create_item(add_types_root); - for(int i=0;i<VisualServer::NODE_TYPE_MAX;i++) { +}; +ShaderGraphEditor::ShaderGraphEditor(bool p_2d) { + _2d=p_2d; + + HBoxContainer *hbc = memnew( HBoxContainer ); + menu = memnew( MenuButton ); + menu->set_text("Add Node.."); + hbc->add_child(menu); + add_child(hbc); + + + tabs = memnew(TabContainer); + tabs->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(tabs); + const char* sname[ShaderGraph::SHADER_TYPE_MAX]={ + "Vertex", + "Fragment", + "Light" + }; + for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) { + + graph_edits[i]= memnew( ShaderGraphView(ShaderGraph::ShaderType(i)) ); + add_child(graph_edits[i]); + graph_edits[i]->get_graph_edit()->set_name(sname[i]); + tabs->add_child(graph_edits[i]->get_graph_edit()); + graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request"); + graph_edits[i]->get_graph_edit()->connect("disconnection_request",graph_edits[i],"_disconnection_request"); + graph_edits[i]->get_graph_edit()->set_right_disconnects(true); - TreeItem *item = add_types->create_item(add_types_root); - PropertyInfo prop = VisualServer::shader_node_get_type_info((VisualServer::ShaderNodeType)i); - item->set_text(0,prop.name); - item->set_text(1,itos(VisualServer::shader_get_input_count((VisualServer::ShaderNodeType)i))); - item->set_text(2,itos(VisualServer::shader_get_output_count((VisualServer::ShaderNodeType)i))); - String hint = (prop.type==Variant::_RID)?prop.hint_string:Variant::get_type_name(prop.type); - item->set_text(3,hint); - item->set_metadata(0,i); } - info_item->set_text(0,"::NODE::"); - info_item->set_custom_color(0,Color(0.6,0.1,0.1)); - info_item->set_text(1,"::INPUTS::"); - info_item->set_custom_color(1,Color(0.6,0.1,0.1)); - info_item->set_text(2,"::OUTPUTS::"); - info_item->set_custom_color(2,Color(0.6,0.1,0.1)); - info_item->set_text(3,"::PARAM::"); - info_item->set_custom_color(3,Color(0.6,0.1,0.1)); - info_item->set_selectable(0,false); - info_item->set_selectable(1,false); - info_item->set_selectable(2,false); - info_item->set_selectable(3,false); - - add_panel->add_child(add_types); - - add_confirm = memnew( Button ); - add_confirm->set_anchor( MARGIN_LEFT, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_TOP, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); - add_confirm->set_begin( Point2( 75, 29 ) ); - add_confirm->set_end( Point2( 10, 15 ) ); - add_confirm->set_text("Add"); - add_panel->add_child(add_confirm); - add_confirm->connect("pressed", this,"_node_add_callback"); - - last_id=1; - last_x=20; - last_y=20; - - property_editor = memnew( CustomPropertyEditor ); - add_child(property_editor); - property_editor->connect("variant_changed", this,"_node_param_changed"); - - h_scroll = memnew( HScrollBar ); - v_scroll = memnew( VScrollBar ); - - add_child(h_scroll); - add_child(v_scroll); - - h_scroll->connect("value_changed", this,"_scroll_moved"); - v_scroll->connect("value_changed", this,"_scroll_moved"); - - node_popup= memnew(PopupMenu ); - add_child(node_popup); - node_popup->set_as_toplevel(true); - - node_popup->connect("item_pressed", this,"_node_menu_item"); + tabs->set_current_tab(1); + + set_custom_minimum_size(Size2(100,300)); } -void ShaderEditorPlugin::edit(Object *p_object) { +void ShaderGraphEditorPlugin::edit(Object *p_object) { - shader_editor->edit(p_object->cast_to<Shader>()); + shader_editor->edit(p_object->cast_to<ShaderGraph>()); } -bool ShaderEditorPlugin::handles(Object *p_object) const { +bool ShaderGraphEditorPlugin::handles(Object *p_object) const { - return p_object->is_type("Shader"); + ShaderGraph *shader=p_object->cast_to<ShaderGraph>(); + if (!shader) + return false; + if (_2d) + return shader->get_mode()==Shader::MODE_CANVAS_ITEM; + else + return shader->get_mode()==Shader::MODE_MATERIAL; } -void ShaderEditorPlugin::make_visible(bool p_visible) { +void ShaderGraphEditorPlugin::make_visible(bool p_visible) { if (p_visible) { shader_editor->show(); - shader_editor->set_process(true); } else { shader_editor->hide(); - shader_editor->set_process(false); } } -ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) { +ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d) { + _2d=p_2d; editor=p_node; - shader_editor = memnew( ShaderEditor ); - editor->get_viewport()->add_child(shader_editor); - shader_editor->set_area_as_parent_rect(); + shader_editor = memnew( ShaderGraphEditor(p_2d) ); shader_editor->hide(); + if (p_2d) + CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(shader_editor); + else + SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor); +// editor->get_viewport()->add_child(shader_editor); +// shader_editor->set_area_as_parent_rect(); +// shader_editor->hide(); } -ShaderEditorPlugin::~ShaderEditorPlugin() +ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin() { } -#endif + diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h index 5b0767dc82..1726302e90 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.h +++ b/tools/editor/plugins/shader_graph_editor_plugin.h @@ -29,122 +29,198 @@ #ifndef SHADER_GRAPH_EDITOR_PLUGIN_H #define SHADER_GRAPH_EDITOR_PLUGIN_H -#if 0 + #include "tools/editor/editor_plugin.h" #include "tools/editor/editor_node.h" #include "scene/resources/shader.h" #include "servers/visual/shader_graph.h" #include "scene/gui/tree.h" #include "scene/gui/button.h" +#include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" #include "tools/editor/property_editor.h" +#include "scene/resources/shader_graph.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class ShaderEditor : public Control { - OBJ_TYPE(ShaderEditor, Control ); +class GraphColorRampEdit : public Control { + + OBJ_TYPE(GraphColorRampEdit,Control); - enum MenuAction { - GRAPH_ADD_NODE, - GRAPH_CLEAR, - NODE_DISCONNECT, - NODE_ERASE, + struct Point { + float offset; + Color color; + bool operator<(const Point& p_ponit) const { + return offset<p_ponit.offset; + } }; - enum ClickType { - CLICK_NONE, - CLICK_NODE, - CLICK_INPUT_SLOT, - CLICK_OUTPUT_SLOT, - CLICK_PARAMETER + PopupPanel *popup; + ColorPicker *picker; + + + bool grabbing; + int grabbed; + float grabbed_at; + Vector<Point> points; + + void _color_changed(const Color& p_color); + +protected: + void _input_event(const InputEvent& p_event); + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors); + Vector<float> get_offsets() const; + Vector<Color> get_colors() const; + virtual Size2 get_minimum_size() const; + GraphColorRampEdit(); +}; + + +class GraphCurveMapEdit : public Control { + + OBJ_TYPE(GraphCurveMapEdit,Control); + + + struct Point { + + float offset; + float height; + bool operator<(const Point& p_ponit) const { + return offset<p_ponit.offset; + } }; - PopupMenu *node_popup; - Popup *add_popup; - PopupMenu *vertex_popup; - PopupMenu *fragment_popup; - PopupMenu *post_popup; - Tree *add_types; - Button *add_confirm; - HScrollBar *h_scroll; - VScrollBar *v_scroll; - - Ref<Shader> shader; - List<int> order; - Set<int> active_nodes; - ShaderGraph shader_graph; - int last_x,last_y; - uint32_t last_id; - - CustomPropertyEditor *property_editor; - - Point2 offset; - ClickType click_type; - Point2 click_pos; - int click_node; - int click_slot; - Point2 click_motion; - ClickType rclick_type; - int rclick_node; - int rclick_slot; - - Size2 _get_maximum_size(); - Size2 get_node_size(int p_node) const; - void _draw_node(int p_node); - - void _add_node_from_text(const String& p_text); - void _update_scrollbars(); - void _scroll_moved(); - void _node_param_changed(); - void _node_add_callback(); - void _node_add(VisualServer::ShaderNodeType p_type); - void _node_edit_property(int p_node); - void _node_menu_item(int p_item); - void _vertex_item(int p_item); - void _fragment_item(int p_item); - void _post_item(int p_item); - - ClickType _locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const; - Point2 _get_slot_pos(int p_node_id,bool p_input,int p_slot); - - Error validate_graph(); - - void _read_shader_graph(); - void _write_shader_graph(); - - virtual bool has_point(const Point2& p_point) const; + + bool grabbing; + int grabbed; + Vector<Point> points; + + void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d); protected: + void _input_event(const InputEvent& p_event); void _notification(int p_what); - void _input_event(InputEvent p_event); static void _bind_methods(); public: - void edit(Ref<Shader> p_shader); - ShaderEditor(); + void set_points(const Vector<Vector2>& p_points); + Vector<Vector2> get_points() const; + virtual Size2 get_minimum_size() const; + GraphCurveMapEdit(); }; -class ShaderEditorPlugin : public EditorPlugin { +class ShaderGraphView : public Node { + + OBJ_TYPE(ShaderGraphView,Node); + + + + CustomPropertyEditor *ped_popup; + bool block_update; + + Label *status; + GraphEdit *graph_edit; + Ref<ShaderGraph> graph; + int edited_id; + + ShaderGraph::ShaderType type; - OBJ_TYPE( ShaderEditorPlugin, EditorPlugin ); + void _update_graph(); + void _create_node(int p_id); - ShaderEditor *shader_editor; + + + void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); + void _disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); + + void _node_removed(int p_id); + void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id); + void _move_node(int p_id,const Vector2& p_to); + + void _scalar_const_changed(double p_value,int p_id); + void _vec_const_changed(double p_value, int p_id, Array p_arr); + void _rgb_const_changed(const Color& p_color, int p_id); + void _xform_const_changed(int p_id,Node* p_button); + void _scalar_op_changed(int p_op, int p_id); + void _vec_op_changed(int p_op, int p_id); + void _vec_scalar_op_changed(int p_op, int p_id); + void _rgb_op_changed(int p_op, int p_id); + void _xform_inv_rev_changed(bool p_enabled, int p_id); + void _scalar_func_changed(int p_func, int p_id); + void _vec_func_changed(int p_func, int p_id); + void _scalar_input_changed(double p_value,int p_id); + void _vec_input_changed(double p_value, int p_id, Array p_arr); + void _xform_input_changed(int p_id,Node* p_button); + void _rgb_input_changed(const Color& p_color, int p_id); + void _tex_input_change(int p_id,Node* p_button); + void _cube_input_change(int p_id); + void _input_name_changed(const String& p_name,int p_id,Node* p_line_edit); + void _tex_edited(int p_id,Node* p_button); + void _cube_edited(int p_id,Node* p_button); + void _variant_edited(); + void _comment_edited(int p_id,Node* p_button); + void _color_ramp_changed(int p_id,Node* p_ramp); + void _curve_changed(int p_id,Node* p_curve); + void _sg_updated(); + Map<int,GraphNode*> node_map; +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void add_node(int p_type); + GraphEdit *get_graph_edit() { return graph_edit; } + void set_graph(Ref<ShaderGraph> p_graph); + + ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT); +}; + +class ShaderGraphEditor : public VBoxContainer { + + OBJ_TYPE(ShaderGraphEditor,VBoxContainer); + + MenuButton *menu; + TabContainer *tabs; + ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX]; + static const char* node_names[ShaderGraph::NODE_TYPE_MAX]; + + bool _2d; + void _add_node(int p_type); +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void edit(Ref<ShaderGraph> p_shader); + ShaderGraphEditor(bool p_2d); +}; + +class ShaderGraphEditorPlugin : public EditorPlugin { + + OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin ); + + bool _2d; + ShaderGraphEditor *shader_editor; EditorNode *editor; public: - virtual String get_name() const { return "Shader"; } + virtual String get_name() const { return "ShaderGraph"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_node); virtual bool handles(Object *p_node) const; virtual void make_visible(bool p_visible); - ShaderEditorPlugin(EditorNode *p_node); - ~ShaderEditorPlugin(); + ShaderGraphEditorPlugin(EditorNode *p_node,bool p_2d); + ~ShaderGraphEditorPlugin(); }; #endif -#endif // SHADER_GRAPH_EDITOR_PLUGIN_H + diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 074fa5c946..30ac50057f 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -249,7 +249,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2& p_pos, bool p_append,b Vector3 ray=_get_ray(p_pos); Vector3 pos=_get_ray_pos(p_pos); - Vector<RID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_scene()->get_root()->get_world()->get_scenario() ); + Vector<RID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_tree()->get_root()->get_world()->get_scenario() ); Set<Ref<SpatialEditorGizmo> > found_gizmos; //uint32_t closest=0; @@ -449,7 +449,7 @@ void SpatialEditorViewport::_select_region() { frustum.push_back( far ); - Vector<RID> instances=VisualServer::get_singleton()->instances_cull_convex(frustum,get_scene()->get_root()->get_world()->get_scenario()); + Vector<RID> instances=VisualServer::get_singleton()->instances_cull_convex(frustum,get_tree()->get_root()->get_world()->get_scenario()); for (int i=0;i<instances.size();i++) { @@ -477,6 +477,16 @@ void SpatialEditorViewport::_select_region() { } +void SpatialEditorViewport::_update_name() { + + String ortho = orthogonal?"Orthogonal":"Perspective"; + + if (name!="") + view_menu->set_text("[ "+name+" "+ortho+" ]"); + else + view_menu->set_text("[ "+ortho+" ]"); +} + void SpatialEditorViewport::_compute_edit(const Point2& p_point) { @@ -535,6 +545,14 @@ SpatialEditorViewport::NavigationScheme SpatialEditorViewport::_get_navigation_s return NAVIGATION_GODOT; } +SpatialEditorViewport::NavigationZoomStyle SpatialEditorViewport::_get_navigation_zoom_style(const String& p_property) { + switch(EditorSettings::get_singleton()->get(p_property).operator int()) { + case 0: return NAVIGATION_ZOOM_VERTICAL; + case 1: return NAVIGATION_ZOOM_HORIZONTAL; + } + return NAVIGATION_ZOOM_VERTICAL; +} + bool SpatialEditorViewport::_gizmo_select(const Vector2& p_screenpos,bool p_hilite_only) { if (!spatial_editor->is_gizmo_visible()) @@ -724,7 +742,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (b.mod.control) { - Vector<RID> instances=VisualServer::get_singleton()->instances_cull_ray(ray_origin,ray_dir,get_scene()->get_root()->get_world()->get_scenario() ); + Vector<RID> instances=VisualServer::get_singleton()->instances_cull_ray(ray_origin,ray_dir,get_tree()->get_root()->get_world()->get_scenario() ); Plane p(ray_origin,_get_camera_normal()); @@ -824,6 +842,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { _edit.plane=TRANSFORM_X_AXIS; set_message("View Plane Transform.",2); + name=""; + _update_name(); } break; case TRANSFORM_X_AXIS: { @@ -1429,10 +1449,19 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (nav_scheme==NAVIGATION_MAYA && m.mod.shift) zoom_speed *= zoom_speed_modifier; - if ( m.relative_y > 0) - cursor.distance*=1+m.relative_y*zoom_speed; - else if (m.relative_y < 0) - cursor.distance/=1-m.relative_y*zoom_speed; + NavigationZoomStyle zoom_style = _get_navigation_zoom_style("3d_editor/zoom_style"); + if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) { + if ( m.relative_x > 0) + cursor.distance*=1-m.relative_x*zoom_speed; + else if (m.relative_x < 0) + cursor.distance/=1+m.relative_x*zoom_speed; + } + else { + if ( m.relative_y > 0) + cursor.distance*=1+m.relative_y*zoom_speed; + else if (m.relative_y < 0) + cursor.distance/=1-m.relative_y*zoom_speed; + } } break; @@ -1443,6 +1472,8 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { cursor.x_rot=Math_PI/2.0; if (cursor.x_rot<-Math_PI/2.0) cursor.x_rot=-Math_PI/2.0; + name=""; + _update_name(); } break; default: {} @@ -1467,9 +1498,14 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (k.mod.shift) { cursor.x_rot=-Math_PI/2.0; set_message("Bottom View.",2); + name="Bottom"; + _update_name(); + } else { cursor.x_rot=Math_PI/2.0; set_message("Top View.",2); + name="Top"; + _update_name(); } } break; case KEY_KP_1: { @@ -1478,10 +1514,14 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (k.mod.shift) { cursor.y_rot=Math_PI; set_message("Rear View.",2); + name="Rear"; + _update_name(); } else { cursor.y_rot=0; set_message("Front View.",2); + name="Front"; + _update_name(); } } break; @@ -1491,9 +1531,13 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (k.mod.shift) { cursor.y_rot=Math_PI/2.0; set_message("Left View.",2); + name="Left"; + _update_name(); } else { cursor.y_rot=-Math_PI/2.0; set_message("Right View.",2); + name="Right"; + _update_name(); } } break; @@ -1501,6 +1545,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { orthogonal = !orthogonal; _menu_option(orthogonal?VIEW_PERSPECTIVE:VIEW_ORTHOGONAL); + _update_name(); } break; @@ -1711,7 +1756,7 @@ void SpatialEditorViewport::_notification(int p_what) { } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { surface->connect("draw",this,"_draw"); surface->connect("input_event",this,"_sinput"); @@ -1814,35 +1859,47 @@ void SpatialEditorViewport::_menu_option(int p_option) { cursor.x_rot=Math_PI/2.0; cursor.y_rot=0; + name="Top"; + _update_name(); } break; case VIEW_BOTTOM: { cursor.x_rot=-Math_PI/2.0; cursor.y_rot=0; + name="Bottom"; + _update_name(); } break; case VIEW_LEFT: { cursor.y_rot=Math_PI/2.0; cursor.x_rot=0; + name="Left"; + _update_name(); } break; case VIEW_RIGHT: { cursor.y_rot=-Math_PI/2.0; cursor.x_rot=0; + name="Right"; + _update_name(); } break; case VIEW_FRONT: { cursor.y_rot=0; cursor.x_rot=0; + name="Front"; + _update_name(); } break; case VIEW_REAR: { cursor.y_rot=Math_PI; cursor.x_rot=0; + name="Rear"; + _update_name(); } break; case VIEW_CENTER_TO_SELECTION: { @@ -1924,6 +1981,7 @@ void SpatialEditorViewport::_menu_option(int p_option) { view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false ); orthogonal=false; call_deferred("update_transform_gizmo_view"); + _update_name(); } break; case VIEW_ORTHOGONAL: { @@ -1932,6 +1990,7 @@ void SpatialEditorViewport::_menu_option(int p_option) { view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true ); orthogonal=true; call_deferred("update_transform_gizmo_view"); + _update_name(); } break; case VIEW_AUDIO_LISTENER: { @@ -1971,12 +2030,12 @@ void SpatialEditorViewport::_preview_exited_scene() { void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { - uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx)|(1<<GIZMO_GRID_LAYER); + uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx);//|(1<<GIZMO_GRID_LAYER); for(int i=0;i<3;i++) { move_gizmo_instance[i]=VS::get_singleton()->instance_create(); VS::get_singleton()->instance_set_base(move_gizmo_instance[i],spatial_editor->get_move_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i],get_scene()->get_root()->get_world()->get_scenario()); + VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i],get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_VISIBLE,false); //VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true); VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_CAST_SHADOW,false); @@ -1984,7 +2043,7 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) { rotate_gizmo_instance[i]=VS::get_singleton()->instance_create(); VS::get_singleton()->instance_set_base(rotate_gizmo_instance[i],spatial_editor->get_rotate_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i],get_scene()->get_root()->get_world()->get_scenario()); + VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i],get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_VISIBLE,false); //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true); VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_CAST_SHADOW,false); @@ -2001,7 +2060,7 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { if (!p_activate) { - previewing->disconnect("exit_scene",this,"_preview_exited_scene"); + previewing->disconnect("exit_tree",this,"_preview_exited_scene"); previewing=NULL; VS::get_singleton()->viewport_attach_camera( viewport->get_viewport(), camera->get_camera() ); //restore if (!preview) @@ -2012,7 +2071,7 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { } else { previewing=preview; - previewing->connect("exit_scene",this,"_preview_exited_scene"); + previewing->connect("exit_tree",this,"_preview_exited_scene"); VS::get_singleton()->viewport_attach_camera( viewport->get_viewport(), preview->get_camera() ); //replace view_menu->hide(); surface->update(); @@ -2130,15 +2189,13 @@ void SpatialEditorViewport::reset() { message_time=0; message=""; last_message=""; + name="Top"; cursor.x_rot=0; cursor.y_rot=0; cursor.distance=4; cursor.region_select=false; - - - - + _update_name(); } SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) { @@ -2172,18 +2229,17 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu = memnew( MenuButton ); surface->add_child(view_menu); view_menu->set_pos( Point2(4,4)); - view_menu->set_text("[view]"); view_menu->set_self_opacity(0.5); - view_menu->get_popup()->add_item("Top",VIEW_TOP); - view_menu->get_popup()->add_item("Bottom",VIEW_BOTTOM); - view_menu->get_popup()->add_item("Left",VIEW_LEFT); - view_menu->get_popup()->add_item("Right",VIEW_RIGHT); - view_menu->get_popup()->add_item("Front",VIEW_FRONT); - view_menu->get_popup()->add_item("Rear",VIEW_REAR); + view_menu->get_popup()->add_item("Top (Num7)",VIEW_TOP); + view_menu->get_popup()->add_item("Bottom (Shift+Num7)",VIEW_BOTTOM); + view_menu->get_popup()->add_item("Left (Num3)",VIEW_LEFT); + view_menu->get_popup()->add_item("Right (Shift+Num3)",VIEW_RIGHT); + view_menu->get_popup()->add_item("Front (Num1)",VIEW_FRONT); + view_menu->get_popup()->add_item("Rear (Shift+Num1)",VIEW_REAR); view_menu->get_popup()->add_separator(); - view_menu->get_popup()->add_check_item("Perspective",VIEW_PERSPECTIVE); - view_menu->get_popup()->add_check_item("Orthogonal",VIEW_ORTHOGONAL); + view_menu->get_popup()->add_check_item("Perspective (Num5)",VIEW_PERSPECTIVE); + view_menu->get_popup()->add_check_item("Orthogonal (Num5)",VIEW_ORTHOGONAL); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE),true); view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_check_item("Environment",VIEW_ENVIRONMENT); @@ -2216,6 +2272,10 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed viewport->set_as_audio_listener(true); } + + name="Top"; + _update_name(); + EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view"); } @@ -2313,7 +2373,7 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) { // si->aabb = VisualServer::get_singleton()->instance_get_base_aabb(inst); - if (get_scene()->is_editor_hint()) + if (get_tree()->is_editor_hint()) editor->call("edit_node",sp); @@ -2454,7 +2514,7 @@ void SpatialEditor::set_state(const Dictionary& p_state) { VisualServer::get_singleton()->free(light_instance); light_instance=RID(); } else { - light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->get_root()->get_world()->get_scenario()); + light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario()); VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform); } @@ -2656,7 +2716,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { VisualServer::get_singleton()->free(light_instance); light_instance=RID(); } else { - light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->get_root()->get_world()->get_scenario()); + light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario()); VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform); _update_default_light_angle(); @@ -2828,7 +2888,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { case MENU_VIEW_DISPLAY_NORMAL: { - VisualServer::get_singleton()->scenario_set_debug( get_scene()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_DISABLED ); + VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_DISABLED ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false ); @@ -2838,7 +2898,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_DISPLAY_WIREFRAME: { - VisualServer::get_singleton()->scenario_set_debug( get_scene()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_WIREFRAME ); + VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_WIREFRAME ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), true ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false ); @@ -2847,7 +2907,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_DISPLAY_OVERDRAW: { - VisualServer::get_singleton()->scenario_set_debug( get_scene()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_OVERDRAW ); + VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_OVERDRAW ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), true ); @@ -2856,7 +2916,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) { } break; case MENU_VIEW_DISPLAY_SHADELESS: { - VisualServer::get_singleton()->scenario_set_debug( get_scene()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_SHADELESS ); + VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_SHADELESS ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false ); view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false ); @@ -2903,7 +2963,7 @@ void SpatialEditor::_init_indicators() { //make sure that the camera indicator is not selectable light=VisualServer::get_singleton()->light_create( VisualServer::LIGHT_DIRECTIONAL ); //VisualServer::get_singleton()->light_set_shadow( light, true ); - light_instance=VisualServer::get_singleton()->instance_create2(light,get_scene()->get_root()->get_world()->get_scenario()); + light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario()); @@ -2964,7 +3024,7 @@ void SpatialEditor::_init_indicators() { d[VisualServer::ARRAY_COLOR]=grid_colors[i]; VisualServer::get_singleton()->mesh_add_surface(grid[i],VisualServer::PRIMITIVE_LINES,d); VisualServer::get_singleton()->mesh_surface_set_material(grid[i],0,indicator_mat); - grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i],get_scene()->get_root()->get_world()->get_scenario()); + grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i],get_tree()->get_root()->get_world()->get_scenario()); grid_visible[i]=false; grid_enable[i]=false; @@ -2988,7 +3048,7 @@ void SpatialEditor::_init_indicators() { // origin = VisualServer::get_singleton()->poly_create(); // VisualServer::get_singleton()->poly_add_primitive(origin,origin_points,Vector<Vector3>(),origin_colors,Vector<Vector3>()); // VisualServer::get_singleton()->poly_set_material(origin,indicator_mat,true); - origin_instance = VisualServer::get_singleton()->instance_create2(origin,get_scene()->get_root()->get_world()->get_scenario()); + origin_instance = VisualServer::get_singleton()->instance_create2(origin,get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_set_layer_mask(origin_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER); VisualServer::get_singleton()->instance_geometry_set_flag(origin_instance,VS::INSTANCE_FLAG_CAST_SHADOW,false); @@ -3025,7 +3085,7 @@ void SpatialEditor::_init_indicators() { VisualServer::get_singleton()->mesh_add_surface(cursor_mesh,VS::PRIMITIVE_LINES,d); VisualServer::get_singleton()->mesh_surface_set_material(cursor_mesh,0,cmat,true); - cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh,get_scene()->get_root()->get_world()->get_scenario()); + cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh,get_tree()->get_root()->get_world()->get_scenario()); VS::get_singleton()->instance_set_layer_mask(cursor_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER); VisualServer::get_singleton()->instance_geometry_set_flag(cursor_instance,VS::INSTANCE_FLAG_CAST_SHADOW,false); @@ -3306,19 +3366,19 @@ void SpatialEditor::_notification(int p_what) { _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT); - get_scene()->connect("node_removed",this,"_node_removed"); + get_tree()->connect("node_removed",this,"_node_removed"); VS::get_singleton()->scenario_set_fallback_environment(get_viewport()->find_world()->get_scenario(),viewport_environment->get_rid()); } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { gizmos = memnew( SpatialEditorGizmos ); _init_indicators(); _update_default_light_angle(); } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { _finish_indicators(); memdelete( gizmos ); @@ -3633,12 +3693,12 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p->add_check_item("Use Default sRGB",MENU_VIEW_USE_DEFAULT_SRGB); p->add_separator(); - p->add_check_item("1 Viewport",MENU_VIEW_USE_1_VIEWPORT,KEY_MASK_ALT+KEY_1); - p->add_check_item("2 Viewports",MENU_VIEW_USE_2_VIEWPORTS,KEY_MASK_ALT+KEY_2); - p->add_check_item("2 Viewports (Alt)",MENU_VIEW_USE_2_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_2); - p->add_check_item("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,KEY_MASK_ALT+KEY_3); - p->add_check_item("3 Viewports (Alt)",MENU_VIEW_USE_3_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_3); - p->add_check_item("4 Viewports",MENU_VIEW_USE_4_VIEWPORTS,KEY_MASK_ALT+KEY_4); + p->add_check_item("1 Viewport",MENU_VIEW_USE_1_VIEWPORT,KEY_MASK_CMD+KEY_1); + p->add_check_item("2 Viewports",MENU_VIEW_USE_2_VIEWPORTS,KEY_MASK_CMD+KEY_2); + p->add_check_item("2 Viewports (Alt)",MENU_VIEW_USE_2_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_2); + p->add_check_item("3 Viewports",MENU_VIEW_USE_3_VIEWPORTS,KEY_MASK_CMD+KEY_3); + p->add_check_item("3 Viewports (Alt)",MENU_VIEW_USE_3_VIEWPORTS_ALT,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_3); + p->add_check_item("4 Viewports",MENU_VIEW_USE_4_VIEWPORTS,KEY_MASK_CMD+KEY_4); p->add_separator(); p->add_check_item("Display Normal",MENU_VIEW_DISPLAY_NORMAL); @@ -3649,7 +3709,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { p->add_check_item("View Origin",MENU_VIEW_ORIGIN); p->add_check_item("View Grid",MENU_VIEW_GRID); p->add_separator(); - p->add_check_item("Settings",MENU_VIEW_CAMERA_SETTINGS ); + p->add_item("Settings",MENU_VIEW_CAMERA_SETTINGS); p->set_item_checked( p->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), true ); diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h index 1fdc97c49d..4d594d1921 100644 --- a/tools/editor/plugins/spatial_editor_plugin.h +++ b/tools/editor/plugins/spatial_editor_plugin.h @@ -92,6 +92,7 @@ public: }; private: int index; + String name; void _menu_option(int p_option); Size2 prev_size; @@ -110,6 +111,7 @@ private: bool orthogonal; float gizmo_scale; + void _update_name(); void _compute_edit(const Point2& p_point); void _clear_selected(); void _select_clicked(bool p_append,bool p_single); @@ -144,6 +146,12 @@ private: }; NavigationScheme _get_navigation_schema(const String& p_property); + enum NavigationZoomStyle { + NAVIGATION_ZOOM_VERTICAL, + NAVIGATION_ZOOM_HORIZONTAL + }; + NavigationZoomStyle _get_navigation_zoom_style(const String& p_property); + enum NavigationMode { NAVIGATION_NONE, NAVIGATION_PAN, diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp index a26fab0f9a..9a9e8ee611 100644 --- a/tools/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/tools/editor/plugins/sprite_frames_editor_plugin.cpp @@ -46,7 +46,7 @@ void SpriteFramesEditor::_notification(int p_what) { } - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { load->set_icon( get_icon("Folder","EditorIcons") ); _delete->set_icon( get_icon("Del","EditorIcons") ); } @@ -229,6 +229,33 @@ void SpriteFramesEditor::_empty_pressed() { } +void SpriteFramesEditor::_empty2_pressed() { + + + int from=-1; + + if (tree->get_selected()) { + + from = tree->get_selected()->get_metadata(0); + sel=from; + + } else { + from=frames->get_frame_count(); + } + + + + Ref<Texture> r; + + undo_redo->create_action("Add Empty"); + undo_redo->add_do_method(frames,"add_frame",r,from+1); + undo_redo->add_undo_method(frames,"remove_frame",from+1); + undo_redo->add_do_method(this,"_update_library"); + undo_redo->add_undo_method(this,"_update_library"); + undo_redo->commit_action(); + +} + void SpriteFramesEditor::_up_pressed() { if (!tree->get_selected()) @@ -322,6 +349,8 @@ void SpriteFramesEditor::_update_library() { ti->set_text(0,"Frame "+itos(i)); ti->set_icon(0,frames->get_frame(i)); } + if (frames->get_frame(i).is_valid()) + ti->set_tooltip(0,frames->get_frame(i)->get_path()); ti->set_metadata(0,i); ti->set_icon_max_width(0,96); if (sel==i) @@ -355,6 +384,7 @@ void SpriteFramesEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&SpriteFramesEditor::_input_event); ObjectTypeDB::bind_method(_MD("_load_pressed"),&SpriteFramesEditor::_load_pressed); ObjectTypeDB::bind_method(_MD("_empty_pressed"),&SpriteFramesEditor::_empty_pressed); + ObjectTypeDB::bind_method(_MD("_empty2_pressed"),&SpriteFramesEditor::_empty2_pressed); ObjectTypeDB::bind_method(_MD("_item_edited"),&SpriteFramesEditor::_item_edited); ObjectTypeDB::bind_method(_MD("_delete_pressed"),&SpriteFramesEditor::_delete_pressed); ObjectTypeDB::bind_method(_MD("_paste_pressed"),&SpriteFramesEditor::_paste_pressed); @@ -387,9 +417,13 @@ SpriteFramesEditor::SpriteFramesEditor() { hbc->add_child(paste); empty = memnew( Button ); - empty->set_text("Insert Empty"); + empty->set_text("Insert Empty (Before)"); hbc->add_child(empty); + empty2 = memnew( Button ); + empty2->set_text("Insert Empty (After)"); + hbc->add_child(empty2); + move_up = memnew( Button ); move_up->set_text("Up"); hbc->add_child(move_up); @@ -422,6 +456,7 @@ SpriteFramesEditor::SpriteFramesEditor() { _delete->connect("pressed", this,"_delete_pressed"); paste->connect("pressed", this,"_paste_pressed"); empty->connect("pressed", this,"_empty_pressed"); + empty2->connect("pressed", this,"_empty2_pressed"); move_up->connect("pressed", this,"_up_pressed"); move_down->connect("pressed", this,"_down_pressed"); file->connect("files_selected", this,"_file_load_request"); diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.h b/tools/editor/plugins/sprite_frames_editor_plugin.h index 99c6ad486e..b0f2201b9e 100644 --- a/tools/editor/plugins/sprite_frames_editor_plugin.h +++ b/tools/editor/plugins/sprite_frames_editor_plugin.h @@ -46,6 +46,7 @@ class SpriteFramesEditor : public PanelContainer { Button *_delete; Button *paste; Button *empty; + Button *empty2; Button *move_up; Button *move_down; Tree *tree; @@ -65,6 +66,7 @@ class SpriteFramesEditor : public PanelContainer { void _file_load_request(const DVector<String>& p_path); void _paste_pressed(); void _empty_pressed(); + void _empty2_pressed(); void _delete_pressed(); void _delete_confirm_pressed(); void _up_pressed(); diff --git a/tools/editor/plugins/stream_editor_plugin.cpp b/tools/editor/plugins/stream_editor_plugin.cpp index 4588c694ee..6477cce47c 100644 --- a/tools/editor/plugins/stream_editor_plugin.cpp +++ b/tools/editor/plugins/stream_editor_plugin.cpp @@ -32,7 +32,7 @@ void StreamEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { play->set_icon( get_icon("Play","EditorIcons") ); stop->set_icon( get_icon("Stop","EditorIcons") ); } diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/tools/editor/plugins/theme_editor_plugin.cpp index ccbd923118..bd6fb37b29 100644 --- a/tools/editor/plugins/theme_editor_plugin.cpp +++ b/tools/editor/plugins/theme_editor_plugin.cpp @@ -568,6 +568,26 @@ ThemeEditor::ThemeEditor() { CheckButton *cb = memnew( CheckButton ); cb->set_text("CheckButton"); first_vb->add_child(cb ); + CheckBox *cbx = memnew( CheckBox ); + cbx->set_text("CheckBox"); + first_vb->add_child(cbx ); + + /* TODO: This is not working properly, controls are overlapping*/ + /* + ButtonGroup *bg = memnew( ButtonGroup ); + bg->set_v_size_flags(SIZE_EXPAND_FILL); + VBoxContainer *gbvb = memnew( VBoxContainer ); + gbvb->set_v_size_flags(SIZE_EXPAND_FILL); + CheckBox *rbx1 = memnew( CheckBox ); + rbx1->set_text("CheckBox Radio1"); + rbx1->set_pressed(true); + gbvb->add_child(rbx1); + CheckBox *rbx2 = memnew( CheckBox ); + rbx2->set_text("CheckBox Radio2"); + gbvb->add_child(rbx2); + bg->add_child(gbvb); + first_vb->add_child(bg); + */ MenuButton* test_menu_button = memnew( MenuButton ); test_menu_button->set_text("MenuButton"); diff --git a/tools/editor/plugins/theme_editor_plugin.h b/tools/editor/plugins/theme_editor_plugin.h index 98156422ee..83432b9232 100644 --- a/tools/editor/plugins/theme_editor_plugin.h +++ b/tools/editor/plugins/theme_editor_plugin.h @@ -33,6 +33,8 @@ #include "scene/gui/texture_frame.h" #include "scene/gui/option_button.h" #include "scene/gui/file_dialog.h" +#include "scene/gui/check_box.h" +#include "scene/gui/button_group.h" #include "tools/editor/editor_node.h" diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index a25997108b..79e43f9012 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -34,7 +34,7 @@ #include "os/file_access.h" #include "tools/editor/editor_settings.h" #include "os/input.h" - +#include "method_bind_ext.inc" void TileMapEditor::_notification(int p_what) { @@ -42,9 +42,13 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_READY: { - pane_drag->connect("dragged", this,"_pane_drag"); + transpose->set_icon( get_icon("Transpose","EditorIcons")); mirror_x->set_icon( get_icon("MirrorX","EditorIcons")); mirror_y->set_icon( get_icon("MirrorY","EditorIcons")); + rotate_0->set_icon( get_icon("Rotate0","EditorIcons")); + rotate_90->set_icon( get_icon("Rotate90","EditorIcons")); + rotate_180->set_icon( get_icon("Rotate180","EditorIcons")); + rotate_270->set_icon( get_icon("Rotate270","EditorIcons")); } break; } @@ -74,24 +78,43 @@ int TileMapEditor::get_selected_tile() const { return item->get_metadata(0); } -void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v,bool p_with_undo) { +void TileMapEditor::set_selected_tile(int p_tile) { + TreeItem *item = palette->get_root()->get_children(); + while (item) { + if ((int)item->get_metadata(0) == p_tile) { + item->select(0); + palette->ensure_cursor_is_visible(); + break; + } + item = item->get_next(); + } +} + +// Wrapper to workaround five arg limit of undo/redo methods +void TileMapEditor::_set_cell_shortened(const Point2& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose) { + ERR_FAIL_COND(!node); + node->set_cell(floor(p_pos.x), floor(p_pos.y), p_value, p_flip_h, p_flip_v, p_transpose); +} + +void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose,bool p_with_undo) { ERR_FAIL_COND(!node); bool prev_flip_h=node->is_cell_x_flipped(p_pos.x,p_pos.y); bool prev_flip_v=node->is_cell_y_flipped(p_pos.x,p_pos.y); + bool prev_transpose=node->is_cell_transposed(p_pos.x,p_pos.y); int prev_val=node->get_cell(p_pos.x,p_pos.y); - if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v) + if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v && p_transpose==prev_transpose) return; //check that it's actually different if (p_with_undo) { - undo_redo->add_do_method(node,"set_cell",p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v); - undo_redo->add_undo_method(node,"set_cell",p_pos.x,p_pos.y,prev_val,prev_flip_h,prev_flip_v); + undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose); + undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose); } else { - node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v); + node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose); } @@ -157,6 +180,7 @@ struct _TileMapEditorCopyData { int cell; bool flip_h; bool flip_v; + bool transpose; }; bool TileMapEditor::forward_input_event(const InputEvent& p_event) { @@ -193,6 +217,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { tcd.cell=node->get_cell(j,i); tcd.flip_h=node->is_cell_x_flipped(j,i); tcd.flip_v=node->is_cell_y_flipped(j,i); + tcd.transpose=node->is_cell_transposed(j,i); dupdata.push_back(tcd); @@ -203,7 +228,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for (List<_TileMapEditorCopyData>::Element *E=dupdata.front();E;E=E->next()) { - _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,true); + _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true); } undo_redo->commit_action(); @@ -225,28 +250,29 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { canvas_item_editor->update(); return true; + } else if (mb.mod.control) { + tool=TOOL_PICKING; + set_selected_tile(node->get_cell(over_tile.x, over_tile.y)); + mirror_x->set_pressed(node->is_cell_x_flipped(over_tile.x, over_tile.y)); + mirror_y->set_pressed(node->is_cell_y_flipped(over_tile.x, over_tile.y)); + transpose->set_pressed(node->is_cell_transposed(over_tile.x, over_tile.y)); + _update_transform_buttons(); + canvas_item_editor->update(); + return true; } else { int id = get_selected_tile(); if (id!=TileMap::INVALID_CELL) { tool=TOOL_PAINTING; Point2i local =node->world_to_map((xform_inv.xform(Point2(mb.x,mb.y)))); paint_undo.clear(); - CellOp op; - op.idx = node->get_cell(local.x,local.y); - if (op.idx>=0) { - if (node->is_cell_x_flipped(local.x,local.y)) - op.xf=true; - if (node->is_cell_y_flipped(local.x,local.y)) - op.yf=true; - } - paint_undo[local]=op; - node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + paint_undo[local]=_get_op_from_cell(local); + node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); return true; } } } else { - if (tool==TOOL_PAINTING || tool == TOOL_SELECTING) { + if (tool==TOOL_PAINTING || tool == TOOL_SELECTING || tool == TOOL_PICKING) { if (tool==TOOL_PAINTING) { @@ -255,8 +281,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y)); - undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf); + undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); @@ -280,16 +306,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { tool=TOOL_ERASING; Point2i local =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y))); paint_undo.clear(); - CellOp op; - op.idx = node->get_cell(local.x,local.y); - if (op.idx>=0) { - if (node->is_cell_x_flipped(local.x,local.y)) - op.xf=true; - if (node->is_cell_y_flipped(local.x,local.y)) - op.yf=true; - } - paint_undo[local]=op; - //node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + paint_undo[local]=_get_op_from_cell(local); + //node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); //return true; _set_cell(local,TileMap::INVALID_CELL); return true; @@ -302,9 +320,9 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - //undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y)); - _set_cell(p,TileMap::INVALID_CELL,false,false,true); - undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf); + //undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + _set_cell(p,TileMap::INVALID_CELL,false,false,false,true); + undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); @@ -338,17 +356,9 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { if (!paint_undo.has(over_tile)) { - CellOp op; - op.idx = node->get_cell(over_tile.x,over_tile.y); - if (op.idx>=0) { - if (node->is_cell_x_flipped(over_tile.x,over_tile.y)) - op.xf=true; - if (node->is_cell_y_flipped(over_tile.x,over_tile.y)) - op.yf=true; - } - paint_undo[over_tile]=op; + paint_undo[over_tile]=_get_op_from_cell(over_tile); } - node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); return true; } @@ -375,25 +385,26 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { return true; } + if (tool==TOOL_ERASING) { Point2i local =over_tile; if (!paint_undo.has(over_tile)) { - - CellOp op; - op.idx = node->get_cell(over_tile.x,over_tile.y); - if (op.idx>=0) { - if (node->is_cell_x_flipped(over_tile.x,over_tile.y)) - op.xf=true; - if (node->is_cell_y_flipped(over_tile.x,over_tile.y)) - op.yf=true; - } - paint_undo[over_tile]=op; + paint_undo[over_tile]=_get_op_from_cell(over_tile); } - //node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + //node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); _set_cell(local,TileMap::INVALID_CELL); return true; } + if (tool==TOOL_PICKING) { + set_selected_tile(node->get_cell(over_tile.x, over_tile.y)); + mirror_x->set_pressed(node->is_cell_x_flipped(over_tile.x, over_tile.y)); + mirror_y->set_pressed(node->is_cell_y_flipped(over_tile.x, over_tile.y)); + transpose->set_pressed(node->is_cell_transposed(over_tile.x, over_tile.y)); + _update_transform_buttons(); + canvas_item_editor->update(); + return true; + } } break; case InputEvent::KEY: { @@ -629,19 +640,53 @@ void TileMapEditor::_canvas_draw() { Ref<Texture> t = ts->tile_get_texture(st); if (t.is_valid()) { - Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset()); + Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset(); Rect2 r = ts->tile_get_region(st); Size2 sc = xform.get_scale(); if (mirror_x->is_pressed()) sc.x*=-1.0; if (mirror_y->is_pressed()) sc.y*=-1.0; + + Rect2 rect; + if (r==Rect2()) { + rect=Rect2(from,t->get_size()); + } else { + + rect=Rect2(from,r.get_size()); + } + + + if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) { + rect.pos+=ts->tile_get_texture_offset(st); + + } else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_CENTER) { + rect.pos+=node->get_cell_size()/2; + Vector2 s = r.size; + + Vector2 center = (s/2) - ts->tile_get_texture_offset(st); + + + if (mirror_x->is_pressed()) + rect.pos.x-=s.x-center.x; + else + rect.pos.x-=center.x; + + if (mirror_y->is_pressed()) + rect.pos.y-=s.y-center.y; + else + rect.pos.y-=center.y; + } + + rect.pos=xform.xform(rect.pos); + rect.size*=sc; + if (r==Rect2()) { - canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5)); + canvas_item_editor->draw_texture_rect(t,rect,false,Color(1,1,1,0.5),transpose->is_pressed()); } else { - canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5)); + canvas_item_editor->draw_texture_rect_region(t,rect,r,Color(1,1,1,0.5),transpose->is_pressed()); } } } @@ -701,27 +746,79 @@ void TileMapEditor::_tileset_settings_changed() { canvas_item_editor->update(); } -void TileMapEditor::_pane_drag(const Point2& p_to) { - - int x = theme_panel->get_margin(MARGIN_RIGHT); - - x+=p_to.x; - if (x<10) - x=10; - if (x>300) - x=300; - theme_panel->set_margin(MARGIN_RIGHT,x); -} - void TileMapEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_menu_option"),&TileMapEditor::_menu_option); ObjectTypeDB::bind_method(_MD("_canvas_draw"),&TileMapEditor::_canvas_draw); - ObjectTypeDB::bind_method(_MD("_pane_drag"),&TileMapEditor::_pane_drag); ObjectTypeDB::bind_method(_MD("_canvas_mouse_enter"),&TileMapEditor::_canvas_mouse_enter); ObjectTypeDB::bind_method(_MD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit); ObjectTypeDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed); + ObjectTypeDB::bind_method(_MD("_update_transform_buttons"),&TileMapEditor::_update_transform_buttons); + ObjectTypeDB::bind_method(_MD("_set_cell_shortened","pos","tile","flip_x","flip_y","transpose"),&TileMapEditor::_set_cell_shortened,DEFVAL(false),DEFVAL(false),DEFVAL(false)); + +} +TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i& p_pos) +{ + CellOp op; + op.idx = node->get_cell(p_pos.x,p_pos.y); + if (op.idx>=0) { + if (node->is_cell_x_flipped(p_pos.x,p_pos.y)) + op.xf=true; + if (node->is_cell_y_flipped(p_pos.x,p_pos.y)) + op.yf=true; + if (node->is_cell_transposed(p_pos.x,p_pos.y)) + op.tr=true; + } + return op; +} + +void TileMapEditor::_update_transform_buttons(Object *p_button) { + //ERR_FAIL_NULL(p_button); + ToolButton *b=p_button->cast_to<ToolButton>(); + //ERR_FAIL_COND(!b); + + mirror_x->set_block_signals(true); + mirror_y->set_block_signals(true); + transpose->set_block_signals(true); + rotate_0->set_block_signals(true); + rotate_90->set_block_signals(true); + rotate_180->set_block_signals(true); + rotate_270->set_block_signals(true); + + if (b == rotate_0) { + mirror_x->set_pressed(false); + mirror_y->set_pressed(false); + transpose->set_pressed(false); + } + else if (b == rotate_90) { + mirror_x->set_pressed(true); + mirror_y->set_pressed(false); + transpose->set_pressed(true); + } + else if (b == rotate_180) { + mirror_x->set_pressed(true); + mirror_y->set_pressed(true); + transpose->set_pressed(false); + } + else if (b == rotate_270) { + mirror_x->set_pressed(false); + mirror_y->set_pressed(true); + transpose->set_pressed(true); + } + + rotate_0->set_pressed(!mirror_x->is_pressed() && !mirror_y->is_pressed() && !transpose->is_pressed()); + rotate_90->set_pressed(mirror_x->is_pressed() && !mirror_y->is_pressed() && transpose->is_pressed()); + rotate_180->set_pressed(mirror_x->is_pressed() && mirror_y->is_pressed() && !transpose->is_pressed()); + rotate_270->set_pressed(!mirror_x->is_pressed() && mirror_y->is_pressed() && transpose->is_pressed()); + + mirror_x->set_block_signals(false); + mirror_y->set_block_signals(false); + transpose->set_block_signals(false); + rotate_0->set_block_signals(false); + rotate_90->set_block_signals(false); + rotate_180->set_block_signals(false); + rotate_270->set_block_signals(false); } TileMapEditor::TileMapEditor(EditorNode *p_editor) { @@ -731,37 +828,66 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { editor=p_editor; undo_redo = editor->get_undo_redo(); - theme_panel = memnew( Panel ); - theme_panel->set_anchor(MARGIN_BOTTOM,ANCHOR_END); - theme_panel->set_begin( Point2(0,26)); - theme_panel->set_end( Point2(100,0) ); - p_editor->get_viewport()->add_child(theme_panel); - theme_panel->hide(); + int mw = EDITOR_DEF("tile_map/palette_min_width",80); + Control *ec = memnew( Control); + ec->set_custom_minimum_size(Size2(mw,0)); + add_child(ec); + // Add tile palette palette = memnew( Tree ); - palette->set_area_as_parent_rect(4); - palette->set_margin(MARGIN_TOP,25);; - theme_panel->add_child(palette); - - pane_drag = memnew( PaneDrag ) ; - pane_drag->set_anchor(MARGIN_LEFT,ANCHOR_END); - pane_drag->set_begin(Point2(16,4)); - theme_panel->add_child(pane_drag); - - add_child( memnew( VSeparator )); - + palette->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(palette); + + // Add menu items + canvas_item_editor_hb = memnew( HBoxContainer ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(canvas_item_editor_hb); + canvas_item_editor_hb->add_child( memnew( VSeparator )); + transpose = memnew( ToolButton ); + transpose->set_toggle_mode(true); + transpose->set_tooltip("Transpose"); + transpose->set_focus_mode(FOCUS_NONE); + transpose->connect("pressed", this, "_update_transform_buttons", make_binds(transpose)); + canvas_item_editor_hb->add_child(transpose); mirror_x = memnew( ToolButton ); mirror_x->set_toggle_mode(true); mirror_x->set_tooltip("Mirror X (A)"); mirror_x->set_focus_mode(FOCUS_NONE); - add_child(mirror_x); + mirror_x->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_x)); + canvas_item_editor_hb->add_child(mirror_x); mirror_y = memnew( ToolButton ); mirror_y->set_toggle_mode(true); mirror_y->set_tooltip("Mirror Y (S)"); mirror_y->set_focus_mode(FOCUS_NONE); - add_child(mirror_y); - - + mirror_y->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_y)); + canvas_item_editor_hb->add_child(mirror_y); + canvas_item_editor_hb->add_child(memnew(VSeparator)); + rotate_0 = memnew( ToolButton ); + rotate_0->set_toggle_mode(true); + rotate_0->set_tooltip("Rotate 0 degrees"); + rotate_0->set_focus_mode(FOCUS_NONE); + rotate_0->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_0)); + canvas_item_editor_hb->add_child(rotate_0); + rotate_90 = memnew( ToolButton ); + rotate_90->set_toggle_mode(true); + rotate_90->set_tooltip("Rotate 90 degrees"); + rotate_90->set_focus_mode(FOCUS_NONE); + rotate_90->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_90)); + canvas_item_editor_hb->add_child(rotate_90); + rotate_180 = memnew( ToolButton ); + rotate_180->set_toggle_mode(true); + rotate_180->set_tooltip("Rotate 180 degrees"); + rotate_180->set_focus_mode(FOCUS_NONE); + rotate_180->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_180)); + canvas_item_editor_hb->add_child(rotate_180); + rotate_270 = memnew( ToolButton ); + rotate_270->set_toggle_mode(true); + rotate_270->set_tooltip("Rotate 270 degrees"); + rotate_270->set_focus_mode(FOCUS_NONE); + rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270)); + canvas_item_editor_hb->add_child(rotate_270); + canvas_item_editor_hb->hide(); + + rotate_0->set_pressed(true); tool=TOOL_NONE; selection_active=false; mouse_over=false; @@ -782,12 +908,12 @@ void TileMapEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tile_map_editor->show(); - tile_map_editor->theme_panel->show(); + tile_map_editor->get_canvas_item_editor_hb()->show(); } else { tile_map_editor->hide(); - tile_map_editor->theme_panel->hide(); + tile_map_editor->get_canvas_item_editor_hb()->hide(); tile_map_editor->edit(NULL); } @@ -797,7 +923,8 @@ TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) { editor=p_node; tile_map_editor = memnew( TileMapEditor(p_node) ); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(tile_map_editor); + CanvasItemEditor::get_singleton()->get_palette_split()->add_child(tile_map_editor); + CanvasItemEditor::get_singleton()->get_palette_split()->move_child(tile_map_editor,0); tile_map_editor->hide(); diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 2336507f1b..fe1295fe98 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -34,15 +34,14 @@ #include "scene/2d/tile_map.h" #include "scene/gui/tool_button.h" #include "scene/gui/button_group.h" -#include "tools/editor/pane_drag.h" /** @author Juan Linietsky <reduzio@gmail.com> */ class CanvasItemEditor; -class TileMapEditor : public HBoxContainer { +class TileMapEditor : public VBoxContainer { - OBJ_TYPE(TileMapEditor, BoxContainer ); + OBJ_TYPE(TileMapEditor, VBoxContainer ); UndoRedo *undo_redo; @@ -52,7 +51,8 @@ class TileMapEditor : public HBoxContainer { TOOL_PAINTING, TOOL_SELECTING, TOOL_ERASING, - TOOL_DUPLICATING + TOOL_DUPLICATING, + TOOL_PICKING }; Tool tool; @@ -63,7 +63,6 @@ class TileMapEditor : public HBoxContainer { Panel *panel; TileMap *node; MenuButton *options; - PaneDrag *pane_drag; bool selection_active; Point2i selection_begin; @@ -72,42 +71,51 @@ class TileMapEditor : public HBoxContainer { bool mouse_over; Label *mirror_label; + ToolButton *transpose; ToolButton *mirror_x; ToolButton *mirror_y; + ToolButton *rotate_0; + ToolButton *rotate_90; + ToolButton *rotate_180; + ToolButton *rotate_270; + + HBoxContainer *canvas_item_editor_hb; struct CellOp { int idx; bool xf; bool yf; - CellOp() { idx=-1; xf=false; yf=false; } + bool tr; + CellOp() { idx=-1; xf=false; yf=false; tr=false; } }; Map<Point2i,CellOp> paint_undo; int get_selected_tile() const; + void set_selected_tile(int p_tile); void _update_palette(); - void _pane_drag(const Point2& p_to); void _canvas_draw(); void _menu_option(int p_option); - void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_with_undo=false); + void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false, bool p_with_undo=false); + void _set_cell_shortened(const Point2& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false); void _canvas_mouse_enter(); void _canvas_mouse_exit(); void _tileset_settings_changed(); -friend class TileMapEditorPlugin; - Panel *theme_panel; protected: void _notification(int p_what); void _node_removed(Node *p_node); static void _bind_methods(); + CellOp _get_op_from_cell(const Point2i& p_pos); + void _update_transform_buttons(Object *p_button=0); public: - Vector2 snap_point(const Vector2& p_point) const; + HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; } bool forward_input_event(const InputEvent& p_event); void edit(Node *p_tile_map); TileMapEditor(EditorNode *p_editor); @@ -120,6 +128,7 @@ class TileMapEditorPlugin : public EditorPlugin { TileMapEditor *tile_map_editor; EditorNode *editor; + public: virtual bool forward_input_event(const InputEvent& p_event) { return tile_map_editor->forward_input_event(p_event); } diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/tools/editor/plugins/tile_set_editor_plugin.cpp index a51caf7d54..8ff7720934 100644 --- a/tools/editor/plugins/tile_set_editor_plugin.cpp +++ b/tools/editor/plugins/tile_set_editor_plugin.cpp @@ -37,83 +37,103 @@ void TileSetEditor::edit(const Ref<TileSet>& p_tileset) { void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_merge) { if (!p_merge) - p_library->clear(); + p_library->clear(); for(int i=0;i<scene->get_child_count();i++) { - Node *child = scene->get_child(i); + Node *child = scene->get_child(i); - if (!child->cast_to<Sprite>()) { - if (child->get_child_count()>0) { - child=child->get_child(0); - if (!child->cast_to<Sprite>()) { - continue; - } + if (!child->cast_to<Sprite>()) { + if (child->get_child_count()>0) { + child=child->get_child(0); + if (!child->cast_to<Sprite>()) { + continue; + } - } else - continue; + } else + continue; - } + } - Sprite *mi = child->cast_to<Sprite>(); - Ref<Texture> texture=mi->get_texture(); - if (texture.is_null()) + Sprite *mi = child->cast_to<Sprite>(); + Ref<Texture> texture=mi->get_texture(); + Ref<CanvasItemMaterial> material=mi->get_material(); + + if (texture.is_null()) continue; - int id = p_library->find_tile_by_name(mi->get_name()); - if (id<0) { - - id=p_library->get_last_unused_tile_id(); - p_library->create_tile(id); - p_library->tile_set_name(id,mi->get_name()); - } - - - p_library->tile_set_texture(id,texture); - Vector2 phys_offset; - - if (mi->is_centered()) { - Size2 s; - if (mi->is_region()) { - s=mi->get_region_rect().size; - } else { - s=texture->get_size(); - } - phys_offset+=-s/2; - } - if (mi->is_region()) { - p_library->tile_set_region(id,mi->get_region_rect()); - } - - Vector<Ref<Shape2D> >collisions; - - for(int j=0;j<mi->get_child_count();j++) { - - Node *child2 = mi->get_child(j); - if (!child2->cast_to<StaticBody2D>()) - continue; - StaticBody2D *sb = child2->cast_to<StaticBody2D>(); - if (sb->get_shape_count()==0) - continue; - Ref<Shape2D> collision=sb->get_shape(0); - if (collision.is_valid()) { - collisions.push_back(collision); + int id = p_library->find_tile_by_name(mi->get_name()); + if (id<0) { + + id=p_library->get_last_unused_tile_id(); + p_library->create_tile(id); + p_library->tile_set_name(id,mi->get_name()); + } + + + + p_library->tile_set_texture(id,texture); + p_library->tile_set_material(id,material); + + Vector2 phys_offset; + + if (mi->is_centered()) { + Size2 s; + if (mi->is_region()) { + s=mi->get_region_rect().size; + } else { + s=texture->get_size(); + } + phys_offset+=-s/2; + } + if (mi->is_region()) { + p_library->tile_set_region(id,mi->get_region_rect()); + } + + Vector<Ref<Shape2D> >collisions; + Ref<NavigationPolygon> nav_poly; + Ref<OccluderPolygon2D> occluder; + + for(int j=0;j<mi->get_child_count();j++) { + + Node *child2 = mi->get_child(j); + + if (child2->cast_to<NavigationPolygonInstance>()) + nav_poly=child2->cast_to<NavigationPolygonInstance>()->get_navigation_polygon(); + + if (child2->cast_to<LightOccluder2D>()) + occluder=child2->cast_to<LightOccluder2D>()->get_occluder_polygon(); + + if (!child2->cast_to<StaticBody2D>()) + continue; + StaticBody2D *sb = child2->cast_to<StaticBody2D>(); + if (sb->get_shape_count()==0) + continue; + Ref<Shape2D> collision=sb->get_shape(0); + if (collision.is_valid()) { + collisions.push_back(collision); } - } + } - if (collisions.size()) { + if (collisions.size()) { - p_library->tile_set_shapes(id,collisions); - p_library->tile_set_shape_offset(id,-phys_offset); - } else { - p_library->tile_set_shape_offset(id,Vector2()); + p_library->tile_set_shapes(id,collisions); + p_library->tile_set_shape_offset(id,-phys_offset); + } else { + p_library->tile_set_shape_offset(id,Vector2()); + + } + + p_library->tile_set_texture_offset(id,mi->get_offset()); + p_library->tile_set_navigation_polygon(id,nav_poly); + p_library->tile_set_light_occluder(id,occluder); + p_library->tile_set_occluder_offset(id,-phys_offset); + p_library->tile_set_navigation_polygon_offset(id,-phys_offset); - } - p_library->tile_set_texture_offset(id,mi->get_offset()); } } @@ -121,23 +141,23 @@ void TileSetEditor::_menu_confirm() { switch(option) { - case MENU_OPTION_REMOVE_ITEM: { + case MENU_OPTION_REMOVE_ITEM: { - tileset->remove_tile(to_erase); - } break; - case MENU_OPTION_MERGE_FROM_SCENE: - case MENU_OPTION_CREATE_FROM_SCENE: { + tileset->remove_tile(to_erase); + } break; + case MENU_OPTION_MERGE_FROM_SCENE: + case MENU_OPTION_CREATE_FROM_SCENE: { - EditorNode *en = editor; - Node * scene = en->get_edited_scene(); - if (!scene) - break; + EditorNode *en = editor; + Node * scene = en->get_edited_scene(); + if (!scene) + break; - _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE); + _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE); - } break; + } break; } } @@ -165,11 +185,11 @@ void TileSetEditor::_menu_cbk(int p_option) { cd->set_text("Create from scene?"); cd->popup_centered(Size2(300,60)); } break; - case MENU_OPTION_MERGE_FROM_SCENE: { + case MENU_OPTION_MERGE_FROM_SCENE: { - cd->set_text("Merge from scene?"); - cd->popup_centered(Size2(300,60)); - } break; + cd->set_text("Merge from scene?"); + cd->popup_centered(Size2(300,60)); + } break; } } diff --git a/tools/editor/plugins/tile_set_editor_plugin.h b/tools/editor/plugins/tile_set_editor_plugin.h index 2531ec55bf..1248b4e007 100644 --- a/tools/editor/plugins/tile_set_editor_plugin.h +++ b/tools/editor/plugins/tile_set_editor_plugin.h @@ -56,7 +56,7 @@ class TileSetEditor : public Control { int option; void _menu_cbk(int p_option); - void _menu_confirm(); + void _menu_confirm(); static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); diff --git a/tools/editor/progress_dialog.cpp b/tools/editor/progress_dialog.cpp index 42dd971bc3..df40c5d5a5 100644 --- a/tools/editor/progress_dialog.cpp +++ b/tools/editor/progress_dialog.cpp @@ -29,7 +29,7 @@ #include "progress_dialog.h" #include "main/main.h" #include "message_queue.h" -#include "scene/gui/empty_control.h" + void BackgroundProgress::_add_task(const String& p_task,const String& p_label, int p_steps) { @@ -43,12 +43,12 @@ void BackgroundProgress::_add_task(const String& p_task,const String& p_label, i t.progress = memnew( ProgressBar ); t.progress->set_max(p_steps); t.progress->set_val(p_steps); - EmptyControl *ec = memnew( EmptyControl ); + Control *ec = memnew( Control ); ec->set_h_size_flags(SIZE_EXPAND_FILL); ec->set_v_size_flags(SIZE_EXPAND_FILL); t.progress->set_area_as_parent_rect(); ec->add_child(t.progress); - ec->set_minsize(Size2(80,5)); + ec->set_custom_minimum_size(Size2(80,5)); t.hb->add_child(ec); add_child(t.hb); @@ -182,6 +182,7 @@ void ProgressDialog::add_task(const String& p_task,const String& p_label,int p_s t.progress->set_val(p_steps); vb2->add_child(t.progress); t.state=memnew( Label ); + t.state->set_clip_text(true); vb2->add_child(t.state); main->add_child(t.vb); diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 1da29c5e7b..449e54e12f 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -256,7 +256,7 @@ void ProjectExportDialog::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { CenterContainer *cc = memnew( CenterContainer ); @@ -320,7 +320,7 @@ void ProjectExportDialog::_notification(int p_what) { _update_group_tree(); } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { } break; case MainLoop::NOTIFICATION_WM_FOCUS_IN: { @@ -482,7 +482,7 @@ Error ProjectExportDialog::export_platform(const String& p_platform, const Strin return ERR_CANT_CREATE; } else { if (p_quit_after) { - get_scene()->quit(); + get_tree()->quit(); } } @@ -529,6 +529,8 @@ void ProjectExportDialog::_group_selected() { _update_group(); //? + + _update_group_tree(); } String ProjectExportDialog::_get_selected_group() { @@ -738,6 +740,8 @@ void ProjectExportDialog::_group_changed(Variant v) { EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg"); EditorNode::get_undo_redo()->commit_action(); updating=false; + // update atlas preview button + _update_group(); } void ProjectExportDialog::_group_item_edited() { @@ -1236,8 +1240,8 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { group_options->add_child(atlas_preview); atlas_preview->show(); atlas_preview->connect("pressed",this,"_group_atlas_preview"); - EmptyControl *ec = memnew(EmptyControl ); - ec->set_minsize(Size2(150,1)); + Control *ec = memnew(Control ); + ec->set_custom_minimum_size(Size2(150,1)); gvb->add_child(ec); VBoxContainer *group_vb_right = memnew( VBoxContainer ); diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h index dfe7a2d900..e437497dd2 100644 --- a/tools/editor/project_export.h +++ b/tools/editor/project_export.h @@ -40,7 +40,7 @@ #include "os/dir_access.h" #include "os/thread.h" #include "scene/gui/option_button.h" -#include "scene/gui/empty_control.h" + #include "scene/gui/slider.h" #include "tools/editor/editor_file_system.h" #include "property_editor.h" diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 5764f9f2d9..0af4a23547 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -39,7 +39,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/panel_container.h" -#include "scene/gui/empty_control.h" + #include "scene/gui/texture_frame.h" #include "scene/gui/margin_container.h" #include "io/resource_saver.h" @@ -65,7 +65,7 @@ class NewProjectDialog : public ConfirmationDialog { error->set_text(""); get_ok()->set_disabled(true); DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (d->change_dir(project_path->get_text())!=OK) { + if (project_path->get_text() != "" && d->change_dir(project_path->get_text())!=OK) { error->set_text("Invalid Path for Project, Path Must Exist!"); memdelete(d); return false; @@ -82,7 +82,7 @@ class NewProjectDialog : public ConfirmationDialog { } else { - if (!d->file_exists("engine.cfg")) { + if (project_path->get_text() != "" && !d->file_exists("engine.cfg")) { error->set_text("Invalid Project Path (engine.cfg must exist)."); memdelete(d); @@ -321,6 +321,7 @@ public: fdialog = memnew( FileDialog ); add_child(fdialog); fdialog->set_access(FileDialog::ACCESS_FILESYSTEM); + fdialog->set_current_dir( EditorSettings::get_singleton()->get("global/default_project_path") ); project_name->connect("text_changed", this,"_text_changed"); project_path->connect("text_changed", this,"_path_text_changed"); fdialog->connect("dir_selected", this,"_path_selected"); @@ -579,8 +580,8 @@ void ProjectManager::_load_recent_projects() { VBoxContainer *vb = memnew(VBoxContainer); hb->add_child(vb); - EmptyControl *ec = memnew( EmptyControl ); - ec->set_minsize(Size2(0,1)); + Control *ec = memnew( Control ); + ec->set_custom_minimum_size(Size2(0,1)); vb->add_child(ec); Label *title = memnew( Label(project_name) ); title->add_font_override("font",get_font("large","Fonts")); @@ -627,7 +628,7 @@ void ProjectManager::_open_project_confirm() { ERR_FAIL_COND(err); } - get_scene()->quit(); + get_tree()->quit(); } void ProjectManager::_open_project() { @@ -785,7 +786,7 @@ void ProjectManager::_erase_project() { void ProjectManager::_exit_dialog() { - get_scene()->quit(); + get_tree()->quit(); } void ProjectManager::_bind_methods() { @@ -973,6 +974,11 @@ ProjectManager::ProjectManager() { npdialog->connect("project_created", this,"_load_recent_projects"); _load_recent_projects(); + + if ( EditorSettings::get_singleton()->get("global/autoscan_project_path") ) { + _scan_begin( EditorSettings::get_singleton()->get("global/autoscan_project_path") ); + } + //get_ok()->set_text("Open"); //get_ok()->set_text("Exit"); @@ -1027,7 +1033,7 @@ void ProjectListFilter::_filter_option_selected(int p_idx) { void ProjectListFilter::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { clear_search_button->set_icon(get_icon("CloseHover","EditorIcons")); } break; } diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp index 105f251461..304fb76d1c 100644 --- a/tools/editor/project_settings.cpp +++ b/tools/editor/project_settings.cpp @@ -57,7 +57,7 @@ static const char* _button_names[JOY_BUTTON_MAX]={ void ProjectSettings::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { translation_list->connect("button_pressed",this,"_translation_delete"); _update_actions(); @@ -504,7 +504,7 @@ void ProjectSettings::popup_project_settings() { void ProjectSettings::_item_selected() { - TreeItem *ti = globals_editor->get_tree()->get_selected(); + TreeItem *ti = globals_editor->get_scene_tree()->get_selected(); if (!ti) return; if (!ti->get_parent()) @@ -1212,7 +1212,7 @@ ProjectSettings::ProjectSettings(EditorData *p_data) { globals_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 ); globals_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 ); globals_editor->set_capitalize_paths(false); - globals_editor->get_tree()->connect("cell_selected",this,"_item_selected"); + globals_editor->get_scene_tree()->connect("cell_selected",this,"_item_selected"); globals_editor->connect("property_toggled",this,"_item_checked"); globals_editor->connect("property_edited",this,"_settings_prop_edited"); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 645d967a4b..3fd713c5b0 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -142,7 +142,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { } String orig_type = res_orig->get_type(); - print_line("orig type: "+orig_type); + Object *inst = ObjectTypeDB::instance( orig_type ); Ref<Resource> res = Ref<Resource>( inst->cast_to<Resource>() ); @@ -187,6 +187,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { ERR_FAIL_COND( inheritors_array.empty() ); + String intype=inheritors_array[p_which-TYPE_BASE_ID]; Object *obj = ObjectTypeDB::instance(intype); @@ -603,6 +604,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty if (hint_text!="") { + int idx=0; for(int i=0;i<hint_text.get_slice_count(",");i++) { @@ -620,19 +622,19 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty E=E->next(); } - int idx=0; for(Set<String>::Element *E=valid_inheritors.front();E;E=E->next()) { String t = E->get(); if (!ObjectTypeDB::can_instance(t)) continue; inheritors_array.push_back(t); + int id = TYPE_BASE_ID+idx; if (has_icon(t,"EditorIcons")) { - menu->add_icon_item(get_icon(t,"EditorIcons"),"New "+t,TYPE_BASE_ID+idx); + menu->add_icon_item(get_icon(t,"EditorIcons"),"New "+t,id); } else { - menu->add_item("New "+t,TYPE_BASE_ID+idx); + menu->add_item("New "+t,id); } idx++; @@ -649,6 +651,8 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty if (!RES(v).is_null()) { + + menu->add_icon_item(get_icon("EditResource","EditorIcons"),"Edit",OBJ_MENU_EDIT); menu->add_icon_item(get_icon("Del","EditorIcons"),"Clear",OBJ_MENU_CLEAR); menu->add_icon_item(get_icon("Duplicate","EditorIcons"),"Make Unique",OBJ_MENU_MAKE_UNIQUE); @@ -657,6 +661,13 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty menu->add_separator(); menu->add_icon_item(get_icon("Reload","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT); } + /*if (r.is_valid() && r->get_path().is_resource_file()) { + menu->set_item_tooltip(1,r->get_path()); + } else if (r.is_valid()) { + menu->set_item_tooltip(1,r->get_name()+" ("+r->get_type()+")"); + }*/ + } else { + } @@ -970,9 +981,11 @@ void CustomPropertyEditor::_action_pressed(int p_which) { if (p_which==0) { + ERR_FAIL_COND( inheritors_array.empty() ); String intype=inheritors_array[0]; + if (hint==PROPERTY_HINT_RESOURCE_TYPE) { @@ -1853,8 +1866,41 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p } else { p_item->set_text(1,"<"+res->get_type()+">"); }; + + + if (res.is_valid() && res->get_path().is_resource_file()) { + p_item->set_tooltip(1,res->get_path()); + } else if (res.is_valid()) { + p_item->set_tooltip(1,res->get_name()+" ("+res->get_type()+")"); + } + + + if (has_icon(res->get_type(),"EditorIcons")) { + + p_item->set_icon(0,get_icon(res->get_type(),"EditorIcons")); + } else { + + Dictionary d = p_item->get_metadata(0); + int hint=d.has("hint")?d["hint"].operator int():-1; + String hint_text=d.has("hint_text")?d["hint_text"]:""; + if (hint==PROPERTY_HINT_RESOURCE_TYPE) { + + if (has_icon(hint_text,"EditorIcons")) { + + p_item->set_icon(0,get_icon(hint_text,"EditorIcons")); + + } else { + p_item->set_icon(0,get_icon("Object","EditorIcons")); + + } + } + } + + + } + } break; default: {}; } @@ -1863,11 +1909,11 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p void PropertyEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { - get_scene()->connect("node_removed",this,"_node_removed"); + get_tree()->connect("node_removed",this,"_node_removed"); } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { edit(NULL); } @@ -1876,6 +1922,14 @@ void PropertyEditor::_notification(int p_what) { if (p_what==NOTIFICATION_FIXED_PROCESS) { + if (refresh_countdown>0) { + refresh_countdown-=get_fixed_process_delta_time(); + if (refresh_countdown<=0) { + TreeItem *root = tree->get_root(); + _refresh_item(root); + } + } + changing=true; if (update_tree_pending) { @@ -1982,7 +2036,71 @@ TreeItem *PropertyEditor::get_parent_node(String p_path,HashMap<String,TreeItem* } +void PropertyEditor::_refresh_item(TreeItem *p_item) { + + if (!p_item) + return; + + String name = p_item->get_metadata(1); + + if (name!=String()) { + + if (get_instanced_node()) { + + Dictionary d = get_instanced_node()->get_instance_state(); + if (d.has(name)) { + Variant v = obj->get(name); + Variant vorig = d[name]; + + int found=-1; + for(int i=0;i<p_item->get_button_count(1);i++) { + + if (p_item->get_button_id(1,i)==3) { + found=i; + break; + } + } + + bool changed = ! (v==vorig); + + if ((found!=-1)!=changed) { + + if (changed) { + + p_item->add_button(1,get_icon("Reload","EditorIcons"),3); + } else { + + p_item->erase_button(1,found); + } + + } + + } + + } + + Dictionary d=p_item->get_metadata(0); + set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]); + } + + TreeItem *c=p_item->get_children(); + + while (c) { + + _refresh_item(c); + + c=c->get_next(); + } + +} + +void PropertyEditor::refresh() { + + if (refresh_countdown>0) + return; + refresh_countdown=EditorSettings::get_singleton()->get("property_editor/auto_refresh_interval"); +} void PropertyEditor::update_tree() { @@ -2140,7 +2258,7 @@ void PropertyEditor::update_tree() { } if (capitalize_paths) - item->set_text( 0, name.capitalize() ); + item->set_text( 0, name.camelcase_to_underscore().capitalize() ); else item->set_text( 0, name ); @@ -2261,7 +2379,7 @@ void PropertyEditor::update_tree() { } else { if (p.type == Variant::REAL) { - item->set_range_config(1, -65536, 65535, 0.01); + item->set_range_config(1, -65536, 65535, 0.001); } else { item->set_range_config(1, -65536, 65535, 1); @@ -2453,7 +2571,10 @@ void PropertyEditor::update_tree() { item->set_editable( 1, !read_only ); item->add_button(1,get_icon("EditResource","EditorIcons")); String type; + if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) + type=p.hint_string; bool notnil=false; + if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) { item->set_text(1,"<null>"); @@ -2477,12 +2598,25 @@ void PropertyEditor::update_tree() { }; notnil=true; + if (has_icon(res->get_type(),"EditorIcons")) { + type=res->get_type(); + } + + if (res.is_valid() && res->get_path().is_resource_file()) { + item->set_tooltip(1,res->get_path()); + } else if (res.is_valid()) { + item->set_tooltip(1,res->get_name()+" ("+res->get_type()+")"); + } + } - if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) { + + if (type!=String()) { + if (type.find(",")!=-1) + type=type.get_slice(",",0); //printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data()); - if (has_icon(p.hint_string,"EditorIcons")) - item->set_icon( 0, get_icon(p.hint_string,"EditorIcons") ); + if (has_icon(type,"EditorIcons")) + item->set_icon( 0, get_icon(type,"EditorIcons") ); else item->set_icon( 0, get_icon("Object","EditorIcons") ); } @@ -2919,7 +3053,7 @@ void PropertyEditor::_bind_methods() { ADD_SIGNAL( MethodInfo("property_edited",PropertyInfo( Variant::STRING, "property"))); } -Tree *PropertyEditor::get_tree() { +Tree *PropertyEditor::get_scene_tree() { return tree; } @@ -3021,6 +3155,7 @@ PropertyEditor::PropertyEditor() { keying=false; read_only=false; show_categories=false; + refresh_countdown=0; } diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index f13deab1ae..c05e13b90e 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -156,6 +156,7 @@ class PropertyEditor : public Control { bool keying; bool read_only; bool show_categories; + float refresh_countdown; HashMap<String,String> pending; String selected_property; @@ -185,6 +186,7 @@ class PropertyEditor : public Control { void _draw_flags(Object *ti,const Rect2& p_rect); Node *get_instanced_node(); + void _refresh_item(TreeItem *p_item); UndoRedo *undo_redo; protected: @@ -197,12 +199,14 @@ public: String get_selected_path() const; - Tree *get_tree(); + Tree *get_scene_tree(); Label* get_top_label(); void hide_top_label(); void update_tree(); void update_property(const String& p_prop); + void refresh(); + void edit(Object* p_object); void set_keying(bool p_active); diff --git a/tools/editor/pvrtc_compress.cpp b/tools/editor/pvrtc_compress.cpp index 9511d6a26d..777a05f272 100644 --- a/tools/editor/pvrtc_compress.cpp +++ b/tools/editor/pvrtc_compress.cpp @@ -32,11 +32,34 @@ #include "io/resource_saver.h" #include "io/resource_loader.h" #include "os/os.h" - +#include "os/file_access.h" +static void (*_base_image_compress_pvrtc2_func)(Image *)=NULL; +static void (*_base_image_compress_pvrtc4_func)(Image *)=NULL; static void _compress_image(Image::CompressMode p_mode,Image *p_image) { String ttpath = EditorSettings::get_singleton()->get("PVRTC/texture_tool"); + + if (ttpath.strip_edges()=="" || !FileAccess::exists(ttpath)) { + switch(p_mode) { + + case Image::COMPRESS_PVRTC2: + if (_base_image_compress_pvrtc2_func) + _base_image_compress_pvrtc2_func(p_image); + else if (_base_image_compress_pvrtc4_func) + _base_image_compress_pvrtc4_func(p_image); + + break; + case Image::COMPRESS_PVRTC4: + if (_base_image_compress_pvrtc4_func) + _base_image_compress_pvrtc4_func(p_image); + + break; + default: ERR_FAIL(); + + } + return; + } String spath = EditorSettings::get_singleton()->get_settings_path(); @@ -100,6 +123,9 @@ static void _compress_etc(Image *p_image) { void _pvrtc_register_compressors() { + _base_image_compress_pvrtc2_func=Image::_image_compress_pvrtc2_func; + _base_image_compress_pvrtc4_func=Image::_image_compress_pvrtc4_func; + Image::_image_compress_pvrtc2_func=_compress_pvrtc2; Image::_image_compress_pvrtc4_func=_compress_pvrtc4; //Image::_image_compress_etc_func=_compress_etc; //use the built in one for ETC diff --git a/tools/editor/quick_open.cpp b/tools/editor/quick_open.cpp index bae7528150..129c637ab0 100644 --- a/tools/editor/quick_open.cpp +++ b/tools/editor/quick_open.cpp @@ -111,7 +111,7 @@ void EditorQuickOpen::_confirmed() { void EditorQuickOpen::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed",this,"_confirmed"); } diff --git a/tools/editor/reparent_dialog.cpp b/tools/editor/reparent_dialog.cpp index 2c85eb3a2a..5a5566c756 100644 --- a/tools/editor/reparent_dialog.cpp +++ b/tools/editor/reparent_dialog.cpp @@ -36,7 +36,7 @@ void ReparentDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed", this,"_reparent"); } diff --git a/tools/editor/resources_dock.cpp b/tools/editor/resources_dock.cpp index a05fe425b3..4614c4945d 100644 --- a/tools/editor/resources_dock.cpp +++ b/tools/editor/resources_dock.cpp @@ -69,36 +69,8 @@ void ResourcesDock::_tool_selected(int p_tool) { TreeItem *ti = resources->get_selected(); if (!ti) break; - Ref<Resource> current_res = ti->get_metadata(0); - - RES res(current_res); - - List<String> extensions; - ResourceSaver::get_recognized_extensions(res,&extensions); - file->set_mode(FileDialog::MODE_SAVE_FILE); - //not for now? - - if (current_res->get_path()!="" && current_res->get_path().find("::")==-1) { - - file->set_current_path(current_res->get_path()); - } else { - String existing; - if (extensions.size()) { - existing="new_"+res->get_type().to_lower()+"."+extensions.front()->get().to_lower(); - } - - file->set_current_file(existing); - } - - file->clear_filters(); - for(int i=0;i<extensions.size();i++) { - - file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper()); - } - - //file->set_current_path(current_path); - file->popup_centered_ratio(); + save_resource_as(ti->get_metadata(0)); } break; @@ -134,7 +106,7 @@ void ResourcesDock::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { button_new->set_icon(get_icon("New","EditorIcons")); button_open->set_icon(get_icon("Folder","EditorIcons")); @@ -174,33 +146,34 @@ void ResourcesDock::save_resource(const String& p_path,const Ref<Resource>& p_re void ResourcesDock::save_resource_as(const Ref<Resource>& p_resource) { + current_action=TOOL_SAVE_AS; - add_resource(p_resource); - TreeItem *root=resources->get_root(); - ERR_FAIL_COND(!root); + RES res(p_resource); - TreeItem *existing=root->get_children(); + List<String> extensions; + ResourceSaver::get_recognized_extensions(res,&extensions); + file->set_mode(FileDialog::MODE_SAVE_FILE); - while(existing) { + if (p_resource->get_path()!="" && p_resource->get_path().find("::")==-1) { - Ref<Resource> r = existing->get_metadata(0); - if (r==p_resource) { - //existing->move_to_top(); - existing->select(0); - resources->ensure_cursor_is_visible(); - return; // existing - } - existing=existing->get_next(); - } - - ERR_FAIL_COND(!existing); + file->set_current_path(p_resource->get_path()); + } else { - existing->select(0); + String existing; + if (extensions.size()) { + existing="new_"+res->get_type().to_lower()+"."+extensions.front()->get().to_lower(); + } - _tool_selected(TOOL_SAVE_AS); + file->set_current_file(existing); + } + file->clear_filters(); + for(int i=0;i<extensions.size();i++) { + file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper()); + } + file->popup_centered_ratio(); } diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index f693036bc2..84b34cf130 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -79,10 +79,22 @@ Node* SceneTreeDock::instance(const String& p_file) { //accept->get_cancel()->hide(); accept->get_ok()->set_text("Ugh"); accept->set_text(String("Error loading scene from ")+p_file); - accept->popup_centered(Size2(300,70));; + accept->popup_centered(Size2(300,70)); return NULL; } + // If the scene hasn't been saved yet a cyclical dependency cannot exist. + if (edited_scene->get_filename()!="") { + + if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) { + + accept->get_ok()->set_text("Ok"); + accept->set_text(String("Cannot instance the scene '")+p_file+String("' because the current scene exists within one of its' nodes.")); + accept->popup_centered(Size2(300,90)); + return NULL; + } + } + instanced_scene->generate_instance_state(); instanced_scene->set_filename( Globals::get_singleton()->localize_path(p_file) ); @@ -100,6 +112,35 @@ Node* SceneTreeDock::instance(const String& p_file) { } +bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) { + int childCount = p_desired_node->get_child_count(); + + if (p_desired_node->get_filename()==p_target_scene_path) { + return true; + } + + for (int i=0;i<childCount;i++) { + Node* child=p_desired_node->get_child(i); + + if(_cyclical_dependency_exists(p_target_scene_path,child)) { + return true; + } + } + + return false; +} + + +static String _get_name_num_separator() { + switch(EditorSettings::get_singleton()->get("scenetree_editor/duplicate_node_name_num_separator").operator int()) { + case 0: return ""; + case 1: return " "; + case 2: return "_"; + case 3: return "-"; + } + return " "; +} + void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option=p_tool; @@ -212,17 +253,50 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!_validate_no_foreign()) break; - Node * node=scene_tree->get_selected(); - ERR_FAIL_COND(!node->get_parent()); - int current_pos = node->get_index(); - int next_pos = current_pos + ((p_tool==TOOL_MOVE_DOWN)?1:-1); + bool MOVING_DOWN = (p_tool == TOOL_MOVE_DOWN); + bool MOVING_UP = !MOVING_DOWN; + + Node *common_parent = scene_tree->get_selected()->get_parent(); + List<Node*> selection = editor_selection->get_selected_node_list(); + selection.sort_custom<Node::Comparator>(); // sort by index + if (MOVING_DOWN) + selection.invert(); + + int lowest_id = common_parent->get_child_count() - 1; + int highest_id = 0; + for (List<Node*>::Element *E = selection.front(); E; E = E->next()) { + int index = E->get()->get_index(); + + if (index > highest_id) highest_id = index; + if (index < lowest_id) lowest_id = index; + + if (E->get()->get_parent() != common_parent) + common_parent = NULL; + } + + if (!common_parent || (MOVING_DOWN && highest_id >= common_parent->get_child_count() - MOVING_DOWN) || (MOVING_UP && lowest_id == 0)) + break; // one or more nodes can not be moved + + if (selection.size() == 1) editor_data->get_undo_redo().create_action("Move Node In Parent"); + if (selection.size() > 1) editor_data->get_undo_redo().create_action("Move Nodes In Parent"); + + for (int i = 0; i < selection.size(); i++) { + Node *top_node = selection[i]; + Node *bottom_node = selection[selection.size() - 1 - i]; + + ERR_FAIL_COND(!top_node->get_parent()); + ERR_FAIL_COND(!bottom_node->get_parent()); - if (next_pos< 0 || next_pos>=node->get_parent()->get_child_count()) - break; // invalid position + int top_node_pos = top_node->get_index(); + int bottom_node_pos = bottom_node->get_index(); + + int top_node_pos_next = top_node_pos + (MOVING_DOWN ? 1 : -1); + int bottom_node_pos_next = bottom_node_pos + (MOVING_DOWN ? 1 : -1); + + editor_data->get_undo_redo().add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next); + editor_data->get_undo_redo().add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos); + } - editor_data->get_undo_redo().create_action("Move Node In Parent"); - editor_data->get_undo_redo().add_do_method(node->get_parent(),"move_child",node,next_pos); - editor_data->get_undo_redo().add_undo_method(node->get_parent(),"move_child",node,current_pos); editor_data->get_undo_redo().commit_action(); } break; @@ -285,17 +359,21 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } int num=nums.to_int(); - if (num<2) - num=2; + if (num<1) + num=1; else num++; - name=name.substr(0,name.length()-nums.length()).strip_edges(); - String attempt=name+" "+itos(num); + String nnsep = _get_name_num_separator(); + name = name.substr(0,name.length()-nums.length()).strip_edges(); + if ( name.substr(name.length()-nnsep.length(),nnsep.length()) == nnsep) { + name = name.substr(0,name.length()-nnsep.length()); + } + String attempt = (name + nnsep + itos(num)).strip_edges(); while(parent->has_node(attempt)) { num++; - attempt=name+" "+itos(num); + attempt = (name + nnsep + itos(num)).strip_edges(); } dup->set_name(attempt); @@ -393,7 +471,7 @@ void SceneTreeDock::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { static const char* button_names[TOOL_BUTTON_MAX]={ "New", @@ -913,7 +991,7 @@ void SceneTreeDock::_delete_confirm() { //delete from animation for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) { Node *n = E->get(); - if (!n->is_inside_scene() || !n->get_parent()) + if (!n->is_inside_tree() || !n->get_parent()) continue; fill_path_renames(n,NULL,&path_renames); @@ -924,7 +1002,7 @@ void SceneTreeDock::_delete_confirm() { //delete for read for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) { Node *n = E->get(); - if (!n->is_inside_scene() || !n->get_parent()) + if (!n->is_inside_tree() || !n->get_parent()) continue; List<Node*> owned; @@ -981,14 +1059,15 @@ void SceneTreeDock::_create() { if (edited_scene) { - + // If root exists in edited scene parent = scene_tree->get_selected(); - ERR_FAIL_COND(!parent); - } else { + if( !parent ) + parent = edited_scene; + } else { + // If no root exist in edited scene parent = scene_root; ERR_FAIL_COND(!parent); - } Object *c = create_dialog->instance_selected(); @@ -1176,7 +1255,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec tb = memnew( ToolButton ); tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_INSTANCE, false)); - tb->set_tooltip("Instance a Node from scene file."); + tb->set_tooltip("Instance a scene file as a Node."); hbc_top->add_child(tb); tool_buttons[TOOL_INSTANCE]=tb; diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index ac5391f3b9..92ebfc5bee 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -102,6 +102,7 @@ class SceneTreeDock : public VBoxContainer { void _load_request(const String& p_path); void _script_open_request(const Ref<Script>& p_script); + bool _cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node); void _node_selected(); void _node_renamed(); diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp index 9b4ef6cef1..e9ec0199d0 100644 --- a/tools/editor/scene_tree_editor.cpp +++ b/tools/editor/scene_tree_editor.cpp @@ -36,11 +36,11 @@ Node *SceneTreeEditor::get_scene_node() { - ERR_FAIL_COND_V(!is_inside_scene(),NULL); - if (get_scene()->get_root()->get_child_count() && get_scene()->get_root()->get_child(0)->cast_to<EditorNode>()) - return get_scene()->get_root()->get_child(0)->cast_to<EditorNode>()->get_edited_scene(); + ERR_FAIL_COND_V(!is_inside_tree(),NULL); + if (get_tree()->get_root()->get_child_count() && get_tree()->get_root()->get_child(0)->cast_to<EditorNode>()) + return get_tree()->get_root()->get_child(0)->cast_to<EditorNode>()->get_edited_scene(); else - return get_scene()->get_root(); + return get_tree()->get_root(); return NULL; } @@ -367,7 +367,7 @@ void SceneTreeEditor::_node_removed(Node *p_node) { void SceneTreeEditor::_update_tree() { - if (!is_inside_scene()) { + if (!is_inside_tree()) { tree_dirty=false; return; } @@ -403,7 +403,7 @@ void SceneTreeEditor::_test_update_tree() { pending_test_update=false; - if (!is_inside_scene()) + if (!is_inside_tree()) return; if(tree_dirty) @@ -483,10 +483,10 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object,int p_cell,bool p_se void SceneTreeEditor::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { - get_scene()->connect("tree_changed",this,"_tree_changed"); - get_scene()->connect("node_removed",this,"_node_removed"); + get_tree()->connect("tree_changed",this,"_tree_changed"); + get_tree()->connect("node_removed",this,"_node_removed"); instance_menu->set_item_icon(2,get_icon("Load","EditorIcons")); tree->connect("item_collapsed",this,"_cell_collapsed"); @@ -494,10 +494,10 @@ void SceneTreeEditor::_notification(int p_what) { // get_scene()->connect("node_removed",this,"_node_removed",Vector<Variant>(),CONNECT_DEFERRED); _update_tree(); } - if (p_what==NOTIFICATION_EXIT_SCENE) { + if (p_what==NOTIFICATION_EXIT_TREE) { - get_scene()->disconnect("tree_changed",this,"_tree_changed"); - get_scene()->disconnect("node_removed",this,"_node_removed"); + get_tree()->disconnect("tree_changed",this,"_tree_changed"); + get_tree()->disconnect("node_removed",this,"_node_removed"); _update_tree(); } @@ -806,7 +806,7 @@ SceneTreeEditor::~SceneTreeEditor() { void SceneTreeDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed", this,"_select"); } diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp index 3f7c82d988..516cb5930d 100644 --- a/tools/editor/scenes_dock.cpp +++ b/tools/editor/scenes_dock.cpp @@ -115,7 +115,7 @@ void ScenesDock::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_update_tree"); @@ -145,7 +145,7 @@ void ScenesDock::_notification(int p_what) { _update_tree(); //maybe it finished already } break; - case NOTIFICATION_EXIT_SCENE: { + case NOTIFICATION_EXIT_TREE: { } break; case NOTIFICATION_PROCESS: { @@ -383,7 +383,7 @@ void ScenesDockFilter::_file_filter_selected(int p_idx) { void ScenesDockFilter::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { clear_search_button->set_icon(get_icon("CloseHover","EditorIcons")); } break; } diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp index 00066e67e9..5043c5cdcd 100644 --- a/tools/editor/script_editor_debugger.cpp +++ b/tools/editor/script_editor_debugger.cpp @@ -431,7 +431,7 @@ void ScriptEditorDebugger::_notification(int p_what) { switch(p_what) { - case NOTIFICATION_ENTER_SCENE: { + case NOTIFICATION_ENTER_TREE: { step->set_icon( get_icon("DebugStep","EditorIcons")); next->set_icon( get_icon("DebugNext","EditorIcons")); @@ -478,8 +478,6 @@ void ScriptEditorDebugger::_notification(int p_what) { if (!connection->is_connected()) { stop(); editor->notify_child_process_exited(); //somehow, exited - msgdialog->set_text("Process being debugged exited."); - msgdialog->popup_centered(Size2(250,100)); break; }; @@ -771,7 +769,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){ inspector = memnew( PropertyEditor ); inspector->set_h_size_flags(SIZE_EXPAND_FILL); inspector->hide_top_label(); - inspector->get_tree()->set_column_title(0,"Variable"); + inspector->get_scene_tree()->set_column_title(0,"Variable"); inspector->set_capitalize_paths(false); inspector->set_read_only(true); sc->add_child(inspector); diff --git a/tools/editor/settings_config_dialog.cpp b/tools/editor/settings_config_dialog.cpp index c82b075bc4..2310df4ffb 100644 --- a/tools/editor/settings_config_dialog.cpp +++ b/tools/editor/settings_config_dialog.cpp @@ -246,7 +246,7 @@ void EditorSettingsDialog::_update_plugins() { void EditorSettingsDialog::_notification(int p_what) { - if (p_what==NOTIFICATION_ENTER_SCENE) { + if (p_what==NOTIFICATION_ENTER_TREE) { rescan_plugins->set_icon(get_icon("Reload","EditorIcons")); _update_plugins(); diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp index 04d5888861..d48a4ce813 100644 --- a/tools/editor/spatial_editor_gizmos.cpp +++ b/tools/editor/spatial_editor_gizmos.cpp @@ -1779,7 +1779,7 @@ void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Po Ref<CapsuleShape> cs = s;
Vector3 ra,rb;
Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
+ float d = axis.dot(ra);
if (p_idx==1)
d-=cs->get_radius();
if (d<0.001)
diff --git a/tools/export/blender25/godot_export_manager.py b/tools/export/blender25/godot_export_manager.py new file mode 100644 index 0000000000..31db2c9e94 --- /dev/null +++ b/tools/export/blender25/godot_export_manager.py @@ -0,0 +1,474 @@ +# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Script copyright (c) Andreas Esau
+
+bl_info = {
+ "name": "Godot Export Manager",
+ "author": "Andreas Esau",
+ "version": (1, 0),
+ "blender": (2, 7, 0),
+ "location": "Scene Properties > Godot Export Manager",
+ "description": "Godot Export Manager uses the Better Collada Exporter to manage Export Groups and automatically export the objects groups to Collada Files.",
+ "warning": "",
+ "wiki_url": ("http://www.godotengine.org"),
+ "tracker_url": "",
+ "category": "Import-Export"}
+
+import bpy
+from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatProperty, FloatVectorProperty, IntProperty, CollectionProperty, PointerProperty
+import os
+from bpy.app.handlers import persistent
+from mathutils import Vector, Matrix
+
+class godot_export_manager(bpy.types.Panel):
+ bl_label = "Godot Export Manager"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "scene"
+
+ bpy.types.Scene.godot_export_on_save = BoolProperty(default=False)
+
+ ### draw function for all ui elements
+ def draw(self, context):
+ layout = self.layout
+ split = self.layout.split()
+ scene = bpy.data.scenes[0]
+ ob = context.object
+ scene = context.scene
+
+ row = layout.row()
+ col = row.column()
+ col.prop(scene,"godot_export_on_save",text="Export Groups on save")
+
+ row = layout.row()
+ col = row.column(align=True)
+ op = col.operator("scene.godot_add_objects_to_group",text="Add selected objects to Group",icon="COPYDOWN")
+
+ op = col.operator("scene.godot_delete_objects_from_group",text="Delete selected objects from Group",icon="PASTEDOWN")
+
+
+
+ row = layout.row()
+ col = row.column()
+ col.label(text="Export Groups:")
+
+
+ row = layout.row()
+ col = row.column()
+
+ col.template_list("UI_List_Godot","dummy",scene, "godot_export_groups", scene, "godot_export_groups_index",rows=1,maxrows=10,type='DEFAULT')
+
+ col = row.column(align=True)
+ col.operator("scene.godot_add_export_group",text="",icon="ZOOMIN")
+ col.operator("scene.godot_delete_export_group",text="",icon="ZOOMOUT")
+ col.operator("scene.godot_export_all_groups",text="",icon="EXPORT")
+
+ if len(scene.godot_export_groups) > 0:
+ row = layout.row()
+ col = row.column()
+ group = scene.godot_export_groups[scene.godot_export_groups_index]
+ col.prop(group,"name",text="Group Name")
+ col.prop(group,"export_name",text="Export Name")
+ col.prop(group,"export_path",text="Export Filepath")
+
+ row = layout.row()
+ col = row.column()
+ row = layout.row()
+ col = row.column()
+ col.label(text="Export Settings:")
+
+ col = col.row(align=True)
+ col.prop(group,"apply_loc",toggle=True,icon="MAN_TRANS")
+ col.prop(group,"apply_rot",toggle=True,icon="MAN_ROT")
+ col.prop(group,"apply_scale",toggle=True,icon="MAN_SCALE")
+
+ row = layout.row()
+ col = row.column()
+
+ col.prop(group,"use_include_particle_duplicates")
+ col.prop(group,"use_mesh_modifiers")
+ col.prop(group,"use_tangent_arrays")
+ col.prop(group,"use_triangles")
+ col.prop(group,"use_copy_images")
+ col.prop(group,"use_active_layers")
+ col.prop(group,"use_exclude_ctrl_bones")
+ col.prop(group,"use_anim")
+ col.prop(group,"use_anim_action_all")
+ col.prop(group,"use_anim_skip_noexp")
+ col.prop(group,"use_anim_optimize")
+ col.prop(group,"anim_optimize_precision")
+ col.prop(group,"use_metadata")
+
+### Custom template_list look
+class UI_List_Godot(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ ob = data
+ slot = item
+ col = layout.row(align=True)
+
+ col.label(text=item.name,icon="GROUP")
+ col.prop(item,"active",text="")
+
+ op = col.operator("scene.godot_select_group_objects",text="",emboss=False,icon="RESTRICT_SELECT_OFF")
+ op.idx = index
+ op = col.operator("scene.godot_export_group",text="",emboss=False,icon="EXPORT")
+ op.idx = index
+
+class add_objects_to_group(bpy.types.Operator):
+ bl_idname = "scene.godot_add_objects_to_group"
+ bl_label = "Add Objects to Group"
+ bl_description = "Adds the selected Objects to the active group below."
+
+ undo = BoolProperty(default=True)
+
+ def execute(self,context):
+ scene = context.scene
+
+ objects_str = ""
+ if len(scene.godot_export_groups) > 0:
+ for i,object in enumerate(context.selected_objects):
+ if object.name not in scene.godot_export_groups[scene.godot_export_groups_index].nodes:
+ node = scene.godot_export_groups[scene.godot_export_groups_index].nodes.add()
+ node.name = object.name
+ if i == 0:
+ objects_str += object.name
+ else:
+ objects_str += ", "+object.name
+
+
+ self.report({'INFO'}, objects_str + " added to group." )
+ if self.undo:
+ bpy.ops.ed.undo_push(message="Objects added to group")
+ else:
+ self.report({'WARNING'}, "Create a group first." )
+ return{'FINISHED'}
+
+class del_objects_from_group(bpy.types.Operator):
+ bl_idname = "scene.godot_delete_objects_from_group"
+ bl_label = "Delete Objects from Group"
+ bl_description = "Delets the selected Objects from the active group below."
+
+ def execute(self,context):
+ scene = context.scene
+
+ if len(scene.godot_export_groups) > 0:
+
+ selected_objects = []
+ for object in context.selected_objects:
+ selected_objects.append(object.name)
+
+ objects_str = ""
+ j = 0
+ for i,node in enumerate(scene.godot_export_groups[scene.godot_export_groups_index].nodes):
+ if node.name in selected_objects:
+ scene.godot_export_groups[scene.godot_export_groups_index].nodes.remove(i)
+
+
+ if j == 0:
+ objects_str += object.name
+ else:
+ objects_str += ", "+object.name
+ j+=1
+
+
+ self.report({'INFO'}, objects_str + " deleted from group." )
+ bpy.ops.ed.undo_push(message="Objects deleted from group")
+ else:
+ self.report({'WARNING'}, "There is no group to delete from." )
+ return{'FINISHED'}
+
+class select_group_objects(bpy.types.Operator):
+ bl_idname = "scene.godot_select_group_objects"
+ bl_label = "Select Group Objects"
+ bl_description = "Will select all group Objects in the scene."
+
+ idx = IntProperty()
+
+ def execute(self,context):
+ scene = context.scene
+ for object in context.scene.objects:
+ object.select = False
+ for node in scene.godot_export_groups[self.idx].nodes:
+ if node.name in bpy.data.objects:
+ bpy.data.objects[node.name].select = True
+ context.scene.objects.active = bpy.data.objects[node.name]
+ return{'FINISHED'}
+
+class export_groups_autosave(bpy.types.Operator):
+ bl_idname = "scene.godot_export_groups_autosave"
+ bl_label = "Export All Groups"
+ bl_description = "Exports all groups to Collada."
+
+ def execute(self,context):
+ scene = context.scene
+ if scene.godot_export_on_save:
+ for i in range(len(scene.godot_export_groups)):
+ if scene.godot_export_groups[i].active:
+ bpy.ops.scene.godot_export_group(idx=i)
+ self.report({'INFO'}, "All Groups exported." )
+ bpy.ops.ed.undo_push(message="Export all Groups")
+ return{'FINISHED'}
+
+class export_all_groups(bpy.types.Operator):
+ bl_idname = "scene.godot_export_all_groups"
+ bl_label = "Export All Groups"
+ bl_description = "Exports all groups to Collada."
+
+ def execute(self,context):
+ scene = context.scene
+
+ for i in range(0,len(scene.godot_export_groups)):
+ bpy.ops.scene.godot_export_group(idx=i,export_all=True)
+
+ self.report({'INFO'}, "All Groups exported." )
+ return{'FINISHED'}
+
+
+class export_group(bpy.types.Operator):
+ bl_idname = "scene.godot_export_group"
+ bl_label = "Export Group"
+ bl_description = "Exports the active group to destination folder as Collada file."
+
+ idx = IntProperty(default=0)
+ export_all = BoolProperty(default=False)
+
+
+ def copy_object_recursive(self,ob,parent,single_user = True):
+ new_ob = bpy.data.objects[ob.name].copy()
+ if single_user or ob.type=="ARMATURE":
+ new_mesh_data = new_ob.data.copy()
+ new_ob.data = new_mesh_data
+ bpy.context.scene.objects.link(new_ob)
+
+ if ob != parent:
+ new_ob.parent = parent
+ else:
+ new_ob.parent = None
+
+ for child in ob.children:
+ self.copy_object_recursive(child,new_ob,single_user)
+ new_ob.select = True
+ return new_ob
+
+ def delete_object(self,ob):
+ if ob != None:
+ for child in ob.children:
+ self.delete_object(child)
+ bpy.context.scene.objects.unlink(ob)
+ bpy.data.objects.remove(ob)
+
+ def convert_group_to_node(self,group):
+ if group.dupli_group != None:
+ for object in group.dupli_group.objects:
+ if object.parent == None:
+ object = self.copy_object_recursive(object,object,True)
+ matrix = Matrix(object.matrix_local)
+ object.matrix_local = Matrix()
+ object.matrix_local *= group.matrix_local
+ object.matrix_local *= matrix
+
+ self.delete_object(group)
+
+ def execute(self,context):
+
+ scene = context.scene
+ group = context.scene.godot_export_groups
+
+ if not group[self.idx].active and self.export_all:
+ return{'FINISHED'}
+
+ for i,object in enumerate(group[self.idx].nodes):
+ if object.name in bpy.data.objects:
+ pass
+ else:
+ group[self.idx].nodes.remove(i)
+ bpy.ops.ed.undo_push(message="Clear not existent Group Nodes.")
+
+ path = group[self.idx].export_path
+ if (path.find("//")==0 or path.find("\\\\")==0):
+ #if relative, convert to absolute
+ path = bpy.path.abspath(path)
+ path = path.replace("\\","/")
+
+ ### if path exists and group export name is set the group will be exported
+ if os.path.exists(path) and group[self.idx].export_name != "":
+
+ context.scene.layers = [True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]
+
+
+ if group[self.idx].export_name.endswith(".dae"):
+ path = os.path.join(path,group[self.idx].export_name)
+ else:
+ path = os.path.join(path,group[self.idx].export_name+".dae")
+
+ hide_select = []
+ for object in context.scene.objects:
+ hide_select.append(object.hide_select)
+ object.hide_select = False
+ object.select = False
+ context.scene.objects.active = None
+
+ ### make particle duplicates, parent and select them
+ nodes_to_be_added = []
+ if group[self.idx].use_include_particle_duplicates:
+ for i,object in enumerate(group[self.idx].nodes):
+ if bpy.data.objects[object.name].type != "EMPTY":
+ context.scene.objects.active = bpy.data.objects[object.name]
+ bpy.data.objects[object.name].select = True
+ bpy.ops.object.duplicates_make_real()
+ for object in context.selected_objects:
+ nodes_to_be_added.append(object)
+ bpy.ops.object.parent_set(type="OBJECT", keep_transform=False)
+
+ for object in context.selected_objects:
+ object.select = False
+ bpy.data.objects[object.name].select = False
+ context.scene.objects.active = None
+ for object in nodes_to_be_added:
+ object.select = True
+
+ ### select all other nodes from the group
+ for i,object in enumerate(group[self.idx].nodes):
+ if bpy.data.objects[object.name].type == "EMPTY":
+ self.convert_group_to_node(bpy.data.objects[object.name])
+ else:
+ bpy.data.objects[object.name].select = True
+
+ bpy.ops.object.transform_apply(location=group[self.idx].apply_loc, rotation=group[self.idx].apply_rot, scale=group[self.idx].apply_scale)
+ bpy.ops.export_scene.dae(check_existing=True, filepath=path, filter_glob="*.dae", object_types=group[self.idx].object_types, use_export_selected=group[self.idx].use_export_selected, use_mesh_modifiers=group[self.idx].use_mesh_modifiers, use_tangent_arrays=group[self.idx].use_tangent_arrays, use_triangles=group[self.idx].use_triangles, use_copy_images=group[self.idx].use_copy_images, use_active_layers=group[self.idx].use_active_layers, use_exclude_ctrl_bones=group[self.idx].use_exclude_ctrl_bones, use_anim=group[self.idx].use_anim, use_anim_action_all=group[self.idx].use_anim_action_all, use_anim_skip_noexp=group[self.idx].use_anim_skip_noexp, use_anim_optimize=group[self.idx].use_anim_optimize, anim_optimize_precision=group[self.idx].anim_optimize_precision, use_metadata=group[self.idx].use_metadata)
+
+ self.report({'INFO'}, '"'+group[self.idx].name+'"' + " Group exported." )
+ msg = "Export Group "+group[self.idx].name
+
+ bpy.ops.ed.undo_push(message="")
+ bpy.ops.ed.undo()
+ bpy.ops.ed.undo_push(message=msg)
+
+ else:
+ self.report({'INFO'}, "Define Export Name and Export Path." )
+ return{'FINISHED'}
+
+class add_export_group(bpy.types.Operator):
+ bl_idname = "scene.godot_add_export_group"
+ bl_label = "Adds a new export Group"
+ bl_description = "Creates a new Export Group with the selected Objects assigned to it."
+
+ def execute(self,context):
+ scene = context.scene
+
+ item = scene.godot_export_groups.add()
+ item.name = "New Group"
+ for object in context.selected_objects:
+ node = item.nodes.add()
+ node.name = object.name
+ scene.godot_export_groups_index = len(scene.godot_export_groups)-1
+ bpy.ops.ed.undo_push(message="Create New Export Group")
+ return{'FINISHED'}
+
+class del_export_group(bpy.types.Operator):
+ bl_idname = "scene.godot_delete_export_group"
+ bl_label = "Delets the selected export Group"
+ bl_description = "Delets the active Export Group."
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_confirm(self,event)
+
+ def execute(self,context):
+ scene = context.scene
+
+ scene.godot_export_groups.remove(scene.godot_export_groups_index)
+ if scene.godot_export_groups_index > 0:
+ scene.godot_export_groups_index -= 1
+ bpy.ops.ed.undo_push(message="Delete Export Group")
+ return{'FINISHED'}
+
+class godot_node_list(bpy.types.PropertyGroup):
+ name = StringProperty()
+
+class godot_export_groups(bpy.types.PropertyGroup):
+ name = StringProperty(name="Group Name")
+ export_name = StringProperty(name="scene_name")
+ nodes = CollectionProperty(type=godot_node_list)
+ export_path = StringProperty(subtype="DIR_PATH")
+ active = BoolProperty(default=True,description="Export Group")
+
+ object_types = EnumProperty(name="Object Types",options={'ENUM_FLAG'},items=(('EMPTY', "Empty", ""),('CAMERA', "Camera", ""),('LAMP', "Lamp", ""),('ARMATURE', "Armature", ""),('MESH', "Mesh", ""),('CURVE', "Curve", ""),),default={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH','CURVE'})
+
+ apply_scale = BoolProperty(name="Apply Scale",description="Apply Scale before export.",default=False)
+ apply_rot = BoolProperty(name="Apply Rotation",description="Apply Rotation before export.",default=False)
+ apply_loc = BoolProperty(name="Apply Location",description="Apply Location before export.",default=False)
+
+ use_export_selected = BoolProperty(name="Selected Objects",description="Export only selected objects (and visible in active layers if that applies).",default=True)
+ use_mesh_modifiers = BoolProperty(name="Apply Modifiers",description="Apply modifiers to mesh objects (on a copy!).",default=True)
+ use_tangent_arrays = BoolProperty(name="Tangent Arrays",description="Export Tangent and Binormal arrays (for normalmapping).",default=False)
+ use_triangles = BoolProperty(name="Triangulate",description="Export Triangles instead of Polygons.",default=False)
+
+ use_copy_images = BoolProperty(name="Copy Images",description="Copy Images (create images/ subfolder)",default=False)
+ use_active_layers = BoolProperty(name="Active Layers",description="Export only objects on the active layers.",default=True)
+ use_exclude_ctrl_bones = BoolProperty(name="Exclude Control Bones",description="Exclude skeleton bones with names that begin with 'ctrl'.",default=True)
+ use_anim = BoolProperty(name="Export Animation",description="Export keyframe animation",default=False)
+ use_anim_action_all = BoolProperty(name="All Actions",description=("Export all actions for the first armature found in separate DAE files"),default=False)
+ use_anim_skip_noexp = BoolProperty(name="Skip (-noexp) Actions",description="Skip exporting of actions whose name end in (-noexp). Useful to skip control animations.",default=True)
+ use_anim_optimize = BoolProperty(name="Optimize Keyframes",description="Remove double keyframes",default=True)
+
+ anim_optimize_precision = FloatProperty(name="Precision",description=("Tolerence for comparing double keyframes (higher for greater accuracy)"),min=1, max=16,soft_min=1, soft_max=16,default=6.0)
+
+ use_metadata = BoolProperty(name="Use Metadata",default=True,options={'HIDDEN'})
+ use_include_particle_duplicates = BoolProperty(name="Include Particle Duplicates",default=True)
+
+def register():
+ bpy.utils.register_class(godot_export_manager)
+ bpy.utils.register_class(godot_node_list)
+ bpy.utils.register_class(godot_export_groups)
+ bpy.utils.register_class(add_export_group)
+ bpy.utils.register_class(del_export_group)
+ bpy.utils.register_class(export_all_groups)
+ bpy.utils.register_class(export_groups_autosave)
+ bpy.utils.register_class(export_group)
+ bpy.utils.register_class(add_objects_to_group)
+ bpy.utils.register_class(del_objects_from_group)
+ bpy.utils.register_class(select_group_objects)
+ bpy.utils.register_class(UI_List_Godot)
+
+ bpy.types.Scene.godot_export_groups = CollectionProperty(type=godot_export_groups)
+ bpy.types.Scene.godot_export_groups_index = IntProperty(default=0,min=0)
+
+def unregister():
+ bpy.utils.unregister_class(godot_export_manager)
+ bpy.utils.unregister_class(godot_node_list)
+ bpy.utils.unregister_class(godot_export_groups)
+ bpy.utils.unregister_class(export_groups_autosave)
+ bpy.utils.unregister_class(add_export_group)
+ bpy.utils.unregister_class(del_export_group)
+ bpy.utils.unregister_class(export_all_groups)
+ bpy.utils.unregister_class(export_group)
+ bpy.utils.unregister_class(add_objects_to_group)
+ bpy.utils.unregister_class(del_objects_from_group)
+ bpy.utils.unregister_class(select_group_objects)
+ bpy.utils.unregister_class(UI_List_Godot)
+
+@persistent
+def auto_export(dummy):
+ bpy.ops.scene.godot_export_groups_autosave()
+
+bpy.app.handlers.save_post.append(auto_export)
+
+if __name__ == "__main__":
+ register()
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py index 7899098e3d..020ab6ca08 100644 --- a/tools/export/blender25/io_scene_dae/export_dae.py +++ b/tools/export/blender25/io_scene_dae/export_dae.py @@ -94,8 +94,6 @@ def strarr(arr): s+=" " return s - - class DaeExporter: def validate_id(self,d): @@ -132,10 +130,10 @@ class DaeExporter: tup = tup + (self.tangent.x,self.tangent.y,self.tangent.z) if (self.bitangent!=None): tup = tup + (self.bitangent.x,self.bitangent.y,self.bitangent.z) - #for t in self.bones: - # tup = tup + (t) - #for t in self.weights: - # tup = tup + (t) + for t in self.bones: + tup = tup + (float(t),) + for t in self.weights: + tup = tup + (float(t),) return tup @@ -162,33 +160,64 @@ class DaeExporter: def export_image(self,image): - if (image in self.image_cache): return self.image_cache[image] - + imgpath = image.filepath if (imgpath.find("//")==0 or imgpath.find("\\\\")==0): #if relative, convert to absolute imgpath = bpy.path.abspath(imgpath) #path is absolute, now do something! - + if (self.config["use_copy_images"]): #copy image basedir = os.path.dirname(self.path)+"/images" if (not os.path.isdir(basedir)): os.makedirs(basedir) - dstfile=basedir+"/"+os.path.basename(imgpath) - if (not os.path.isfile(dstfile)): - shutil.copy(imgpath,dstfile) - imgpath="images/"+os.path.basename(imgpath) + + if os.path.isfile(imgpath): + dstfile=basedir+"/"+os.path.basename(imgpath) + + if (not os.path.isfile(dstfile)): + shutil.copy(imgpath,dstfile) + imgpath="images/"+os.path.basename(imgpath) + else: + ### if file is not found save it as png file in the destination folder + img_tmp_path = image.filepath + if img_tmp_path.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")): + image.filepath = basedir+"/"+os.path.basename(img_tmp_path) + else: + image.filepath = basedir+"/"+image.name+".png" + + dstfile=basedir+"/"+os.path.basename(image.filepath) + + if (not os.path.isfile(dstfile)): + + image.save() + imgpath="images/"+os.path.basename(image.filepath) + image.filepath = img_tmp_path else: #export relative, always, no one wants absolute paths. - imgpath = os.path.relpath(imgpath,os.path.dirname(self.path)).replace("\\","/") # export unix compatible always - + try: + imgpath = os.path.relpath(imgpath,os.path.dirname(self.path)).replace("\\","/") # export unix compatible always + + except: + pass #fails sometimes, not sure why + imgid = self.new_id("image") + + print("FOR: "+imgpath) + +# if (not os.path.isfile(imgpath)): +# print("NOT FILE?") +# if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")): +# imgpath="images/"+os.path.basename(imgpath) +# else: +# imgpath="images/"+image.name+".png" + self.writel(S_IMGS,1,'<image id="'+imgid+'" name="'+image.name+'">') self.writel(S_IMGS,2,'<init_from>'+imgpath+'</init_from>"/>') self.writel(S_IMGS,1,'</image>') @@ -331,7 +360,7 @@ class DaeExporter: return matid - def export_mesh(self,node,armature=None,skeyindex=-1,skel_source=None): + def export_mesh(self,node,armature=None,skeyindex=-1,skel_source=None,custom_name=None): mesh = node.data @@ -368,9 +397,9 @@ class DaeExporter: # self.export_node(node,il,shape.name) node.data.update() if (armature and k==0): - md=self.export_mesh(node,armature,k,mid) + md=self.export_mesh(node,armature,k,mid,shape.name) else: - md=self.export_mesh(node,None,k) + md=self.export_mesh(node,None,k,None,shape.name) node.data = p node.data.update() @@ -484,10 +513,18 @@ class DaeExporter: mat_assign=[] uv_layer_count=len(mesh.uv_textures) - if (len(mesh.uv_textures)): - mesh.calc_tangents() + if (has_tangents and len(mesh.uv_textures)): + try: + mesh.calc_tangents() + except: + self.operator.report({'WARNING'},'CalcTangets failed for mesh "'+mesh.name+'", no tangets will be exported.') + #uv_layer_count=0 + mesh.calc_normals_split() + has_tangents=False + else: mesh.calc_normals_split() + has_tangents=False for fi in range(len(mesh.polygons)): @@ -495,8 +532,8 @@ class DaeExporter: if (not (f.material_index in surface_indices)): surface_indices[f.material_index]=[] - print("Type: "+str(type(f.material_index))) - print("IDX: "+str(f.material_index)+"/"+str(len(mesh.materials))) + #print("Type: "+str(type(f.material_index))) + #print("IDX: "+str(f.material_index)+"/"+str(len(mesh.materials))) try: #Bizarre blender behavior i don't understand, so catching exception @@ -555,16 +592,30 @@ class DaeExporter: if (armature!=None): wsum=0.0 + zero_bones=[] + for vg in mv.groups: if vg.group >= len(node.vertex_groups): continue; name = node.vertex_groups[vg.group].name + if (name in si["bone_index"]): #could still put the weight as 0.0001 maybe if (vg.weight>0.001): #blender has a lot of zero weight stuff v.bones.append(si["bone_index"][name]) v.weights.append(vg.weight) wsum+=vg.weight + if (wsum==0.0): + if not self.wrongvtx_report: + self.operator.report({'WARNING'},'Mesh for object "'+node.name+'" has unassigned weights. This may look wrong in exported model.') + self.wrongvtx_report=True + + #blender can have bones assigned that weight zero so they remain local + #this is the best it can be done? + v.bones.append(0) + v.weights.append(1) + + tup = v.get_tup() @@ -584,7 +635,10 @@ class DaeExporter: meshid = self.new_id("mesh") - self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">') + if (custom_name!=None): + self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+custom_name+'">') + else: + self.writel(S_GEOM,1,'<geometry id="'+meshid+'" name="'+mesh.name+'">') self.writel(S_GEOM,2,'<mesh>') @@ -850,6 +904,29 @@ class DaeExporter: if (node.parent!=None): if (node.parent.type=="ARMATURE"): armature=node.parent + armcount=0 + for n in node.modifiers: + if (n.type=="ARMATURE"): + armcount+=1 + if (armcount>1): + self.operator.report({'WARNING'},'Object "'+node.name+'" refers to more than one armature! This is unsopported.') + + + + + if (node.data.shape_keys!=None): + sk = node.data.shape_keys + if (sk.animation_data): + #print("HAS ANIM") + #print("DRIVERS: "+str(len(sk.animation_data.drivers))) + for d in sk.animation_data.drivers: + if (d.driver): + for v in d.driver.variables: + for t in v.targets: + if (t.id!=None and t.id.name in self.scene.objects): + #print("LINKING "+str(node)+" WITH "+str(t.id.name)) + self.armature_for_morph[node]=self.scene.objects[t.id.name] + meshdata = self.export_mesh(node,armature) close_controller=False @@ -887,6 +964,12 @@ class DaeExporter: boneidx = si["bone_count"] si["bone_count"]+=1 bonesid = si["id"]+"-"+str(boneidx) + if (bone.name in self.used_bones): + if (self.config["use_anim_action_all"]): + self.operator.report({'WARNING'},'Bone name "'+bone.name+'" used in more than one skeleton. Actions might export wrong.') + else: + self.used_bones.append(bone.name) + si["bone_index"][bone.name]=boneidx si["bone_ids"][bone]=boneid si["bone_names"].append(bonesid) @@ -949,12 +1032,12 @@ class DaeExporter: self.writel(S_CAMS,5,'<zfar> '+str(camera.clip_end)+' </zfar>') self.writel(S_CAMS,4,'</perspective>') else: - self.writel(S_CAMS,4,'<orthografic>') - self.writel(S_CAMS,5,'<xmag> '+str(camera.ortho_scale)+' </xmag>') # I think? + self.writel(S_CAMS,4,'<orthographic>') + self.writel(S_CAMS,5,'<xmag> '+str(camera.ortho_scale*0.5)+' </xmag>') # I think? self.writel(S_CAMS,5,'<aspect_ratio> '+str(self.scene.render.resolution_x / self.scene.render.resolution_y)+' </aspect_ratio>') self.writel(S_CAMS,5,'<znear> '+str(camera.clip_start)+' </znear>') self.writel(S_CAMS,5,'<zfar> '+str(camera.clip_end)+' </zfar>') - self.writel(S_CAMS,4,'</orthografic>') + self.writel(S_CAMS,4,'</orthographic>') self.writel(S_CAMS,3,'</technique_common>') self.writel(S_CAMS,2,'</optics>') @@ -1145,15 +1228,16 @@ class DaeExporter: def export_node(self,node,il): - if (not self.is_node_valid(node)): + if (not node in self.valid_nodes): return + prev_node = bpy.context.scene.objects.active bpy.context.scene.objects.active = node self.writel(S_NODES,il,'<node id="'+self.validate_id(node.name)+'" name="'+node.name+'" type="NODE">') il+=1 self.writel(S_NODES,il,'<matrix sid="transform">'+strmtx(node.matrix_local)+'</matrix>') - print("NODE TYPE: "+node.type+" NAME: "+node.name) + #print("NODE TYPE: "+node.type+" NAME: "+node.name) if (node.type=="MESH"): self.export_mesh_node(node,il) elif (node.type=="CURVE"): @@ -1165,18 +1249,19 @@ class DaeExporter: elif (node.type=="LAMP"): self.export_lamp_node(node,il) - self.valid_nodes.append(node) for x in node.children: self.export_node(x,il) il-=1 self.writel(S_NODES,il,'</node>') + bpy.context.scene.objects.active = prev_node #make previous node active again def is_node_valid(self,node): if (not node.type in self.config["object_types"]): return False if (self.config["use_active_layers"]): valid=False + #print("NAME: "+node.name) for i in range(20): if (node.layers[i] and self.scene.layers[i]): valid=True @@ -1196,8 +1281,21 @@ class DaeExporter: self.writel(S_NODES,0,'<library_visual_scenes>') self.writel(S_NODES,1,'<visual_scene id="'+self.scene_name+'" name="scene">') + #validate nodes + for obj in self.scene.objects: + if (obj in self.valid_nodes): + continue + if (self.is_node_valid(obj)): + n = obj + while (n!=None): + if (not n in self.valid_nodes): + self.valid_nodes.append(n) + n=n.parent + + + for obj in self.scene.objects: - if (obj.parent==None): + if (obj in self.valid_nodes and obj.parent==None): self.export_node(obj,2) self.writel(S_NODES,1,'</visual_scene>') @@ -1313,7 +1411,7 @@ class DaeExporter: # Change frames first, export objects last # This improves performance enormously - print("anim from: "+str(start)+" to "+str(end)+" allowed: "+str(allowed)) + #print("anim from: "+str(start)+" to "+str(end)+" allowed: "+str(allowed)) for t in range(start,end+1): self.scene.frame_set(t) key = t * frame_len - frame_sub @@ -1327,6 +1425,7 @@ class DaeExporter: if (node.type=="MESH" and node.data!=None and (node in self.armature_for_morph) and (self.armature_for_morph[node] in allowed)): pass #all good you pass with flying colors for morphs inside of action else: + #print("fail "+str((node in self.armature_for_morph))) continue if (node.type=="MESH" and node.data!=None and node.data.shape_keys!=None and (node.data in self.mesh_cache) and len(node.data.shape_keys.key_blocks)): target = self.mesh_cache[node.data]["morph_id"] @@ -1366,7 +1465,7 @@ class DaeExporter: bone_name=self.skeleton_info[node]["bone_ids"][bone] if (not (bone_name in xform_cache)): - print("has bone: "+bone_name) + #print("has bone: "+bone_name) xform_cache[bone_name]=[] posebone = node.pose.bones[bone.name] @@ -1398,11 +1497,17 @@ class DaeExporter: return tcn def export_animations(self): - + tmp_mat = [] + for s in self.skeletons: + tmp_bone_mat = [] + for bone in s.pose.bones: + tmp_bone_mat.append(Matrix(bone.matrix_basis)) + bone.matrix_basis = Matrix() + tmp_mat.append([Matrix(s.matrix_local),tmp_bone_mat]) + self.writel(S_ANIM,0,'<library_animations>') - if (self.config["use_anim_action_all"] and len(self.skeletons)): cached_actions = {} @@ -1433,41 +1538,55 @@ class DaeExporter: bones.append(dp) allowed_skeletons=[] - for y in self.skeletons: + for i,y in enumerate(self.skeletons): if (y.animation_data): for z in y.pose.bones: if (z.bone.name in bones): if (not y in allowed_skeletons): allowed_skeletons.append(y) y.animation_data.action=x; + + y.matrix_local = tmp_mat[i][0] + for j,bone in enumerate(s.pose.bones): + bone.matrix_basis = Matrix() + + #print("allowed skeletons "+str(allowed_skeletons)) + #print(str(x)) - print(str(x)) - - tcn = self.export_animation(int(x.frame_range[0]),int(x.frame_range[1]),allowed_skeletons) + tcn = self.export_animation(int(x.frame_range[0]),int(x.frame_range[1]+0.5),allowed_skeletons) framelen=(1.0/self.scene.render.fps) start = x.frame_range[0]*framelen end = x.frame_range[1]*framelen - print("Export anim: "+x.name) + #print("Export anim: "+x.name) self.writel(S_ANIM_CLIPS,1,'<animation_clip name="'+x.name+'" start="'+str(start)+'" end="'+str(end)+'">') for z in tcn: self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'"/>') self.writel(S_ANIM_CLIPS,1,'</animation_clip>') + if (len(tcn)==0): + self.operator.report({'WARNING'},'Animation clip "'+x.name+'" contains no tracks.') + self.writel(S_ANIM_CLIPS,0,'</library_animation_clips>') - for s in self.skeletons: + + for i,s in enumerate(self.skeletons): if (s.animation_data==None): continue if s in cached_actions: s.animation_data.action = bpy.data.actions[cached_actions[s]] else: s.animation_data.action = None + for j,bone in enumerate(s.pose.bones): + bone.matrix_basis = tmp_mat[i][1][j] + else: self.export_animation(self.scene.frame_start,self.scene.frame_end) - + + + self.writel(S_ANIM,0,'</library_animations>') def export(self): @@ -1533,7 +1652,8 @@ class DaeExporter: f.write(bytes('</COLLADA>\n',"UTF-8")) return True - def __init__(self,path,kwargs): + def __init__(self,path,kwargs,operator): + self.operator=operator self.scene=bpy.context.scene self.last_id=0 self.scene_name=self.new_id("scene") @@ -1547,6 +1667,11 @@ class DaeExporter: self.config=kwargs self.valid_nodes=[] self.armature_for_morph={} + self.used_bones=[] + self.wrongvtx_report=False + + + @@ -1557,9 +1682,11 @@ def save(operator, context, **kwargs ): - exp = DaeExporter(filepath,kwargs) + exp = DaeExporter(filepath,kwargs,operator) exp.export() + + return {'FINISHED'} # so the script wont run after we have batch exported. diff --git a/tools/script_plugins/time/time.gd b/tools/script_plugins/time/time.gd index 66b3e9ed04..2e56d89d4f 100644 --- a/tools/script_plugins/time/time.gd +++ b/tools/script_plugins/time/time.gd @@ -21,12 +21,12 @@ func _init(): timer.set_one_shot(false) timer.connect("timeout",self,"_timeout") -func _enter_scene(): +func _enter_tree(): label = Label.new() add_custom_control(CONTAINER_TOOLBAR,label) timer.start() -func _exit_scene(): +func _exit_tree(): timer.stop() label.free() label=null diff --git a/version.py b/version.py index 31257304f6..46490c48f4 100644 --- a/version.py +++ b/version.py @@ -1,8 +1,7 @@ short_name="godot" name="Godot Engine" major=1 -minor=0 -revision="$Rev: 3917 $" +minor=1 status="beta1" |